@milehimikey/em-portal 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,7 +14,9 @@ front and a way to navigate a system of several models, not a flat per-model sit
14
14
 
15
15
  ## Status
16
16
 
17
- **0.1.0 — read-only multi-model browser.** See [What 0.1.0 includes](#what-01-includes) below.
17
+ **0.2.0 — read-only multi-model browser + guided first read.** See
18
+ [What 0.1.0 includes](#what-01-includes) and [What 0.2.0 adds](#what-020-adds-the-guided-first-read)
19
+ below.
18
20
 
19
21
  ## Quickstart
20
22
 
@@ -25,9 +27,10 @@ npx em-portal build models/*/*.em -o site
25
27
 
26
28
  ```
27
29
  site/
28
- index.html # landing page: em status rollup (state up front)
30
+ index.html # landing page: em status rollup (state up front) + "First read" entry point
29
31
  <model-key>/
30
32
  index.html # model page: diagram + slice table
33
+ walkthrough.html # guided first read (0.2.0): teaches the notation on THIS model
31
34
  diagram.svg
32
35
  slices/
33
36
  <slice-key>.html # slice page: diagram, doc, driftSignal, PR link
@@ -146,14 +149,9 @@ em-portal.
146
149
  - Fully static, self-contained output; deterministic builds (same inputs -> byte-identical
147
150
  site, verified in `test/build.test.ts`); no LLM anywhere.
148
151
 
149
- **Deferred to 0.2.0** (MIL-174, "guided first read"): the onboarding/teaching layer — real
150
- click-driven interaction that annotates a first-time reader's own model as they encounter each
151
- element/pattern kind, rather than a glossary page. 0.1.0's pages are informative but not
152
- teaching-aware.
153
-
154
152
  **Deferred to 0.3.0** (MIL-175, "async review intake"): a "raise a question" affordance on a
155
- slice page, triaged into an `issue "..."` marker through the normal ratified path. 0.1.0 is
156
- read-only.
153
+ slice page, triaged into an `issue "..."` marker through the normal ratified path. The portal is
154
+ still read-only otherwise.
157
155
 
158
156
  **Also deferred / open, not yet built**:
159
157
  - A real GitHub Pages/bucket deploy workflow wired to a specific target repo — see
@@ -161,8 +159,55 @@ read-only.
161
159
  and tests, since it has no real event models of its own to publish.
162
160
  - Parallelizing the per-model `em export`/`em render` calls (they run sequentially today — see
163
161
  [Open questions](#open-questions)).
164
- - Any client-side JS (search, filtering, sort) pages are plain static HTML, same posture as
165
- `em catalog`.
162
+ - Any client-side JS beyond the walkthrough's own stepper (search, filtering, sort across the
163
+ slice table) — every other page is still plain static HTML, same posture as `em catalog`.
164
+
165
+ ## What 0.2.0 adds: the guided first read
166
+
167
+ **MIL-174.** A first-time, non-technical reader clicks "First read" — prominent on the landing
168
+ page (pointed at the first model given to `em-portal build`) and on every model page (pointed at
169
+ that model) — and gets a self-paced, Next/Prev walkthrough that teaches the notation using **the
170
+ team's own model as every example**, never a generic glossary:
171
+
172
+ 1. Time runs left to right — anchored to the model's own first slice.
173
+ 2. A real **event**, **command**, and **view/read model** from this model, each with its
174
+ definition and a color-keyed callout naming the actual element.
175
+ 3. **Personas & swimlanes** — this model's own declared personas and contexts.
176
+ 4. The **four slice patterns** (State Change, State View, Automation, Translation), each taught
177
+ on the first real slice of that pattern this model has — a pattern the model doesn't use yet
178
+ is still explained, but says so plainly ("this model has no Translation slice yet") instead of
179
+ pointing at nothing.
180
+ 5. The three **markers** (amber note = linked design doc, red issue = open question, teal
181
+ divergence = accepted deviation), each on a real marked-up element when this model has one.
182
+ 6. **Status & ratification** — the draft → reviewed → ready-to-implement → implemented lifecycle,
183
+ a real example of this model's own slice status, that a named human ratifies (`ratifiedBy`),
184
+ and a link to the landing page's status rollup as the "is this healthy" view.
185
+ 7. Where to go next: the slice table, a real slice page, the status rollup.
186
+
187
+ Every step is picked **deterministically at build time** from the model's own `em export` JSON
188
+ (first occurrence in model order — see `src/walkthroughSteps.ts`, unit-tested independently of any
189
+ HTML) and embedded in the generated page as a small JSON blob; a vanilla-JS stepper (no
190
+ dependency, inlined, no fetch of any other page) drives Next/Prev, the left/right arrow keys, a
191
+ numbered step nav, and a visible "Exit walkthrough" link/Escape key at every step. The step count
192
+ is always the same 14 regardless of what the model contains, so the progress indicator ("Step 4
193
+ of 14") never depends on how much of the model's own vocabulary happens to show up.
194
+
195
+ **Highlight mechanism** (verified against a real `em render` SVG, not assumed): `em`'s renderer
196
+ already tags every element's node group with `data-slice="<index>"` and embeds an
197
+ `<metadata id="em-slices">` block — the same mechanism `em watch --serve`'s own Review mode
198
+ storyboard uses to spotlight one slice at a time. The walkthrough inlines the model's own
199
+ `diagram.svg` directly into the page (not `<object>`-embedded, which isn't reliably
200
+ script-reachable from `file://`) and reuses that same `data-slice` attribute to dim every other
201
+ slice while a step is active — a real, intentional, already-load-bearing integration point, not a
202
+ new one invented for this feature.
203
+
204
+ There is deliberately **no per-element spotlight** inside the diagram: `em`'s SVG node ids come
205
+ from a model-wide, name-only slug (`makeId()` in the em repo), independent of `em export`'s own
206
+ stable `<sliceKey>/<kind>.<slug>` ref scheme and never published as a stable contract — relying on
207
+ it would mean treating an internal Graphviz `<title>` as an API. Single-element steps degrade
208
+ honestly instead: a color-keyed callout card (kind + name + a same-page link to the real element),
209
+ styled to match the diagram's own kind/marker colors, so it reads as the same visual language
210
+ rather than a second one.
166
211
 
167
212
  ## CI publish recipe
168
213
 
package/dist/build.js CHANGED
@@ -7,6 +7,7 @@
7
7
  // index.html landing page: em status rollup + model index
8
8
  // <model-key>/
9
9
  // index.html model page: diagram + slice table
10
+ // walkthrough.html guided first read (MIL-174) over this model
10
11
  // diagram.svg
11
12
  // slices/
12
13
  // <slice-key>.html slice page: diagram, doc, driftSignal, PR link
@@ -15,7 +16,7 @@
15
16
  // Every model gets its own output directory (mirroring `em catalog`'s
16
17
  // convention) so slice keys from different models can never collide, even
17
18
  // without a cross-file dedupe pass.
18
- import { mkdir, writeFile } from "node:fs/promises";
19
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
19
20
  import { basename, extname, join } from "node:path";
20
21
  import { emExportJson, emRenderModel, emRenderSlice, emStatusJson } from "./em/run.js";
21
22
  import { checkExportSchemaCompatible } from "./em/exportDoc.js";
@@ -26,6 +27,8 @@ import { dedupe, kebabSlug } from "./slug.js";
26
27
  import { renderIndexPage } from "./pages/index.js";
27
28
  import { renderModelPage } from "./pages/model.js";
28
29
  import { renderSlicePage } from "./pages/slice.js";
30
+ import { renderWalkthroughPage } from "./pages/walkthrough.js";
31
+ import { buildWalkthroughSteps } from "./walkthroughSteps.js";
29
32
  export async function buildPortal(files, opts) {
30
33
  const t0 = performance.now();
31
34
  if (files.length === 0)
@@ -90,6 +93,17 @@ export async function buildPortal(files, opts) {
90
93
  slices: sliceSummaries,
91
94
  });
92
95
  await writeFile(join(modelDir, "index.html"), modelPage, "utf8");
96
+ // MIL-174: the guided first read — built from the SAME diagram.svg just
97
+ // written to disk (read back rather than re-rendered, so this never
98
+ // shells out to `em` a second time for a file already sitting there).
99
+ const diagramSvgSource = await readFile(join(modelDir, diagramFile), "utf8");
100
+ const walkthroughPage = renderWalkthroughPage({
101
+ modelKey,
102
+ modelName: doc.model.name ?? modelKey,
103
+ steps: buildWalkthroughSteps(doc),
104
+ diagramSvgSource,
105
+ });
106
+ await writeFile(join(modelDir, "walkthrough.html"), walkthroughPage, "utf8");
93
107
  modelSummaries.push({
94
108
  key: modelKey,
95
109
  name: doc.model.name ?? modelKey,
package/dist/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ const program = new Command();
7
7
  program
8
8
  .name("em-portal")
9
9
  .description("Stakeholder-facing static portal for em event models")
10
- .version("0.1.0");
10
+ .version("0.2.0");
11
11
  program
12
12
  .command("build")
13
13
  .description("Build a static, read-only multi-model portal site from one or more .em model files")
@@ -53,6 +53,7 @@ const STYLE = `
53
53
  .permalink a { color: inherit; }
54
54
  code { background: #eee; padding: .05rem .3rem; border-radius: 3px; }
55
55
  footer { max-width: 1000px; margin: 0 auto; padding: 0 1.25rem 2rem; font-size: 12px; color: #7b8794; }
56
+ .first-read-cta { display: inline-block; margin: .5rem 0 1rem; padding: .5rem 1rem; border-radius: 6px; background: #1f2933; color: #fff; text-decoration: none; font-weight: 600; }
56
57
  `;
57
58
  /** `homeHref` is always relative to the page being built so the whole site
58
59
  * works opened straight off disk via `file://` or served from any subpath —
@@ -1 +1 @@
1
- {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/pages/html.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2EAA2E;AAC3E,2EAA2E;AAC3E,qEAAqE;AACrE,wEAAwE;AACxE,+DAA+D;AAE/D,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCb,CAAC;AAOF;;;;iDAIiD;AACjD,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,QAAgB,EAAE,QAAgB,EAAE,SAAkB,EAAE;IAC5F,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM;QAC7B,CAAC,CAAC,wBAAwB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;QACrI,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;WACjB,KAAK;;;qBAGK,UAAU,CAAC,QAAQ,CAAC,kBAAkB,SAAS;;EAElE,QAAQ;;;;;CAKT,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/pages/html.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,2EAA2E;AAC3E,2EAA2E;AAC3E,qEAAqE;AACrE,wEAAwE;AACxE,+DAA+D;AAE/D,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Cb,CAAC;AAOF;;;;iDAIiD;AACjD,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,QAAgB,EAAE,QAAgB,EAAE,SAAkB,EAAE;IAC5F,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM;QAC7B,CAAC,CAAC,wBAAwB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;QACrI,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;WACjB,KAAK;;;qBAGK,UAAU,CAAC,QAAQ,CAAC,kBAAkB,SAAS;;EAElE,QAAQ;;;;;CAKT,CAAC;AACF,CAAC"}
@@ -114,7 +114,12 @@ ${linkRows}
114
114
  </tbody>
115
115
  </table>`
116
116
  : "";
117
- const body = `${renderStatusSection(status)}
117
+ const firstReadHref = summary.models[0] ? `${escapeHtml(summary.models[0].key)}/walkthrough.html` : null;
118
+ const firstReadBanner = firstReadHref
119
+ ? ` <p><a class="first-read-cta" href="${firstReadHref}">First read: new here? Learn the notation on ${escapeHtml(summary.models[0].name)} &rarr;</a></p>`
120
+ : "";
121
+ const body = `${firstReadBanner}
122
+ ${renderStatusSection(status)}
118
123
  <h2>Models</h2>
119
124
  <table>
120
125
  <thead><tr><th>Model</th><th>Slices</th><th>Source</th></tr></thead>
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pages/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pages/index.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,7 @@ export function renderModelPage(args) {
41
41
  .join("\n");
42
42
  const body = ` <p><code>${escapeHtml(file)}</code></p>
43
43
  <h1>${escapeHtml(modelName)}</h1>
44
+ <p><a class="first-read-cta" href="walkthrough.html">First read: learn the notation on this model &rarr;</a></p>
44
45
  <div class="diagram-frame"><object class="diagram" type="image/svg+xml" data="${escapeHtml(diagramFile)}"></object></div>
45
46
  <p class="full-diagram-link"><a href="${escapeHtml(diagramFile)}">Open full diagram &rarr;</a></p>
46
47
  <table>
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/pages/model.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,sEAAsE;AACtE,0EAA0E;AAC1E,6EAA6E;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAE/C,2EAA2E;AAC3E,uEAAuE;AACvE,sEAAsE;AACtE,sEAAsE;AACtE,mCAAmC;AAEnC,MAAM,aAAa,GAAiC;IAClD,cAAc,EAAE,cAAc;IAC9B,YAAY,EAAE,YAAY;IAC1B,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;CAC7B,CAAC;AAEF,SAAS,WAAW,CAAC,MAAe,EAAE,MAAqB;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,mCAAmC,CAAC;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,oCAAoC,CAAC;IACzD,MAAM,GAAG,GAAG,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,OAAO,sBAAsB,GAAG,KAAK,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,KAAoB;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACxF,OAAO,sBAAsB,GAAG,KAAK,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;AAClE,CAAC;AAmBD,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;8BACjB,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;8BAC7C,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;cACpD,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;cAC/B,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;YAC3B,CACP;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,IAAI,GAAG,gBAAgB,UAAU,CAAC,IAAI,CAAC;UACrC,UAAU,CAAC,SAAS,CAAC;oFACqD,UAAU,CAAC,WAAW,CAAC;4CAC/D,UAAU,CAAC,WAAW,CAAC;;;;EAIjE,IAAI;;aAEO,CAAC;IAEZ,OAAO,MAAM,CAAC,GAAG,SAAS,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACtG,CAAC"}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/pages/model.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,sEAAsE;AACtE,0EAA0E;AAC1E,6EAA6E;AAE7E,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAE/C,2EAA2E;AAC3E,uEAAuE;AACvE,sEAAsE;AACtE,sEAAsE;AACtE,mCAAmC;AAEnC,MAAM,aAAa,GAAiC;IAClD,cAAc,EAAE,cAAc;IAC9B,YAAY,EAAE,YAAY;IAC1B,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,YAAY,EAAE,cAAc;CAC7B,CAAC;AAEF,SAAS,WAAW,CAAC,MAAe,EAAE,MAAqB;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,mCAAmC,CAAC;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,oCAAoC,CAAC;IACzD,MAAM,GAAG,GAAG,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,OAAO,sBAAsB,GAAG,KAAK,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;AACnE,CAAC;AAED,SAAS,UAAU,CAAC,KAAoB;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACxF,OAAO,sBAAsB,GAAG,KAAK,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC;AAClE,CAAC;AAmBD,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACtD,MAAM,IAAI,GAAG,MAAM;SAChB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC;8BACjB,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;8BAC7C,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;cACpD,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;cAC/B,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;YAC3B,CACP;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,IAAI,GAAG,gBAAgB,UAAU,CAAC,IAAI,CAAC;UACrC,UAAU,CAAC,SAAS,CAAC;;oFAEqD,UAAU,CAAC,WAAW,CAAC;4CAC/D,UAAU,CAAC,WAAW,CAAC;;;;EAIjE,IAAI;;aAEO,CAAC;IAEZ,OAAO,MAAM,CAAC,GAAG,SAAS,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACtG,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { WalkthroughStep } from "../walkthroughSteps.js";
2
+ export interface WalkthroughPageArgs {
3
+ modelKey: string;
4
+ modelName: string;
5
+ steps: WalkthroughStep[];
6
+ /** The model's own full `em render` diagram.svg, as raw file content —
7
+ * inlined into the page (not <object>-embedded) so the client-side
8
+ * spotlight script can reach its `data-slice` nodes. */
9
+ diagramSvgSource: string;
10
+ }
11
+ export declare function renderWalkthroughPage(args: WalkthroughPageArgs): string;
@@ -0,0 +1,325 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // MIL-174: the "guided first read" page — a self-paced Next/Prev walkthrough
3
+ // that teaches the notation using the team's own model as every example (see
4
+ // docs/decisions/mil-162-teachable-navigator.md's "guided first read"
5
+ // property). Every step's copy is built here from the structured picks
6
+ // src/walkthroughSteps.ts already made; this file only turns that into
7
+ // escaped HTML + the small inline JS stepper — no element/slice selection
8
+ // logic lives here.
9
+ //
10
+ // Highlight mechanism (verified against a real `em render` SVG, not
11
+ // assumed): `em`'s own renderer tags every element's node group with
12
+ // `data-slice="<sliceIndex>"` and embeds an `<metadata id="em-slices">`
13
+ // block (src/render/sliceOverlay.ts in the em repo) — the exact mechanism
14
+ // `em watch --serve`'s own Review mode storyboard uses to spotlight one
15
+ // slice at a time. That's a real, intentional, documented integration
16
+ // point, so this page reuses it at SLICE granularity: the model's own
17
+ // diagram.svg is inlined (not <object>-embedded — a cross-document
18
+ // <object> isn't reliably script-reachable from file://, and em's own
19
+ // viewer inlines for the same reason) and a `.wt-dim` class dims every
20
+ // `[data-slice]` node not matching the active step's slice.
21
+ //
22
+ // There is no equivalent per-ELEMENT hook: `em`'s SVG node ids come from
23
+ // `makeId(name)` (model/model.ts in the em repo) — a model-wide, name-only
24
+ // slug, deduped independently of `em export`'s own `<sliceKey>/<kind>.<slug>`
25
+ // ref scheme, and never surfaced as a stable public contract. Depending on
26
+ // it would mean parsing an internal Graphviz-emitted <title> as if it were
27
+ // an API. So single-element steps (a specific event/command/view, a single
28
+ // marked-up element) degrade honestly, per this ticket's own guidance: a
29
+ // color-keyed callout card (kind + name + a same-page link to the real
30
+ // element), not a fragile in-SVG spotlight — built from the same
31
+ // ElementExport-shaped data every other page already renders, just styled
32
+ // to match the diagram's own kind colors (src/emit/theme.ts /
33
+ // src/render/drawNotes.ts in the em repo) so it reads as "the same
34
+ // notation," not a second visual language.
35
+ import { escapeHtml, layout } from "./html.js";
36
+ const KIND_COLOR = {
37
+ ui: { fill: "#FFFFFF", stroke: "#9AA0A6" },
38
+ command: { fill: "#B8D0F5", stroke: "#2B6CB0" },
39
+ view: { fill: "#C6E7C6", stroke: "#2F855A" },
40
+ event: { fill: "#F6B26B", stroke: "#B7791F" },
41
+ automation: { fill: "#DBDBDB", stroke: "#5F6368" },
42
+ processor: { fill: "#DBDBDB", stroke: "#5F6368" },
43
+ saga: { fill: "#DBDBDB", stroke: "#5F6368" },
44
+ translation: { fill: "#DBDBDB", stroke: "#5F6368" },
45
+ };
46
+ const DEFAULT_KIND_COLOR = { fill: "#EEEEEE", stroke: "#9AA0A6" };
47
+ function kindColor(kind) {
48
+ return KIND_COLOR[kind] ?? DEFAULT_KIND_COLOR;
49
+ }
50
+ const MARKER_COLOR = {
51
+ note: { fill: "#F4C430", stroke: "#7A5200" },
52
+ issue: { fill: "#E53935", stroke: "#8B0000" },
53
+ divergence: { fill: "#26A69A", stroke: "#00695C" },
54
+ };
55
+ const MARKER_LABEL = {
56
+ note: "note",
57
+ issue: "issue",
58
+ divergence: "accepted divergence",
59
+ };
60
+ const MARKER_DEFINITION = {
61
+ note: "An amber folded corner marks a <strong>note</strong> — a linked design doc with more detail than fits on the diagram itself.",
62
+ issue: "A red folded corner marks an <strong>issue</strong> — an open question awaiting a ruling before this element's design is settled.",
63
+ divergence: "A teal folded corner marks a <strong>divergence</strong> — a reasoned, ratified deviation between the model and its implementation: already decided, not still open.",
64
+ };
65
+ const PATTERN_DEFINITION = {
66
+ "state-change": "A <strong>State Change</strong> slice is the classic write path: a UI issues a command, the system validates it, and — if accepted — records one or more events. <code>ui → command → event</code>.",
67
+ "state-view": "A <strong>State View</strong> slice is the classic read path: one or more events are replayed into a read model, which a UI then displays. <code>event → view → ui</code>.",
68
+ automation: "An <strong>Automation</strong> slice is the system reacting to its own events with no person in the loop — a processor watches a view (or events) and issues a command by itself.",
69
+ translation: "A <strong>Translation</strong> slice crosses a system or context boundary — adapting something external into a command, or pushing internal state out to another system.",
70
+ };
71
+ /** Every dynamic string this page inserts goes through escapeHtml; ref/slug
72
+ * values used inside an href are also escaped (they're safe URL characters
73
+ * by construction, but this file makes no exception for that). */
74
+ function elementCallout(pick, extra = "") {
75
+ const c = kindColor(pick.kind);
76
+ return `<div class="wt-callout" style="background:${c.fill};border-color:${c.stroke}">
77
+ <div class="wt-callout-head"><span class="wt-callout-kind">${escapeHtml(pick.kind)}</span><span class="wt-callout-name">${escapeHtml(pick.name)}</span></div>
78
+ <div class="wt-callout-slice">in <a href="slices/${escapeHtml(pick.sliceKey)}.html#${escapeHtml(pick.ref)}">${escapeHtml(pick.sliceName)}</a></div>
79
+ ${extra}
80
+ </div>`;
81
+ }
82
+ function flowChip(pick) {
83
+ const c = kindColor(pick.kind);
84
+ return `<span class="wt-chip" style="background:${c.fill};border-color:${c.stroke}"><span class="wt-chip-kind">${escapeHtml(pick.kind)}</span> ${escapeHtml(pick.name)}</span>`;
85
+ }
86
+ function renderIntro(step) {
87
+ const anchor = step.firstSlice
88
+ ? `<p>Your model's story starts with the <strong>${escapeHtml(step.firstSlice.name)}</strong> slice, spotlighted below — everything to its right happened later.</p>`
89
+ : `<p>This model doesn't have any slices yet — once it does, its story will read left to right here.</p>`;
90
+ return `<p>Time runs left to right. This whole picture is <strong>${escapeHtml(step.modelName)}</strong>'s business process, told as a timeline: earlier things happened on the left, later things on the right.</p>
91
+ ${anchor}`;
92
+ }
93
+ const ELEMENT_DEFINITION = {
94
+ event: "An <strong>event</strong> is a fact that already happened — always named in the past tense (“Order Placed,” not “Place Order”). Once recorded, an event is never deleted or edited; if something changes, a later event records that.",
95
+ command: "A <strong>command</strong> is an intention — someone or something asking for a change. Unlike an event, a command can be <strong>rejected</strong>: the system might refuse it (bad data, a broken rule, no permission).",
96
+ view: "A <strong>view</strong> (also called a read model) is what someone reads — a screen, a report, a dashboard. A view is always built by replaying events; it never stores a new fact of its own.",
97
+ };
98
+ function renderElement(step) {
99
+ const def = `<p>${ELEMENT_DEFINITION[step.kind]}</p>`;
100
+ if (!step.element) {
101
+ return `${def}<p>This model doesn't have a${step.kind === "event" ? "n" : ""} ${escapeHtml(step.kind)} yet.</p>`;
102
+ }
103
+ const fromLine = step.kind === "view" && step.fromNames && step.fromNames.length > 0
104
+ ? `<div class="wt-callout-slice">Built from: ${step.fromNames.map((n) => `<code>${escapeHtml(n)}</code>`).join(", ")}</div>`
105
+ : "";
106
+ return `${def}${elementCallout(step.element, fromLine)}`;
107
+ }
108
+ function renderSwimlanes(step) {
109
+ return `<p>Across the top of the diagram are <strong>persona</strong> rows — who acts: ${step.personas.map((p) => `<code>${escapeHtml(p)}</code>`).join(", ")}.</p>
110
+ <p>Below those are rows for each part of the system that records something — ${step.contexts.map((c) => `<code>${escapeHtml(c)}</code>`).join(", ")}.</p>
111
+ <p>Reading a diagram is reading down a column — what happened, all at once, across every row — as much as it's reading left to right.</p>`;
112
+ }
113
+ function renderPattern(step) {
114
+ const def = `<p>${PATTERN_DEFINITION[step.pattern]}</p>`;
115
+ if (!step.found || !step.slice) {
116
+ return `${def}<p>This model has no ${escapeHtml(step.patternLabel)} slice yet — you'll recognize the shape once one exists.</p>`;
117
+ }
118
+ const flow = step.elements.map(flowChip).join(' <span class="wt-arrow">→</span> ');
119
+ return `${def}<p>A real example from your model: the <strong>${escapeHtml(step.slice.name)}</strong> slice.</p>
120
+ <div class="wt-flow">${flow}</div>
121
+ <p><a href="slices/${escapeHtml(step.slice.key)}.html">Open this slice &rarr;</a></p>`;
122
+ }
123
+ function renderMarker(step) {
124
+ const def = `<p>${MARKER_DEFINITION[step.marker]}</p>`;
125
+ if (!step.found || !step.element) {
126
+ return `${def}<p>This model has no ${escapeHtml(MARKER_LABEL[step.marker])} yet.</p>`;
127
+ }
128
+ const c = MARKER_COLOR[step.marker];
129
+ const textHtml = step.text
130
+ ? `<div class="wt-callout-slice">${escapeHtml(step.text)}</div>`
131
+ : "";
132
+ const callout = `<div class="wt-callout" style="background:${c.fill};border-color:${c.stroke}">
133
+ <div class="wt-callout-head"><span class="wt-callout-kind">${escapeHtml(step.element.kind)}</span><span class="wt-callout-name">${escapeHtml(step.element.name)}</span></div>
134
+ <div class="wt-callout-slice">in <a href="slices/${escapeHtml(step.element.sliceKey)}.html#${escapeHtml(step.element.ref)}">${escapeHtml(step.element.sliceName)}</a></div>
135
+ ${textHtml}
136
+ </div>`;
137
+ return `${def}${callout}`;
138
+ }
139
+ function statusBadgeClass(status) {
140
+ return status === "implemented" ? "ok" : "";
141
+ }
142
+ function renderStatus(step) {
143
+ const lifecycle = `<p>Every slice doc moves through a lifecycle: <strong>draft</strong> &rarr; <strong>reviewed</strong> &rarr; <strong>ready-to-implement</strong> &rarr; <strong>implemented</strong>.</p>`;
144
+ const example = step.exampleStatus
145
+ ? `<p>For example, your <strong>${escapeHtml(step.exampleStatus.sliceName)}</strong> slice is currently <span class="badge ${statusBadgeClass(step.exampleStatus.status)}">${escapeHtml(step.exampleStatus.status)}</span>.</p>`
146
+ : `<p>This model's slices don't have a recorded status yet — routine for an early model, not a defect.</p>`;
147
+ const ratify = `<p>A named human <strong>ratifies</strong> a slice doc — signs off that its current status is correct.</p>`;
148
+ const ratifyExample = step.exampleRatified
149
+ ? `<p><strong>${escapeHtml(step.exampleRatified.sliceName)}</strong> was ratified by <strong>${escapeHtml(step.exampleRatified.ratifiedBy)}</strong>${step.exampleRatified.ratifiedOn ? ` on ${escapeHtml(step.exampleRatified.ratifiedOn)}` : ""}.</p>`
150
+ : `<p>None of this model's slices have been ratified yet — also routine early on.</p>`;
151
+ const rollup = `<p>The landing page's status rollup is the “is this healthy” view across every model — <a href="../index.html">see it</a>.</p>`;
152
+ return `${lifecycle}${example}${ratify}${ratifyExample}${rollup}`;
153
+ }
154
+ function renderNext(step, modelName) {
155
+ const links = [`<a class="wt-cta" href="index.html">Browse the slice table &rarr;</a>`];
156
+ if (step.firstSlice) {
157
+ links.push(`<a class="wt-cta" href="slices/${escapeHtml(step.firstSlice.key)}.html">Read a real slice: ${escapeHtml(step.firstSlice.name)} &rarr;</a>`);
158
+ }
159
+ links.push(`<a class="wt-cta" href="../index.html">Check system health &rarr;</a>`);
160
+ return `<p>That's the whole notation — four kinds of box, three kinds of marker. Everything else on this site is the same vocabulary, applied to the rest of <strong>${escapeHtml(modelName)}</strong>'s real slices.</p>
161
+ <div class="wt-next-links">${links.join("\n ")}</div>`;
162
+ }
163
+ function renderStepBody(step, modelName) {
164
+ switch (step.kind) {
165
+ case "intro":
166
+ return renderIntro(step);
167
+ case "event":
168
+ case "command":
169
+ case "view":
170
+ return renderElement(step);
171
+ case "swimlanes":
172
+ return renderSwimlanes(step);
173
+ case "pattern":
174
+ return renderPattern(step);
175
+ case "marker":
176
+ return renderMarker(step);
177
+ case "status":
178
+ return renderStatus(step);
179
+ case "next":
180
+ return renderNext(step, modelName);
181
+ }
182
+ }
183
+ /** Strips the XML/DOCTYPE preamble and any comments graphviz puts before its
184
+ * `<svg ...>` root (verified against a real `em render` output: `<?xml ...?>`
185
+ * + a `<!DOCTYPE svg ...>` block, neither of which is legal inside an HTML
186
+ * document body), keeping the `<svg>...</svg>` element itself — the part
187
+ * that carries the `data-slice` attributes and `em-slices` metadata this
188
+ * page's spotlight needs. Falls back to the raw source if the expected
189
+ * `<svg`/`</svg>` markers aren't found, rather than throwing — a
190
+ * malformed-looking diagram beats a failed build. */
191
+ function extractInlineSvg(svgSource) {
192
+ const start = svgSource.indexOf("<svg");
193
+ const end = svgSource.lastIndexOf("</svg>");
194
+ if (start === -1 || end === -1)
195
+ return svgSource;
196
+ return svgSource.slice(start, end + "</svg>".length).replace("<svg", '<svg id="wt-diagram"');
197
+ }
198
+ const WALKTHROUGH_STYLE = `
199
+ .wt-nav { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; margin: 1rem 0; }
200
+ .wt-nav button { font: inherit; padding: .5rem 1rem; border-radius: 6px; border: 1px solid #ccc; background: #fff; cursor: pointer; }
201
+ .wt-nav button:disabled { opacity: .4; cursor: default; }
202
+ .wt-nav button.wt-primary { background: #1f2933; color: #fff; border-color: #1f2933; }
203
+ .wt-nav a.wt-exit { margin-left: auto; font-size: 13px; }
204
+ .wt-dots { display: flex; flex-wrap: wrap; gap: .35rem; margin: 0 0 1rem; padding: 0; }
205
+ .wt-dots button { width: 1.6rem; height: 1.6rem; border-radius: 50%; border: 1px solid #ccc; background: #fff; font-size: 11px; cursor: pointer; padding: 0; }
206
+ .wt-dots button[aria-current="step"] { background: #1f2933; color: #fff; border-color: #1f2933; }
207
+ .wt-diagram-frame { position: relative; overflow: auto; }
208
+ .wt-diagram-frame svg [data-slice] { transition: opacity .15s ease; }
209
+ .wt-diagram-frame svg [data-slice].wt-dim { opacity: .15; }
210
+ @media (prefers-reduced-motion: reduce) {
211
+ .wt-diagram-frame svg [data-slice] { transition: none; }
212
+ }
213
+ .wt-panels { margin-top: 1rem; }
214
+ .wt-step h2 { margin-top: 0; }
215
+ .wt-callout { border: 2px solid; border-radius: 8px; padding: .6rem .8rem; margin: .75rem 0; max-width: 28rem; }
216
+ .wt-callout-head { display: flex; gap: .5rem; align-items: baseline; }
217
+ .wt-callout-kind { text-transform: uppercase; font-size: 11px; letter-spacing: .03em; font-weight: 700; color: #3f3f3f; }
218
+ .wt-callout-name { font-weight: 600; }
219
+ .wt-callout-slice { font-size: 13px; margin-top: .25rem; }
220
+ .wt-flow { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin: .75rem 0; }
221
+ .wt-chip { border: 1px solid; border-radius: 999px; padding: .15rem .6rem; font-size: 13px; }
222
+ .wt-chip-kind { font-size: 10px; text-transform: uppercase; color: #3f3f3f; }
223
+ .wt-arrow { color: #7b8794; }
224
+ .wt-next-links { display: flex; flex-direction: column; gap: .5rem; margin-top: 1rem; }
225
+ .wt-cta { display: inline-block; padding: .6rem .9rem; border-radius: 6px; background: #1f2933; color: #fff; text-decoration: none; width: fit-content; }
226
+ `;
227
+ function stepperScript(exitHref) {
228
+ // Vanilla JS, inlined, no external assets — the whole page must work
229
+ // opened straight off disk via file:// (no fetch of any other page). Reads
230
+ // the JSON blob (#wt-data) for navigation-only metadata (id/title/
231
+ // sliceIndex per step); every step's actual copy is already server-rendered
232
+ // markup in .wt-step panels, so the JSON is deliberately small.
233
+ return `(function () {
234
+ var data = JSON.parse(document.getElementById('wt-data').textContent);
235
+ var panels = Array.prototype.slice.call(document.querySelectorAll('.wt-step'));
236
+ var svg = document.getElementById('wt-diagram');
237
+ var progressEl = document.getElementById('wt-progress');
238
+ var prevBtn = document.getElementById('wt-prev');
239
+ var nextBtn = document.getElementById('wt-next');
240
+ var dots = Array.prototype.slice.call(document.querySelectorAll('#wt-dots button'));
241
+ var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
242
+ var idx = 0;
243
+
244
+ function applySpotlight(sliceIndex) {
245
+ if (!svg) return;
246
+ var nodes = svg.querySelectorAll('[data-slice]');
247
+ for (var i = 0; i < nodes.length; i++) {
248
+ var dim = sliceIndex !== null && nodes[i].getAttribute('data-slice') !== String(sliceIndex);
249
+ nodes[i].classList.toggle('wt-dim', dim);
250
+ }
251
+ if (sliceIndex !== null) {
252
+ var target = svg.querySelector('[data-slice="' + sliceIndex + '"]');
253
+ if (target && target.scrollIntoView) {
254
+ target.scrollIntoView({ behavior: reduceMotion ? 'auto' : 'smooth', block: 'nearest', inline: 'center' });
255
+ }
256
+ }
257
+ }
258
+
259
+ function render() {
260
+ for (var i = 0; i < panels.length; i++) panels[i].hidden = i !== idx;
261
+ if (progressEl) progressEl.textContent = 'Step ' + (idx + 1) + ' of ' + data.length + ': ' + data[idx].title;
262
+ if (prevBtn) prevBtn.disabled = idx === 0;
263
+ if (nextBtn) nextBtn.textContent = idx === data.length - 1 ? 'Finish' : 'Next \\u2192';
264
+ for (var d = 0; d < dots.length; d++) dots[d].setAttribute('aria-current', d === idx ? 'step' : 'false');
265
+ applySpotlight(data[idx].sliceIndex);
266
+ }
267
+
268
+ function go(n) {
269
+ idx = Math.max(0, Math.min(data.length - 1, n));
270
+ render();
271
+ }
272
+
273
+ if (prevBtn) prevBtn.addEventListener('click', function () { go(idx - 1); });
274
+ if (nextBtn) nextBtn.addEventListener('click', function () {
275
+ if (idx === data.length - 1) { window.location.href = ${JSON.stringify(exitHref)}; }
276
+ else { go(idx + 1); }
277
+ });
278
+ dots.forEach(function (btn, i) { btn.addEventListener('click', function () { go(i); }); });
279
+ document.addEventListener('keydown', function (e) {
280
+ if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
281
+ if (e.key === 'ArrowRight') go(idx + 1);
282
+ else if (e.key === 'ArrowLeft') go(idx - 1);
283
+ else if (e.key === 'Escape') window.location.href = ${JSON.stringify(exitHref)};
284
+ });
285
+
286
+ render();
287
+ })();`;
288
+ }
289
+ export function renderWalkthroughPage(args) {
290
+ const { modelName, steps } = args;
291
+ const inlineSvg = extractInlineSvg(args.diagramSvgSource);
292
+ const dotsHtml = steps
293
+ .map((_, i) => `<button type="button" data-step-index="${i}" aria-current="${i === 0 ? "step" : "false"}">${i + 1}</button>`)
294
+ .join("");
295
+ const panelsHtml = steps
296
+ .map((s, i) => ` <section class="wt-step" id="wt-step-${escapeHtml(s.id)}" ${i === 0 ? "" : "hidden"}>
297
+ <h2>${escapeHtml(s.title)}</h2>
298
+ ${renderStepBody(s, modelName)}
299
+ </section>`)
300
+ .join("\n");
301
+ // Navigation-only metadata for the client script — title/sliceIndex per
302
+ // step, nothing that duplicates the panel markup above.
303
+ const navData = steps.map((s) => ({ id: s.id, title: s.title, sliceIndex: s.sliceIndex }));
304
+ const body = ` <style>${WALKTHROUGH_STYLE}</style>
305
+ <p class="pattern">Guided first read &middot; ${escapeHtml(modelName)}</p>
306
+ <h1>First read: ${escapeHtml(modelName)}</h1>
307
+ <p id="wt-progress" class="pattern" aria-live="polite">Step 1 of ${steps.length}: ${escapeHtml(steps[0]?.title ?? "")}</p>
308
+ <div class="wt-nav">
309
+ <button id="wt-prev" type="button" disabled>&larr; Prev</button>
310
+ <button id="wt-next" type="button" class="wt-primary">Next &rarr;</button>
311
+ <a class="wt-exit" href="index.html">Exit walkthrough</a>
312
+ </div>
313
+ <nav class="wt-dots" id="wt-dots" aria-label="Steps">${dotsHtml}</nav>
314
+ <div class="diagram-frame wt-diagram-frame">${inlineSvg}</div>
315
+ <div class="wt-panels">
316
+ ${panelsHtml}
317
+ </div>
318
+ <script type="application/json" id="wt-data">${JSON.stringify(navData)}</script>
319
+ <script>${stepperScript("index.html")}</script>`;
320
+ return layout(`First read: ${modelName} — em portal`, body, "../index.html", [
321
+ { label: modelName, href: "index.html" },
322
+ { label: "First read", href: "." },
323
+ ]);
324
+ }
325
+ //# sourceMappingURL=walkthrough.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walkthrough.js","sourceRoot":"","sources":["../../src/pages/walkthrough.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ import { ExportDoc, SlicePattern } from "./em/exportDoc.js";
2
+ /** The four canonical patterns taught by the walkthrough, in the order
3
+ * they're introduced — "unclassified" (a slice em couldn't classify) is
4
+ * never one of them; it isn't a pattern a reader should learn as normal
5
+ * vocabulary. */
6
+ export declare const TAUGHT_PATTERNS: readonly SlicePattern[];
7
+ export declare const PATTERN_LABEL: Record<SlicePattern, string>;
8
+ export interface WalkthroughElementPick {
9
+ ref: string;
10
+ kind: string;
11
+ name: string;
12
+ sliceKey: string;
13
+ sliceName: string;
14
+ sliceIndex: number;
15
+ }
16
+ interface BaseStep {
17
+ id: string;
18
+ title: string;
19
+ /** Which slice (by `EmSlice.index`) the inline diagram should spotlight
20
+ * while this step is active, or `null` to show the whole diagram at full
21
+ * opacity — used for steps that aren't anchored to one slice (swimlanes,
22
+ * status, where-to-go-next). */
23
+ sliceIndex: number | null;
24
+ }
25
+ export interface IntroStep extends BaseStep {
26
+ kind: "intro";
27
+ modelName: string;
28
+ firstSlice: {
29
+ key: string;
30
+ name: string;
31
+ index: number;
32
+ } | null;
33
+ }
34
+ export interface ElementStep extends BaseStep {
35
+ kind: "event" | "command" | "view";
36
+ element: WalkthroughElementPick | null;
37
+ /** `view` only: the names this view's `from` clause cites, when present —
38
+ * "always built from events" is easier to believe pointing at the actual
39
+ * source name(s). */
40
+ fromNames: string[] | null;
41
+ }
42
+ export interface SwimlanesStep extends BaseStep {
43
+ kind: "swimlanes";
44
+ personas: string[];
45
+ contexts: string[];
46
+ }
47
+ export interface PatternStep extends BaseStep {
48
+ kind: "pattern";
49
+ pattern: SlicePattern;
50
+ patternLabel: string;
51
+ found: boolean;
52
+ slice: {
53
+ key: string;
54
+ name: string;
55
+ index: number;
56
+ } | null;
57
+ /** The matched slice's own elements, in declaration order, so the
58
+ * renderer can narrate its actual flow (e.g. ui -> command -> event) —
59
+ * empty when `found` is false. */
60
+ elements: WalkthroughElementPick[];
61
+ }
62
+ export type MarkerKind = "note" | "issue" | "divergence";
63
+ export interface MarkerStep extends BaseStep {
64
+ kind: "marker";
65
+ marker: MarkerKind;
66
+ found: boolean;
67
+ element: WalkthroughElementPick | null;
68
+ /** The marker's own text: the note's doc path, the issue's question, or
69
+ * the divergence's rationale. */
70
+ text: string | null;
71
+ }
72
+ export interface StatusStep extends BaseStep {
73
+ kind: "status";
74
+ exampleStatus: {
75
+ sliceKey: string;
76
+ sliceName: string;
77
+ status: string;
78
+ } | null;
79
+ exampleRatified: {
80
+ sliceKey: string;
81
+ sliceName: string;
82
+ ratifiedBy: string;
83
+ ratifiedOn: string | null;
84
+ } | null;
85
+ }
86
+ export interface NextStep extends BaseStep {
87
+ kind: "next";
88
+ firstSlice: {
89
+ key: string;
90
+ name: string;
91
+ } | null;
92
+ }
93
+ export type WalkthroughStep = IntroStep | ElementStep | SwimlanesStep | PatternStep | MarkerStep | StatusStep | NextStep;
94
+ /** Derives the full, ordered "guided first read" step sequence for one
95
+ * model — always the same 14 steps in the same order (intro, event,
96
+ * command, view, swimlanes, the 4 patterns, the 3 markers, status, next),
97
+ * regardless of what the model contains, so the progress indicator ("Step
98
+ * N of 14") never has to depend on how much of the model's own vocabulary
99
+ * actually shows up. What differs per model is only each step's content —
100
+ * which real element/slice it points at, or, honestly, that it has none
101
+ * yet. */
102
+ export declare function buildWalkthroughSteps(doc: ExportDoc): WalkthroughStep[];
103
+ export {};
@@ -0,0 +1,198 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // MIL-174: build-time derivation of the "guided first read" walkthrough's
3
+ // steps — a pure, deterministic function of one model's own `em export`
4
+ // document. This is deliberately separate from src/pages/walkthrough.ts
5
+ // (which turns these into HTML + the client-side stepper's JSON blob), the
6
+ // same split crossModel.ts (pure join) / pages/index.ts (HTML) already uses:
7
+ // keeps "which element did we pick, and why" unit-testable without a DOM or
8
+ // an HTML string to grep.
9
+ //
10
+ // Per docs/decisions/mil-162-teachable-navigator.md's "guided first read"
11
+ // property, every example the walkthrough teaches with is a REAL element
12
+ // from the team's own model, picked deterministically — first occurrence in
13
+ // model order (slice order, then element-declaration order within a slice),
14
+ // never randomly and never hardcoded copy. A model with no matching element
15
+ // (a pattern this model doesn't use, a marker kind it never sets, or a model
16
+ // with zero slices at all) degrades honestly: the step still appears (so the
17
+ // reader learns the full vocabulary and the progress count stays stable),
18
+ // but its body says so instead of pointing at nothing — never a broken
19
+ // reference, never a silently-vanished step.
20
+ /** The four canonical patterns taught by the walkthrough, in the order
21
+ * they're introduced — "unclassified" (a slice em couldn't classify) is
22
+ * never one of them; it isn't a pattern a reader should learn as normal
23
+ * vocabulary. */
24
+ export const TAUGHT_PATTERNS = ["state-change", "state-view", "automation", "translation"];
25
+ export const PATTERN_LABEL = {
26
+ "state-change": "State Change",
27
+ "state-view": "State View",
28
+ automation: "Automation",
29
+ translation: "Translation",
30
+ unclassified: "Unclassified",
31
+ };
32
+ function toPick(el, slice) {
33
+ return {
34
+ ref: el.ref,
35
+ kind: el.kind,
36
+ name: el.name,
37
+ sliceKey: slice.key,
38
+ sliceName: slice.name,
39
+ sliceIndex: slice.index,
40
+ };
41
+ }
42
+ /** First element of `kind` in model order (slice order, then declaration
43
+ * order within the slice) — the deterministic "pick a real example" rule
44
+ * every step in this module follows. `null` for a model with no element of
45
+ * that kind at all (including a model with zero slices). */
46
+ function firstElementOfKind(model, kind) {
47
+ for (const slice of model.slices) {
48
+ for (const el of slice.elements) {
49
+ if (el.kind === kind)
50
+ return { el, slice };
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ /** First slice (in model order) classified as `pattern`, or `null` if this
56
+ * model has none — the "skip patterns the model doesn't contain, saying
57
+ * so" case. */
58
+ function firstSliceOfPattern(model, pattern) {
59
+ return model.slices.find((s) => s.pattern === pattern) ?? null;
60
+ }
61
+ /** First element (model order) carrying a non-null value for `field`, or
62
+ * `null` if no element in this model sets that marker at all. */
63
+ function firstElementWithMarker(model, field) {
64
+ for (const slice of model.slices) {
65
+ for (const el of slice.elements) {
66
+ if (el[field])
67
+ return { el, slice };
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ function buildIntroStep(model) {
73
+ const first = model.slices[0] ?? null;
74
+ return {
75
+ id: "intro",
76
+ kind: "intro",
77
+ title: "Reading the picture",
78
+ sliceIndex: first?.index ?? null,
79
+ modelName: model.name ?? "this model",
80
+ firstSlice: first ? { key: first.key, name: first.name, index: first.index } : null,
81
+ };
82
+ }
83
+ function buildElementStep(model, kind) {
84
+ const found = firstElementOfKind(model, kind);
85
+ const titleByKind = {
86
+ event: "Event",
87
+ command: "Command",
88
+ view: "View / read model",
89
+ };
90
+ return {
91
+ id: kind,
92
+ kind,
93
+ title: titleByKind[kind],
94
+ sliceIndex: found?.slice.index ?? null,
95
+ element: found ? toPick(found.el, found.slice) : null,
96
+ fromNames: kind === "view" && found?.el.from ? found.el.from.map((f) => f.name) : null,
97
+ };
98
+ }
99
+ function buildSwimlanesStep(model) {
100
+ return {
101
+ id: "swimlanes",
102
+ kind: "swimlanes",
103
+ title: "Personas & swimlanes",
104
+ sliceIndex: null,
105
+ personas: model.personas,
106
+ contexts: model.contexts,
107
+ };
108
+ }
109
+ function buildPatternSteps(model) {
110
+ return TAUGHT_PATTERNS.map((pattern) => {
111
+ const slice = firstSliceOfPattern(model, pattern);
112
+ return {
113
+ id: `pattern-${pattern}`,
114
+ kind: "pattern",
115
+ title: `Pattern: ${PATTERN_LABEL[pattern]}`,
116
+ sliceIndex: slice?.index ?? null,
117
+ pattern,
118
+ patternLabel: PATTERN_LABEL[pattern],
119
+ found: slice !== null,
120
+ slice: slice ? { key: slice.key, name: slice.name, index: slice.index } : null,
121
+ elements: slice ? slice.elements.map((el) => toPick(el, slice)) : [],
122
+ };
123
+ });
124
+ }
125
+ function buildMarkerSteps(model) {
126
+ const markers = [
127
+ { marker: "note", field: "note", title: "Marker: linked design doc" },
128
+ { marker: "issue", field: "issue", title: "Marker: open question" },
129
+ { marker: "divergence", field: "divergence", title: "Marker: accepted divergence" },
130
+ ];
131
+ return markers.map(({ marker, field, title }) => {
132
+ const found = firstElementWithMarker(model, field);
133
+ return {
134
+ id: `marker-${marker}`,
135
+ kind: "marker",
136
+ title,
137
+ sliceIndex: found?.slice.index ?? null,
138
+ marker,
139
+ found: found !== null,
140
+ element: found ? toPick(found.el, found.slice) : null,
141
+ text: found ? found.el[field] : null,
142
+ };
143
+ });
144
+ }
145
+ function buildStatusStep(model) {
146
+ const withStatus = model.slices.find((s) => s.doc.found && s.doc.status);
147
+ const withRatification = model.slices.find((s) => s.doc.found && s.doc.ratifiedBy);
148
+ return {
149
+ id: "status",
150
+ kind: "status",
151
+ title: "Status & ratification",
152
+ sliceIndex: null,
153
+ exampleStatus: withStatus
154
+ ? { sliceKey: withStatus.key, sliceName: withStatus.name, status: withStatus.doc.status }
155
+ : null,
156
+ exampleRatified: withRatification
157
+ ? {
158
+ sliceKey: withRatification.key,
159
+ sliceName: withRatification.name,
160
+ ratifiedBy: withRatification.doc.ratifiedBy,
161
+ ratifiedOn: withRatification.doc.ratifiedOn,
162
+ }
163
+ : null,
164
+ };
165
+ }
166
+ function buildNextStep(model) {
167
+ const first = model.slices[0] ?? null;
168
+ return {
169
+ id: "next",
170
+ kind: "next",
171
+ title: "Where to go next",
172
+ sliceIndex: null,
173
+ firstSlice: first ? { key: first.key, name: first.name } : null,
174
+ };
175
+ }
176
+ /** Derives the full, ordered "guided first read" step sequence for one
177
+ * model — always the same 14 steps in the same order (intro, event,
178
+ * command, view, swimlanes, the 4 patterns, the 3 markers, status, next),
179
+ * regardless of what the model contains, so the progress indicator ("Step
180
+ * N of 14") never has to depend on how much of the model's own vocabulary
181
+ * actually shows up. What differs per model is only each step's content —
182
+ * which real element/slice it points at, or, honestly, that it has none
183
+ * yet. */
184
+ export function buildWalkthroughSteps(doc) {
185
+ const model = doc.model;
186
+ return [
187
+ buildIntroStep(model),
188
+ buildElementStep(model, "event"),
189
+ buildElementStep(model, "command"),
190
+ buildElementStep(model, "view"),
191
+ buildSwimlanesStep(model),
192
+ ...buildPatternSteps(model),
193
+ ...buildMarkerSteps(model),
194
+ buildStatusStep(model),
195
+ buildNextStep(model),
196
+ ];
197
+ }
198
+ //# sourceMappingURL=walkthroughSteps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walkthroughSteps.js","sourceRoot":"","sources":["../src/walkthroughSteps.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milehimikey/em-portal",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Stakeholder-facing static portal for em event models — a multi-model, read-only browser built from `em export`/`em status --json`",
5
5
  "type": "module",
6
6
  "bin": {