@milehimikey/em 1.7.1 → 1.8.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.
Files changed (112) hide show
  1. package/.claude/skills/event-modeling/SKILL.md +92 -65
  2. package/.claude/skills/event-modeling/reference/conform.md +45 -20
  3. package/.claude/skills/event-modeling/reference/em-dsl.md +120 -55
  4. package/.claude/skills/event-modeling/reference/extract.md +5 -4
  5. package/.claude/skills/event-modeling/reference/implement.md +34 -22
  6. package/.claude/skills/event-modeling/templates/model-readme.md +8 -5
  7. package/.claude/skills/event-modeling/templates/slice.md +19 -5
  8. package/README.md +6 -4
  9. package/dist/catalog/docJoin.d.ts +28 -3
  10. package/dist/catalog/docJoin.js +82 -13
  11. package/dist/catalog/docJoin.js.map +1 -1
  12. package/dist/catalog/docModelConsistencyValidate.d.ts +8 -0
  13. package/dist/catalog/docModelConsistencyValidate.js +335 -0
  14. package/dist/catalog/docModelConsistencyValidate.js.map +1 -0
  15. package/dist/catalog/noteBindingValidate.d.ts +8 -0
  16. package/dist/catalog/noteBindingValidate.js +133 -0
  17. package/dist/catalog/noteBindingValidate.js.map +1 -0
  18. package/dist/catalog/pages.js +3 -3
  19. package/dist/catalog/pages.js.map +1 -1
  20. package/dist/catalog/sliceDoc.d.ts +14 -0
  21. package/dist/catalog/sliceDoc.js +22 -0
  22. package/dist/catalog/sliceDoc.js.map +1 -1
  23. package/dist/catalog/sliceReadyValidate.d.ts +18 -0
  24. package/dist/catalog/sliceReadyValidate.js +25 -1
  25. package/dist/catalog/sliceReadyValidate.js.map +1 -1
  26. package/dist/cli/agentsMd.d.ts +15 -0
  27. package/dist/cli/agentsMd.js +72 -0
  28. package/dist/cli/agentsMd.js.map +1 -0
  29. package/dist/cli/conformScope.d.ts +86 -0
  30. package/dist/cli/conformScope.js +156 -0
  31. package/dist/cli/conformScope.js.map +1 -0
  32. package/dist/cli/contract.d.ts +7 -0
  33. package/dist/cli/contract.js +27 -0
  34. package/dist/cli/contract.js.map +1 -0
  35. package/dist/cli/coverage.d.ts +69 -0
  36. package/dist/cli/coverage.js +157 -0
  37. package/dist/cli/coverage.js.map +1 -0
  38. package/dist/cli/markImplemented.d.ts +34 -0
  39. package/dist/cli/markImplemented.js +180 -0
  40. package/dist/cli/markImplemented.js.map +1 -0
  41. package/dist/cli/migrateReactionShape.d.ts +62 -0
  42. package/dist/cli/migrateReactionShape.js +283 -0
  43. package/dist/cli/migrateReactionShape.js.map +1 -0
  44. package/dist/cli/sliceIndex.d.ts +49 -0
  45. package/dist/cli/sliceIndex.js +115 -0
  46. package/dist/cli/sliceIndex.js.map +1 -0
  47. package/dist/cli/sliceNew.d.ts +18 -0
  48. package/dist/cli/sliceNew.js +53 -0
  49. package/dist/cli/sliceNew.js.map +1 -0
  50. package/dist/cli/stateFile.d.ts +74 -0
  51. package/dist/cli/stateFile.js +191 -0
  52. package/dist/cli/stateFile.js.map +1 -0
  53. package/dist/cli.js +535 -43
  54. package/dist/cli.js.map +1 -1
  55. package/dist/emit/coverageJson.d.ts +8 -0
  56. package/dist/emit/coverageJson.js +30 -0
  57. package/dist/emit/coverageJson.js.map +1 -0
  58. package/dist/emit/dot.js +41 -10
  59. package/dist/emit/dot.js.map +1 -1
  60. package/dist/emit/json.d.ts +72 -4
  61. package/dist/emit/json.js +73 -4
  62. package/dist/emit/json.js.map +1 -1
  63. package/dist/emit/validateJson.d.ts +52 -0
  64. package/dist/emit/validateJson.js +120 -0
  65. package/dist/emit/validateJson.js.map +1 -0
  66. package/dist/mcp/main.d.ts +2 -0
  67. package/dist/mcp/main.js +20 -0
  68. package/dist/mcp/main.js.map +1 -0
  69. package/dist/mcp/server.d.ts +11 -0
  70. package/dist/mcp/server.js +260 -0
  71. package/dist/mcp/server.js.map +1 -0
  72. package/dist/model/model.d.ts +30 -1
  73. package/dist/model/model.js +26 -0
  74. package/dist/model/model.js.map +1 -1
  75. package/dist/model/rules.d.ts +114 -0
  76. package/dist/model/rules.js +116 -4
  77. package/dist/model/rules.js.map +1 -1
  78. package/dist/model/validate.js +83 -7
  79. package/dist/model/validate.js.map +1 -1
  80. package/dist/parser/ast.d.ts +41 -0
  81. package/dist/parser/lexer.d.ts +16 -0
  82. package/dist/parser/lexer.js +44 -2
  83. package/dist/parser/lexer.js.map +1 -1
  84. package/dist/parser/parser.js +340 -20
  85. package/dist/parser/parser.js.map +1 -1
  86. package/dist/render/drawNotes.js +8 -1
  87. package/dist/render/drawNotes.js.map +1 -1
  88. package/dist/render/render.js +85 -17
  89. package/dist/render/render.js.map +1 -1
  90. package/dist/render/serve.d.ts +4 -0
  91. package/dist/render/serve.js +23 -227
  92. package/dist/render/serve.js.map +1 -1
  93. package/dist/render/sliceStatus.d.ts +1 -1
  94. package/dist/render/sliceStatus.js +35 -6
  95. package/dist/render/sliceStatus.js.map +1 -1
  96. package/dist/render/viewerHtml.d.ts +1 -0
  97. package/dist/render/viewerHtml.js +5 -0
  98. package/dist/render/viewerHtml.js.map +1 -0
  99. package/dist/render/watch.d.ts +10 -0
  100. package/dist/render/watch.js +29 -0
  101. package/dist/render/watch.js.map +1 -1
  102. package/dist/templates.d.ts +19 -0
  103. package/dist/templates.js +169 -0
  104. package/dist/templates.js.map +1 -1
  105. package/dist/util/markers.d.ts +13 -0
  106. package/dist/util/markers.js +30 -0
  107. package/dist/util/markers.js.map +1 -0
  108. package/dist/util/walkDir.d.ts +10 -1
  109. package/dist/util/walkDir.js +11 -7
  110. package/dist/util/walkDir.js.map +1 -1
  111. package/package.json +12 -3
  112. package/.claude/skills/event-modeling/templates/live.html +0 -105
