Skip to content

Commit b167dcb

Browse files
authored
add elm_ui and terminal_ui example targets (#143)
1 parent 06ff460 commit b167dcb

288 files changed

Lines changed: 10373 additions & 8951 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.spec/specs/examples/package.spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ decisions:
5555
stability: stable
5656
5757
- id: repo.examples.runtime_selection_boundary
58-
statement: Every example application shall compile authored screens through `unified_ui` into canonical `UnifiedIUR` and render through the runtime selected for the launch session, with `live_ui` as the default runtime when no command-line runtime argument or equivalent override is provided.
58+
statement: Every example application shall compile authored screens through `unified_ui` into canonical `UnifiedIUR` and render through the runtime selected for the launch session, with maintained launcher targets for `live_ui`, `desktop_ui`, `elm_ui`, and `terminal_ui`, and with `live_ui` as the default runtime when no command-line runtime argument or equivalent override is provided.
5959
priority: must
6060
stability: stable
6161

‎.spec/specs/examples/structure.spec.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ decisions:
4646
stability: stable
4747
4848
- id: repo.examples.structure.local_package_dependencies
49-
statement: Each example application shall depend on `packages/unified-ui` and `packages/unified_iur` through local path dependencies and may depend on one or more supported runtime packages required for its launch targets, but no focused example application shall require an `examples/shared/` path dependency.
49+
statement: Each example application shall depend on `packages/unified-ui` and `packages/unified_iur` through local path dependencies and shall include the supported runtime-package dependencies required for its maintained launch targets, including `live_ui`, `desktop_ui`, `elm_ui`, and `terminal_ui`, but no focused example application shall require an `examples/shared/` path dependency.
5050
priority: must
5151
stability: stable
5252

‎.spec/specs/examples/tooling.spec.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ decisions:
2626

2727
```spec-requirements
2828
- id: repo.examples.tooling.index_surface
29-
statement: The example suite shall provide a top-level index under `examples/` that explains the common example-shell contract, the suite default theme/style baseline, the default runtime behavior, and the per-widget example-app catalog.
29+
statement: The example suite shall provide a top-level index under `examples/` that explains the common example-shell contract, the suite default theme/style baseline, the supported runtime targets, the default runtime behavior, and the per-widget example-app catalog.
3030
priority: must
3131
stability: stable
3232
@@ -36,12 +36,12 @@ decisions:
3636
stability: stable
3737
3838
- id: repo.examples.tooling.runtime_selection_surface
39-
statement: The suite shall provide a documented launch surface that accepts runtime selection through a command-line argument or equivalent override, and shall default to `live_ui` when no runtime is specified.
39+
statement: The suite shall provide a documented launch surface that accepts runtime selection through a command-line argument or equivalent override for `live_ui`, `desktop_ui`, `elm_ui`, and `terminal_ui`, shall default to `live_ui` when no runtime is specified, and may satisfy non-browser runtimes through review-oriented runtime output when a standalone launcher is not yet maintained.
4040
priority: must
4141
stability: stable
4242
4343
- id: repo.examples.tooling.shared_validation
44-
statement: The suite shall provide a repeatable validation workflow that checks whether each catalog entry still preserves the common example-shell contract, the suite default theme/style baseline, and the runtime-selection contract.
44+
statement: The suite shall provide a repeatable validation workflow that checks whether each catalog entry still preserves the common example-shell contract, the suite default theme/style baseline, and the documented runtime-selection contract.
4545
priority: must
4646
stability: stable
4747
@@ -62,7 +62,7 @@ decisions:
6262
- id: repo.examples.tooling.review_example_suite
6363
given: A maintainer wants to review the standalone example-app suite after adding or changing a widget
6464
when: The maintainer uses the suite index and validation workflow
65-
then: The maintainer can find the widget-focused app, run it independently, and verify that it still preserves the common example-shell contract, the suite default theme/style baseline, and the default runtime behavior
65+
then: The maintainer can find the widget-focused app, run it independently through the chosen maintained runtime target, and verify that it still preserves the common example-shell contract, the suite default theme/style baseline, and the default runtime behavior
6666
```
6767

6868
## Verification

‎AGENTS.md‎

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,23 @@ Start with the contract layer before changing code or docs:
1010

1111
1. `.spec/README.md`
1212
2. `.spec/AGENTS.md`
13-
3. `.spec/decisions/README.md`
14-
4. `.spec/specs/package.spec.md`
15-
5. `.spec/specs/architecture.spec.md`
16-
6. `.spec/specs/dsl_iur_symbiosis.spec.md`
17-
7. `.spec/specs/platform_runtimes.spec.md`
18-
8. `.spec/specs/signal_transport.spec.md`
19-
9. `.spec/specs/governance/governance_layer.spec.md`
20-
10. `.spec/specs/governance/contracts/workspace_governance_contract.spec.md`
13+
3. `.spec/conformance/README.md`
14+
4. `.spec/decisions/README.md`
15+
5. `.spec/specs/spec_system.spec.md`
16+
6. `.spec/specs/package.spec.md`
17+
7. `.spec/specs/architecture.spec.md`
18+
8. `.spec/specs/dsl_iur_symbiosis.spec.md`
19+
9. `.spec/specs/platform_runtimes.spec.md`
20+
10. `.spec/specs/signal_transport.spec.md`
21+
11. `.spec/specs/conformance_layer.spec.md`
22+
12. `.spec/specs/governance/governance_layer.spec.md`
23+
13. `.spec/specs/governance/contracts/workspace_governance_contract.spec.md`
2124

2225
Read the relevant package specs under `.spec/specs/` before editing a package.
26+
If you are changing `packages/unified-ui`, also read
27+
`.spec/specs/governance/contracts/unified_ui_change_contract.spec.md`.
28+
If you are changing `packages/unified_iur`, also read
29+
`.spec/specs/governance/contracts/unified_iur_change_contract.spec.md`.
2330
If the change is durable and cross-cutting, also read the matching ADRs under
2431
`.spec/decisions/`.
2532

@@ -37,16 +44,24 @@ If the change is durable and cross-cutting, also read the matching ADRs under
3744

3845
The `.spec/` workspace is the current-truth contract layer for this repository.
3946

47+
- `.spec/specs/spec_system.spec.md` defines the contract for the `.spec`
48+
workspace itself
4049
- `.spec/specs/**/*.spec.md` are the canonical authored subjects
4150
- `.spec/specs/governance/` contains repository-wide governance contracts
51+
- `.spec/specs/conformance_layer.spec.md` defines the separate conformance
52+
layer
4253
- `.spec/decisions/**/*.md` contains durable ADR rationale
43-
- `.spec/conformance/` contains machine-readable implementation evidence
54+
- `.spec/conformance/*/manifest.json` contains machine-readable implementation
55+
evidence
4456
- `.spec/planning/*/spec-traceability.json` contains machine-readable plan
4557
coverage manifests
58+
- `.spec/planning/*/spec-traceability.md` contains generated review-facing plan
59+
coverage mirrors
60+
- `.spec/state.json` is generated by `mix spec.plan` and `mix spec.verify`
4661

4762
Governance and conformance are separate layers. Do not treat conformance
48-
manifests, planning mirrors, or branch-local notes as substitutes for authored
49-
spec subjects.
63+
manifests, generated planning mirrors, state output, or branch-local notes as
64+
substitutes for authored spec subjects.
5065

5166
## Core Architecture
5267

@@ -98,16 +113,29 @@ package, and several runtime libraries.
98113
When you change canonical package surfaces, the specs must move with the code in
99114
the same change set.
100115

101-
- Changes to canonical `unified_ui` DSL surface must update the affected
116+
- `unified_ui` surface changes are governed by
117+
`.spec/specs/governance/contracts/unified_ui_change_contract.spec.md`
118+
- `unified_iur` surface changes are governed by
119+
`.spec/specs/governance/contracts/unified_iur_change_contract.spec.md`
120+
- Changes to canonical `unified_ui` authored DSL surface for widgets, layouts,
121+
layering, styling, theming, or interaction binding must update the affected
102122
subjects under `.spec/specs/unified-ui/`
103-
- Changes to canonical `unified_iur` interchange surface must update the
123+
- Changes to canonical `unified_iur` interchange surface for widgets, layouts,
124+
layering, styling, theming, or interaction representation must update the
104125
affected subjects under `.spec/specs/unified-iur/`
105126
- Changes to canonical `unified_ui` widget, display-system, or theming surface
106127
intended for ecosystem-wide authoring must update the paired
107128
`.spec/specs/unified-iur/` subjects in the same change set
108129
- Changes to canonical `unified_iur` widget, display-system, or theming surface
109130
intended for ecosystem-wide authoring and rendering must update the paired
110131
`.spec/specs/unified-ui/` subjects in the same change set
132+
- `unified_ui` and `unified_iur` subjects must stay within the root ecosystem
133+
bounds defined by `.spec/specs/architecture.spec.md`,
134+
`.spec/specs/dsl_iur_symbiosis.spec.md`,
135+
`.spec/specs/platform_runtimes.spec.md`, and
136+
`.spec/specs/signal_transport.spec.md`
137+
- Runtime-library-native widget, runtime, styling, and local signal
138+
responsibilities must not be absorbed into `unified_ui` or `unified_iur`
111139
- Repository-wide governance changes belong under `.spec/specs/governance/`
112140
- Durable cross-cutting policy changes must add or update an ADR under
113141
`.spec/decisions/`
@@ -156,6 +184,10 @@ Repository root:
156184
- `mix spec.check`
157185
- `mix spec.diffcheck`
158186
- `mix spec.report`
187+
- `mix spec.plancheck <package>`
188+
- `mix spec.traceability.generate <package>`
189+
- `mix spec.compliance <package>`
190+
- `mix spec.compliance.ci`
159191

160192
Package-local commands:
161193

@@ -174,12 +206,15 @@ Package-local commands:
174206
- If you edit `.spec`, follow `.spec/AGENTS.md`
175207
- Prefer targeted package-local tests over broad repository-wide runs
176208
- When changing repository-wide or package-wide policy, update the subject specs
177-
first and ADRs second
209+
first, ADRs second, and conformance evidence separately
178210
- When changing canonical DSL or canonical IUR surface, expect coordinated
179-
changes across code, package specs, and possibly runtime rendering or
180-
transport subjects
211+
changes across code, package specs, paired canonical package subjects, and
212+
possibly runtime rendering or transport subjects
181213
- Conformance evidence lives under `.spec/conformance/`; do not embed that
182214
evidence into governance subjects
215+
- Do not hand-edit generated `.spec/state.json` or
216+
`.spec/planning/*/spec-traceability.md`; regenerate them through the Mix
217+
tasks that own them
183218
- Generated traceability mirrors are review aids, not the source of truth
184219
- Packages currently target Elixir `~> 1.19`; older runtimes will fail before
185220
compilation
@@ -189,10 +224,15 @@ Package-local commands:
189224
- `CLAUDE.md`
190225
- `.spec/README.md`
191226
- `.spec/AGENTS.md`
227+
- `.spec/conformance/README.md`
228+
- `.spec/specs/spec_system.spec.md`
192229
- `.spec/specs/package.spec.md`
193230
- `.spec/specs/architecture.spec.md`
194231
- `.spec/specs/dsl_iur_symbiosis.spec.md`
195232
- `.spec/specs/platform_runtimes.spec.md`
196233
- `.spec/specs/signal_transport.spec.md`
234+
- `.spec/specs/conformance_layer.spec.md`
197235
- `.spec/specs/governance/governance_layer.spec.md`
198236
- `.spec/specs/governance/contracts/workspace_governance_contract.spec.md`
237+
- `.spec/specs/governance/contracts/unified_ui_change_contract.spec.md`
238+
- `.spec/specs/governance/contracts/unified_iur_change_contract.spec.md`

‎examples/README.md‎

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,32 @@ detail.
2121

2222
## Layout
2323

24-
- `shared/`: the shared support library that owns the common dependency wiring,
25-
DSL template, catalog, runtime helpers, release checks, and maintainer tasks
24+
- `shared/`: maintainer tooling, catalog, validation, and release-readiness
25+
helpers that remain useful for suite-wide review workflows
2626
- one standalone app directory per implemented widget-focused example
2727

2828
Directory convention:
2929

3030
- every example app lives in `examples/<widget_name>/`
3131
- every example app is a standalone Phoenix LiveView app and Mix project
32-
- every example app depends on `examples/shared/` plus the local package paths
33-
for `unified_ui`, `unified_iur`, and `live_ui`
34-
- every example app reuses the shared template in
35-
`UnifiedExamples.Shared.Template`
32+
- focused example apps are self-contained and do not depend on
33+
`examples/shared/`
34+
- every focused example app depends on the local package paths for
35+
`unified_ui`, `unified_iur`, `live_ui`, `desktop_ui`, `elm_ui`, and
36+
`terminal_ui`
37+
- every focused example app can be started from its own directory and defaults
38+
to `live_ui` when no target package is specified
3639

3740
## Shared Baseline
3841

39-
The shared authoring template gives every example app the same review surface:
42+
The shared authoring baseline gives every example app the same review surface:
4043

4144
- shared `UnifiedUi` DSL shell macros: `example_panel/1` and
4245
`example_form_panel/1`
4346
- shared default theme id: `:example_suite_default`
4447
- shared default style profile keys: `:shell`, `:panel`, `:form_shell`,
4548
`:title`, `:summary`, `:notes`, `:button`, and `:text_input`
46-
- shared runtime flow through `examples/shared/` helpers rather than
47-
app-specific boot code
49+
- a common app-local launcher surface through `mix example.start`
4850
- one meaningful authored interaction story per example so reviewers can
4951
understand what to try in the browser and what outcome to expect without
5052
opening source files
@@ -71,8 +73,13 @@ demonstrating:
7173
- `unified_ui` owns the authored DSL template and compiler surface
7274
- `unified_iur` owns the canonical intermediate representation produced by that
7375
authored DSL
74-
- `live_ui` owns the runtime rendering path that mounts the resulting canonical
75-
screen under the shared theme and style baseline
76+
- `live_ui` is the default browser runtime target for the example suite
77+
- `desktop_ui` is the native desktop target currently wired into the app-local
78+
launcher surface
79+
- `elm_ui` is available through the same launcher as a review-oriented runtime
80+
snapshot of the Phoenix-and-Elm server/frontend path
81+
- `terminal_ui` is available through the same launcher as a review-oriented
82+
runtime snapshot of the terminal runtime path
7683

7784
The shared support library exposes traceability metadata for every app so
7885
reviewers can see the exact package roots, package specs, general ecosystem
@@ -84,9 +91,10 @@ Run these from `examples/shared/`:
8491

8592
- `mix examples.list`: print the current suite catalog
8693
- `mix examples.launch <directory> --dry-run`: print the standalone Phoenix
87-
launch command for one app
94+
launch command or runtime-review command for one app
8895
- `mix examples.launch <directory> --smoke-test`: boot one app through its
89-
Phoenix endpoint and verify the LiveView entrypoint responds
96+
Phoenix endpoint and verify the LiveView entrypoint responds for browser-
97+
runnable launch targets
9098
- `mix examples.preview <directory>`: inspect one app through the shared
9199
preview path
92100
- `mix examples.run <directory>`: run one app through its own test workflow
@@ -95,26 +103,66 @@ Run these from `examples/shared/`:
95103
- `mix examples.report`: print the cross-family review summary
96104
- `mix examples.release --strict`: run the full documentation, traceability,
97105
validation, and release-readiness workflow
98-
- `mix phx.server`: run from any `examples/<widget_name>/` directory to launch
99-
that example directly in the browser
106+
- `mix example.start`: run from any example app directory to launch that app,
107+
defaulting to `live_ui` and accepting `--target-package desktop_ui`,
108+
`--target-package elm_ui`, and `--target-package terminal_ui`
109+
- `mix phx.server`: still works directly from example app directories for the
110+
default `live_ui` browser path
100111

101112
Direct browser workflow for any example app:
102113

103114
```bash
104115
cd examples/button
105116
mix deps.get
106-
mix phx.server
117+
mix example.start
107118
```
108119

109120
The default mount URL is `http://127.0.0.1:5000/`, and you can override the
110-
port with `PORT=4100 mix phx.server`.
121+
port with `mix example.start --port 4100`.
122+
123+
Native desktop workflow for any focused example app:
124+
125+
```bash
126+
cd examples/button
127+
mix deps.get
128+
mix example.start --target-package desktop_ui
129+
```
130+
131+
ElmUi review workflow for any focused example app:
132+
133+
```bash
134+
cd examples/button
135+
mix deps.get
136+
mix example.start --target-package elm_ui
137+
```
138+
139+
This prints an `ElmUi` runtime snapshot to stdout for the compiled canonical
140+
example instead of launching the LiveView browser shell.
141+
142+
TerminalUi review workflow for any focused example app:
143+
144+
```bash
145+
cd examples/button
146+
mix deps.get
147+
mix example.start --target-package terminal_ui
148+
```
149+
150+
Use `--backend-mode tty` when you want the fallback terminal-capability path:
151+
152+
```bash
153+
cd examples/button
154+
mix example.start --target-package terminal_ui --backend-mode tty
155+
```
156+
157+
This prints a `TerminalUi` runtime snapshot to stdout for the compiled
158+
canonical example instead of launching a browser or SDL window.
111159

112160
Aggregate demo workflow:
113161

114162
```bash
115163
cd examples/demo
116164
mix deps.get
117-
mix phx.server
165+
mix example.start
118166
```
119167

120168
Or preview the demo launch contract from the shared tooling:
@@ -124,6 +172,14 @@ cd examples/shared
124172
mix examples.launch demo --dry-run
125173
```
126174

175+
You can also preview non-browser launch commands from the shared tooling:
176+
177+
```bash
178+
cd examples/shared
179+
mix examples.launch button --runtime elm_ui --dry-run
180+
mix examples.launch button --runtime terminal_ui --dry-run
181+
```
182+
127183
When you launch an example, look for two shared review surfaces in the browser:
128184

129185
- `Meaningful Interaction Story`: explains what changed in human terms

‎examples/alert_dialog/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ From this directory:
1111
`mix deps.get`
1212
`mix phx.server`
1313

14-
The app mounts at `http://127.0.0.1:4000/` by default. Override the port with
15-
`PORT=4100 mix phx.server`.
14+
The app mounts at `http://127.0.0.1:5000/` by default. Override the port with
15+
`PORT=5100 mix phx.server`.
1616

1717
## Try It
1818

‎examples/alert_dialog/lib/unified_examples/alert_dialog.ex‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ defmodule UnifiedExamples.AlertDialog do
33
Self-contained standalone example-app entrypoint for the focused example project.
44
"""
55

6-
@directory __MODULE__ |> Module.split() |> List.last() |> Macro.underscore() |> then(&"examples/#{&1}")
6+
@directory __MODULE__
7+
|> Module.split()
8+
|> List.last()
9+
|> Macro.underscore()
10+
|> then(&"examples/#{&1}")
711
@app @directory |> Path.basename() |> then(&String.to_atom("unified_example_#{&1}"))
812
@purpose :widget_proof
913

@@ -68,17 +72,17 @@ defmodule UnifiedExamples.AlertDialog do
6872

6973
@spec boot(keyword()) :: {:ok, LiveUi.Runtime.State.t()} | {:error, term()}
7074
def boot(opts \\ []) do
71-
Runtime.mount(screen_module(), runtime_opts(opts))
75+
__MODULE__.Runtime.mount(screen_module(), runtime_opts(opts))
7276
end
7377

7478
@spec component_assigns(keyword()) :: {:ok, map()} | {:error, term()}
7579
def component_assigns(opts \\ []) do
76-
Runtime.component_assigns(screen_module(), runtime_opts(opts))
80+
__MODULE__.Runtime.component_assigns(screen_module(), runtime_opts(opts))
7781
end
7882

7983
@spec render_html(keyword()) :: {:ok, String.t()} | {:error, term()}
8084
def render_html(opts \\ []) do
81-
Runtime.render_html(screen_module(), runtime_opts(opts))
85+
__MODULE__.Runtime.render_html(screen_module(), runtime_opts(opts))
8286
end
8387

8488
@spec launch_path() :: String.t()

0 commit comments

Comments
 (0)