@@ -0,0 +1,115 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `em slice index` (MIL-98): rewrites the marker-delimited Slices table in a model's sibling
3
+ // README.md from the same facts `em export` derives for each slice — export key, AST-derived
4
+ // pattern, and the slice-doc frontmatter join — so the README's "ONE place slices are
5
+ // enumerated" (templates/model-readme.md) stops being hand-maintained, derived data that drifts.
6
+ //
7
+ // Deliberately no new parsing: buildSliceIndexTable below calls exactly the two functions
8
+ // `em export`'s own per-slice loop (src/emit/json.ts) calls — classifySlicePattern and
9
+ // resolveSliceDocJoin — so a slice's pattern/status/implementedIn here can never disagree with
10
+ // what `em export`/`em catalog` already say about it.
11
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
12
+ import { dirname, join } from "node:path";
13
+ import { classifySlicePattern, slicePatternLabel } from "../catalog/classify.js";
14
+ import { resolveSliceDocJoin } from "../catalog/docJoin.js";
15
+ import { applyMarker } from "../util/markers.js";
16
+ /** The marker name wrapping the Slices table: `<!-- GENERATED:slices:start -->` /
17
+ * `<!-- GENERATED:slices:end -->`, matching templates/model-readme.md. */
18
+ export const SLICE_INDEX_MARKER = "slices";
19
+ const TABLE_HEADER = "| # | Slice | Pattern | Status | Implemented in | Design doc |\n" +
20
+ "|---|-------|---------|--------|----------------|------------|";
21
+ /** Escape characters that would break a markdown table cell: `|` (the column separator) and
22
+ * newlines (a slice name is always one line, but a doc's freeform `implementedIn` text isn't
23
+ * guaranteed to be). */
24
+ function escapeCell(s) {
25
+ // Backslashes first: escaping `|` alone would let a pre-existing `\` in the source text
26
+ // combine with the newly-inserted `\` (e.g. a literal `\|`) and un-escape the pipe again
27
+ // once Markdown unescapes the backslash sequence (CodeQL "incomplete string escaping").
28
+ return s.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
29
+ }
30
+ /** Status cell wording: mirrors `em catalog`'s own found/status split (catalog/pages.ts's
31
+ * statusLabel — "no doc" when nothing was found, the doc's own status otherwise, "unknown" for
32
+ * a found-but-unusable doc) with one deliberate difference: "no doc yet", matching the wording
33
+ * templates/model-readme.md and reference/extract.md already use for a slice that hasn't
34
+ * reached the `slice` phase. `doc.found` false covers both of docJoin's not-found reasons
35
+ * (no-doc-bound and binding-missing-file) — catalog doesn't distinguish them either, since a
36
+ * broken binding still means "there's no doc a human can currently read." */
37
+ function statusCell(doc) {
38
+ if (!doc.found)
39
+ return "no doc yet";
40
+ return doc.status ?? "unknown";
41
+ }
42
+ /** Build the Slices table body for `model`. `baseDir` is the `.em` file's directory — same
43
+ * doc-resolution convention `em export`/`em catalog` use for `slices/<key>.md`. */
44
+ export function buildSliceIndexTable(model, refs, baseDir) {
45
+ const diagnostics = [];
46
+ const rows = model.slices.map((slice, i) => {
47
+ const sliceKey = refs.sliceKeys[i];
48
+ const pattern = classifySlicePattern(slice);
49
+ const { doc, diagnostics: docDiags } = resolveSliceDocJoin(slice, sliceKey, baseDir, (id) => refs.refById.get(id));
50
+ diagnostics.push(...docDiags);
51
+ return {
52
+ index: i + 1,
53
+ name: slice.name,
54
+ pattern: slicePatternLabel(pattern),
55
+ status: statusCell(doc),
56
+ implementedIn: doc.implementedIn ?? "—",
57
+ docPath: doc.path,
58
+ };
59
+ });
60
+ const lines = rows.map((r) => `| ${r.index} | ${escapeCell(r.name)} | ${escapeCell(r.pattern)} | ${escapeCell(r.status)} | ` +
61
+ `${escapeCell(r.implementedIn)} | [${r.docPath}](${r.docPath}) |`);
62
+ return { markdown: [TABLE_HEADER, ...lines].join("\n"), rows, diagnostics };
63
+ }
64
+ /**
65
+ * Rewrite (or, in `check` mode, verify) the GENERATED:slices block in `<dirname(emFilePath)>/
66
+ * README.md`. Never creates the README or the marker pair — both are user errors reported back
67
+ * via `ok: false`, not silently fixed: a missing README means the model wasn't scaffolded from
68
+ * templates/model-readme.md yet, and missing markers mean an older/hand-edited README that
69
+ * needs the marker pair added first (see the message text for exactly what to do).
70
+ *
71
+ * `check: true` never writes to disk; a stale table is reported as `kind: "stale"` instead
72
+ * (CI-ready — the caller exits non-zero without having touched the working tree).
73
+ */
74
+ export function runSliceIndex(model, refs, emFilePath, check) {
75
+ const baseDir = dirname(emFilePath);
76
+ const readmePath = join(baseDir, "README.md");
77
+ const table = buildSliceIndexTable(model, refs, baseDir);
78
+ if (!existsSync(readmePath)) {
79
+ return {
80
+ ok: false,
81
+ kind: "missing-readme",
82
+ message: `em slice index: expected a README.md next to ${emFilePath} (looked for ${readmePath}) — ` +
83
+ "none found. Scaffold one from templates/model-readme.md first.",
84
+ table,
85
+ };
86
+ }
87
+ const original = readFileSync(readmePath, "utf8");
88
+ const updated = applyMarker(original, SLICE_INDEX_MARKER, table.markdown);
89
+ if (updated === null) {
90
+ return {
91
+ ok: false,
92
+ kind: "missing-markers",
93
+ message: `em slice index: ${readmePath} has no <!-- GENERATED:${SLICE_INDEX_MARKER}:start --> / ` +
94
+ `<!-- GENERATED:${SLICE_INDEX_MARKER}:end --> markers around its Slices table — add them ` +
95
+ "(copy the ## Slices section from .claude/skills/event-modeling/templates/model-readme.md) " +
96
+ "before running this command.",
97
+ table,
98
+ };
99
+ }
100
+ const changed = updated !== original;
101
+ if (!changed)
102
+ return { ok: true, readmePath, wrote: false, changed: false, table };
103
+ if (check) {
104
+ return {
105
+ ok: false,
106
+ kind: "stale",
107
+ message: `em slice index --check: ${readmePath}'s Slices table is stale — run ` +
108
+ `\`em slice index ${emFilePath}\` and commit the result.`,
109
+ table,
110
+ };
111
+ }
112
+ writeFileSync(readmePath, updated, "utf8");
113
+ return { ok: true, readmePath, wrote: true, changed: true, table };
114
+ }
115
+ //# sourceMappingURL=sliceIndex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceIndex.js","sourceRoot":"","sources":["../../src/cli/sliceIndex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** `pattern`'s exact 4-value enum — docs/slice-doc-schema.md's "Canonical keys" table. */
2
+ export declare const SLICE_PATTERNS: readonly ["state-change", "state-view", "automation", "translation"];
3
+ export type SlicePattern = (typeof SLICE_PATTERNS)[number];
4
+ export declare function isSlicePattern(value: string): value is SlicePattern;
5
+ /** The filename stem a slice's display name maps to — `slices/<key>.md`, and the same key a
6
+ * `note "slices/<key>.md"` binding on the slice's primary element must match. Always derive
7
+ * it with this (kebabSlug, the same helper `em scaffold` uses) rather than letting a caller
8
+ * pass a pre-slugged key of their own, so the two can never drift apart. */
9
+ export declare function sliceDocKey(displayName: string): string;
10
+ /**
11
+ * Build the full contents of a fresh `slices/<key>.md`. Frontmatter: exactly the 5 keys
12
+ * required at `status: draft`, in the same order templates/slice.md's own frontmatter block
13
+ * uses. Body: the `# Slice: <name>` heading and the diagram-image stub the skill's `slice`
14
+ * phase step 3 fills the actual image in for (`em render ... --slice ... -o
15
+ * slices/<key>.svg`) — every judgment section (Intent, Command, Scenarios, Open Questions,
16
+ * ...) is deliberately left out, staying hand-authored per templates/slice.md.
17
+ */
18
+ export declare function buildSliceDocContent(displayName: string, key: string, pattern: SlicePattern, swimlane: string): string;
@@ -0,0 +1,53 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // `em slice new` (MIL-97 item 3): scaffolds a fresh slices/<key>.md doc's mechanical
3
+ // frontmatter + heading — exactly the 5 keys docs/slice-doc-schema.md's required-vs-optional
4
+ // table requires at `status: draft` (schemaVersion/pattern/swimlane/status/version), nothing
5
+ // else — no `implementedIn` (only required once a slice has ever reached `implemented`), no
6
+ // lineage keys (`split-from`/`merged-from`/`superseded-by` only apply to a split/merge/rename
7
+ // doc), no commented-out guidance cruft. The skill's `slice` phase still writes every judgment
8
+ // section by hand (Intent, Command, Scenarios, Open Questions, ...) — this command only kills
9
+ // the copy-paste-the-template-and-fill-in-the-frontmatter step, the one purely mechanical part
10
+ // that was silently drifting when hand-typed (a placeholder left unedited, a key forgotten).
11
+ //
12
+ // Deliberately fs-free/pure — src/cli.ts owns the write, the existing-file/--force check, and
13
+ // the printed `note` reminder, same split as sliceIndex.ts (buildSliceIndexTable vs
14
+ // runSliceIndex/CLI wiring).
15
+ import { kebabSlug } from "../util/slug.js";
16
+ /** `pattern`'s exact 4-value enum — docs/slice-doc-schema.md's "Canonical keys" table. */
17
+ export const SLICE_PATTERNS = ["state-change", "state-view", "automation", "translation"];
18
+ export function isSlicePattern(value) {
19
+ return SLICE_PATTERNS.includes(value);
20
+ }
21
+ /** Current frontmatter dialect version (docs/slice-doc-schema.md, "schemaVersion vs version"):
22
+ * one value, the same across every doc using this dialect, bumped only by `em` maintainers
23
+ * when the dialect's canonical keys change — unrelated to any one slice's own `version`.
24
+ * Unchanged since MIL-86. */
25
+ const SCHEMA_VERSION = 1;
26
+ /** The filename stem a slice's display name maps to — `slices/<key>.md`, and the same key a
27
+ * `note "slices/<key>.md"` binding on the slice's primary element must match. Always derive
28
+ * it with this (kebabSlug, the same helper `em scaffold` uses) rather than letting a caller
29
+ * pass a pre-slugged key of their own, so the two can never drift apart. */
30
+ export function sliceDocKey(displayName) {
31
+ return kebabSlug(displayName);
32
+ }
33
+ /**
34
+ * Build the full contents of a fresh `slices/<key>.md`. Frontmatter: exactly the 5 keys
35
+ * required at `status: draft`, in the same order templates/slice.md's own frontmatter block
36
+ * uses. Body: the `# Slice: <name>` heading and the diagram-image stub the skill's `slice`
37
+ * phase step 3 fills the actual image in for (`em render ... --slice ... -o
38
+ * slices/<key>.svg`) — every judgment section (Intent, Command, Scenarios, Open Questions,
39
+ * ...) is deliberately left out, staying hand-authored per templates/slice.md.
40
+ */
41
+ export function buildSliceDocContent(displayName, key, pattern, swimlane) {
42
+ return (`---\n` +
43
+ `schemaVersion: ${SCHEMA_VERSION}\n` +
44
+ `pattern: ${pattern}\n` +
45
+ `swimlane: ${swimlane}\n` +
46
+ `status: draft\n` +
47
+ `version: 1\n` +
48
+ `---\n` +
49
+ `# Slice: ${displayName}\n` +
50
+ `\n` +
51
+ `![Diagram](./${key}.svg)\n`);
52
+ }
53
+ //# sourceMappingURL=sliceNew.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sliceNew.js","sourceRoot":"","sources":["../../src/cli/sliceNew.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,qFAAqF;AACrF,6FAA6F;AAC7F,6FAA6F;AAC7F,4FAA4F;AAC5F,8FAA8F;AAC9F,+FAA+F;AAC/F,8FAA8F;AAC9F,+FAA+F;AAC/F,6FAA6F;AAC7F,EAAE;AACF,8FAA8F;AAC9F,oFAAoF;AACpF,6BAA6B;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,0FAA0F;AAC1F,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,CAAU,CAAC;AAGnG,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAQ,cAAoC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED;;;8BAG8B;AAC9B,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB;;;6EAG6E;AAC7E,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB,EAAE,GAAW,EAAE,OAAqB,EAAE,QAAgB;IAC5G,OAAO,CACL,OAAO;QACP,kBAAkB,cAAc,IAAI;QACpC,YAAY,OAAO,IAAI;QACvB,aAAa,QAAQ,IAAI;QACzB,iBAAiB;QACjB,cAAc;QACd,OAAO;QACP,YAAY,WAAW,IAAI;QAC3B,IAAI;QACJ,gBAAgB,GAAG,SAAS,CAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,74 @@
1
+ /** Filename the skill scaffolds/reads at `<model-dir>/.event-modeling.md`. */
2
+ export declare const STATE_FILE_NAME = ".event-modeling.md";
3
+ /** Canonical phase enum — the ONE list `em state set-phase` enforces. Mirrors
4
+ * templates/state.md's `Current phase:` placeholder list exactly (not SKILL.md's superset,
5
+ * which also lists `watch` — a live-viewing activity you pass through, never a phase you
6
+ * leave the model parked at, so it's deliberately not a valid `Current phase:` value). */
7
+ export declare const PHASES: readonly ["discover", "extract", "model", "slice", "implement", "conform", "review", "validate"];
8
+ export type Phase = (typeof PHASES)[number];
9
+ export declare function isPhase(value: string): value is Phase;
10
+ /** The state file's mechanical fields, decoded to plain data. `lastConformance`/`lastReview`
11
+ * are `null` for the template's `never` marker (never run yet). */
12
+ export interface ParsedState {
13
+ modelPath: string;
14
+ phase: string;
15
+ step: string;
16
+ lastUpdated: string;
17
+ lastConformance: {
18
+ date: string;
19
+ revision: string;
20
+ report: string;
21
+ } | null;
22
+ lastReview: string | null;
23
+ }
24
+ export type ParseStateResult = {
25
+ ok: true;
26
+ state: ParsedState;
27
+ } | {
28
+ ok: false;
29
+ message: string;
30
+ };
31
+ export type PatchResult = {
32
+ ok: true;
33
+ text: string;
34
+ } | {
35
+ ok: false;
36
+ message: string;
37
+ };
38
+ /** Resolve what `<dir>` means for every `em state` subcommand: a direct path to the state file
39
+ * itself (its basename is exactly `.event-modeling.md`) is used as-is; anything else is treated
40
+ * as the model directory containing it. Lets `em state read .` and
41
+ * `em state read path/to/.event-modeling.md` both work without a separate flag. */
42
+ export declare function resolveStateFilePath(dirOrFile: string): string;
43
+ export type LoadResult = {
44
+ ok: true;
45
+ path: string;
46
+ text: string;
47
+ } | {
48
+ ok: false;
49
+ message: string;
50
+ };
51
+ /** The one fs read every `em state` subcommand goes through. */
52
+ export declare function loadStateFile(dirOrFile: string): LoadResult;
53
+ /** Parse the six mechanical bullets out of a state file's raw text. `ok: false` when the file
54
+ * is missing one of the bullet lines entirely, or when `Last conformance:`/`Last stakeholder
55
+ * review:` holds neither `never` nor its documented format — both are the file failing to be
56
+ * the thing resume/conform scoping needs, so both are reported the same way. */
57
+ export declare function parseState(text: string): ParseStateResult;
58
+ /** `em state set-phase`: rewrite `Current phase:` (and `Current step:` when `step` is given)
59
+ * plus `Last updated:`. `phase` is trusted to already be a validated `Phase` — the CLI layer
60
+ * checks against `PHASES` before calling this so the enum has exactly one home. */
61
+ export declare function setPhase(text: string, phase: Phase, today: string, step?: string): PatchResult;
62
+ /** `em state set-conformance`: rewrite `Last conformance:` in the EXACT format
63
+ * reference/conform.md's "keep the format exact" instruction specifies — the next conform
64
+ * run's scoping (reference/conform.md step 1) parses this line back out — plus `Last
65
+ * updated:`. */
66
+ export declare function setConformance(text: string, revision: string, report: string, today: string): PatchResult;
67
+ /** `em state set-review`: rewrite `Last stakeholder review:` (per templates/state.md's format)
68
+ * plus `Last updated:`. `date` is trusted to already look like `YYYY-MM-DD` — the CLI layer
69
+ * validates before calling this. */
70
+ export declare function setReview(text: string, date: string, today: string): PatchResult;
71
+ /** Loose but real validation for a `YYYY-MM-DD` CLI argument: right shape, and month/day in
72
+ * range — not a full calendar (no leap-year/days-in-month check), which is more rigor than a
73
+ * state-file marker needs. */
74
+ export declare function isValidDateString(s: string): boolean;
@@ -0,0 +1,191 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Reads and writes the MECHANICAL fields of a model's resumable state file
3
+ // (`.event-modeling.md`, see .claude/skills/event-modeling/templates/state.md): `Model file:`,
4
+ // `Current phase:`, `Current step:`, `Last updated:`, `Last conformance:`, `Last stakeholder
5
+ // review:`. This is the ONE parser for those bullets — `em changelog` (src/emit/changelog.ts,
6
+ // parseDecisionsLog) parses a disjoint section of the same file (the `## Decisions log`) and
7
+ // stays a separate function for that reason, but shares STATE_FILE_NAME with this module rather
8
+ // than hard-coding the filename a second time.
9
+ //
10
+ // Deliberately narrow: judgment content (Session inputs, Participants, Decisions log, Usage
11
+ // log, Open questions, Slice inventory) is agent-authored prose and out of scope here — this
12
+ // module only ever touches the six mechanical bullets above, byte-for-byte leaving every other
13
+ // line alone.
14
+ //
15
+ // Pure text in, text/data out (parseState, setPhase, setConformance, setReview); `loadStateFile`
16
+ // is the one bit of fs I/O, kept here so both `em state` (src/cli.ts) and any future caller
17
+ // share the same file-location convention instead of re-deriving it.
18
+ import { existsSync, readFileSync } from "node:fs";
19
+ import { basename, join } from "node:path";
20
+ /** Filename the skill scaffolds/reads at `<model-dir>/.event-modeling.md`. */
21
+ export const STATE_FILE_NAME = ".event-modeling.md";
22
+ /** Canonical phase enum — the ONE list `em state set-phase` enforces. Mirrors
23
+ * templates/state.md's `Current phase:` placeholder list exactly (not SKILL.md's superset,
24
+ * which also lists `watch` — a live-viewing activity you pass through, never a phase you
25
+ * leave the model parked at, so it's deliberately not a valid `Current phase:` value). */
26
+ export const PHASES = ["discover", "extract", "model", "slice", "implement", "conform", "review", "validate"];
27
+ export function isPhase(value) {
28
+ return PHASES.includes(value);
29
+ }
30
+ const LABELS = {
31
+ modelFile: "Model file",
32
+ currentPhase: "Current phase",
33
+ currentStep: "Current step",
34
+ lastUpdated: "Last updated",
35
+ lastConformance: "Last conformance",
36
+ lastStakeholderReview: "Last stakeholder review",
37
+ };
38
+ function escapeForRegex(s) {
39
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
40
+ }
41
+ function bulletLineRegex(label) {
42
+ // `m` (multiline) so `^`/`$` bound one line; `.` already excludes line terminators, so this
43
+ // never reaches across lines regardless of LF/CRLF.
44
+ return new RegExp(`^-\\s+\\*\\*${escapeForRegex(label)}:\\*\\*.*$`, "m");
45
+ }
46
+ function bulletValue(text, label) {
47
+ const re = new RegExp(`^-\\s+\\*\\*${escapeForRegex(label)}:\\*\\*\\s*(.*)$`, "m");
48
+ const m = re.exec(text);
49
+ return m ? m[1].trim() : null;
50
+ }
51
+ /** Resolve what `<dir>` means for every `em state` subcommand: a direct path to the state file
52
+ * itself (its basename is exactly `.event-modeling.md`) is used as-is; anything else is treated
53
+ * as the model directory containing it. Lets `em state read .` and
54
+ * `em state read path/to/.event-modeling.md` both work without a separate flag. */
55
+ export function resolveStateFilePath(dirOrFile) {
56
+ return basename(dirOrFile) === STATE_FILE_NAME ? dirOrFile : join(dirOrFile, STATE_FILE_NAME);
57
+ }
58
+ /** The one fs read every `em state` subcommand goes through. */
59
+ export function loadStateFile(dirOrFile) {
60
+ const path = resolveStateFilePath(dirOrFile);
61
+ if (!existsSync(path)) {
62
+ return { ok: false, message: `em state: no state file at ${path}` };
63
+ }
64
+ return { ok: true, path, text: readFileSync(path, "utf8") };
65
+ }
66
+ const LAST_CONFORMANCE_RE = /^(\d{4}-\d{2}-\d{2}) @ (.+?) — report: (.+)$/;
67
+ const LEADING_DATE_RE = /^(\d{4}-\d{2}-\d{2})\b/;
68
+ /** Parse the six mechanical bullets out of a state file's raw text. `ok: false` when the file
69
+ * is missing one of the bullet lines entirely, or when `Last conformance:`/`Last stakeholder
70
+ * review:` holds neither `never` nor its documented format — both are the file failing to be
71
+ * the thing resume/conform scoping needs, so both are reported the same way. */
72
+ export function parseState(text) {
73
+ const missing = [];
74
+ const raw = {};
75
+ for (const label of Object.values(LABELS)) {
76
+ const v = bulletValue(text, label);
77
+ if (v === null)
78
+ missing.push(label);
79
+ else
80
+ raw[label] = v;
81
+ }
82
+ if (missing.length > 0) {
83
+ return {
84
+ ok: false,
85
+ message: `missing bullet line(s): ${missing.map((l) => `"- **${l}:**"`).join(", ")}`,
86
+ };
87
+ }
88
+ const modelPath = raw[LABELS.modelFile].replace(/^`|`$/g, "");
89
+ const lastConformanceRaw = raw[LABELS.lastConformance];
90
+ let lastConformance = null;
91
+ if (lastConformanceRaw !== "never") {
92
+ const m = LAST_CONFORMANCE_RE.exec(lastConformanceRaw);
93
+ if (!m) {
94
+ return {
95
+ ok: false,
96
+ message: `"- **Last conformance:**" doesn't match "YYYY-MM-DD @ <revision> — report: <path>" or "never": ${lastConformanceRaw}`,
97
+ };
98
+ }
99
+ lastConformance = { date: m[1], revision: m[2], report: m[3] };
100
+ }
101
+ const lastReviewRaw = raw[LABELS.lastStakeholderReview];
102
+ let lastReview = null;
103
+ if (lastReviewRaw !== "never") {
104
+ const m = LEADING_DATE_RE.exec(lastReviewRaw);
105
+ if (!m) {
106
+ return {
107
+ ok: false,
108
+ message: `"- **Last stakeholder review:**" doesn't start with "YYYY-MM-DD" or "never": ${lastReviewRaw}`,
109
+ };
110
+ }
111
+ lastReview = m[1];
112
+ }
113
+ return {
114
+ ok: true,
115
+ state: {
116
+ modelPath,
117
+ phase: raw[LABELS.currentPhase],
118
+ step: raw[LABELS.currentStep],
119
+ lastUpdated: raw[LABELS.lastUpdated],
120
+ lastConformance,
121
+ lastReview,
122
+ },
123
+ };
124
+ }
125
+ /** Replace one or more bullet lines in place, in the order given, failing (without writing
126
+ * anything) if any targeted bullet is missing. Every other byte of `text` — including every
127
+ * other bullet, and whatever line ending style the file already used — passes through the
128
+ * regex untouched. */
129
+ function applyBulletUpdates(text, updates) {
130
+ let result = text;
131
+ const missing = [];
132
+ for (const { label, value } of updates) {
133
+ const re = bulletLineRegex(label);
134
+ if (!re.test(result)) {
135
+ missing.push(label);
136
+ continue;
137
+ }
138
+ // Replacer function, not a string pattern — a string replacement would let `$&`/`$'`/`$$`
139
+ // etc. in a user-supplied value (revision, report path, step) expand against the matched
140
+ // line and corrupt the file. A function's return value is inserted literally.
141
+ result = result.replace(re, () => `- **${label}:** ${value}`);
142
+ }
143
+ if (missing.length > 0) {
144
+ return { ok: false, message: `missing bullet line(s): ${missing.map((l) => `"- **${l}:**"`).join(", ")}` };
145
+ }
146
+ return { ok: true, text: result };
147
+ }
148
+ /** `em state set-phase`: rewrite `Current phase:` (and `Current step:` when `step` is given)
149
+ * plus `Last updated:`. `phase` is trusted to already be a validated `Phase` — the CLI layer
150
+ * checks against `PHASES` before calling this so the enum has exactly one home. */
151
+ export function setPhase(text, phase, today, step) {
152
+ const updates = [{ label: LABELS.currentPhase, value: phase }];
153
+ if (step !== undefined)
154
+ updates.push({ label: LABELS.currentStep, value: step });
155
+ updates.push({ label: LABELS.lastUpdated, value: today });
156
+ return applyBulletUpdates(text, updates);
157
+ }
158
+ /** `em state set-conformance`: rewrite `Last conformance:` in the EXACT format
159
+ * reference/conform.md's "keep the format exact" instruction specifies — the next conform
160
+ * run's scoping (reference/conform.md step 1) parses this line back out — plus `Last
161
+ * updated:`. */
162
+ export function setConformance(text, revision, report, today) {
163
+ const value = `${today} @ ${revision} — report: ${report}`;
164
+ return applyBulletUpdates(text, [
165
+ { label: LABELS.lastConformance, value },
166
+ { label: LABELS.lastUpdated, value: today },
167
+ ]);
168
+ }
169
+ /** `em state set-review`: rewrite `Last stakeholder review:` (per templates/state.md's format)
170
+ * plus `Last updated:`. `date` is trusted to already look like `YYYY-MM-DD` — the CLI layer
171
+ * validates before calling this. */
172
+ export function setReview(text, date, today) {
173
+ const value = `${date} — attendees: see Participants`;
174
+ return applyBulletUpdates(text, [
175
+ { label: LABELS.lastStakeholderReview, value },
176
+ { label: LABELS.lastUpdated, value: today },
177
+ ]);
178
+ }
179
+ const DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
180
+ /** Loose but real validation for a `YYYY-MM-DD` CLI argument: right shape, and month/day in
181
+ * range — not a full calendar (no leap-year/days-in-month check), which is more rigor than a
182
+ * state-file marker needs. */
183
+ export function isValidDateString(s) {
184
+ const m = DATE_RE.exec(s);
185
+ if (!m)
186
+ return false;
187
+ const month = Number(m[2]);
188
+ const day = Number(m[3]);
189
+ return month >= 1 && month <= 12 && day >= 1 && day <= 31;
190
+ }
191
+ //# sourceMappingURL=stateFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateFile.js","sourceRoot":"","sources":["../../src/cli/stateFile.ts"],"names":[],"mappings":"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"}