@milehimikey/em 1.16.1 → 1.18.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/.claude/skills/event-modeling/SKILL.md +1 -1
- package/.claude/skills/event-modeling-conform/SKILL.md +3 -2
- package/.claude/skills/event-modeling-conform/reference/conform.md +7 -0
- package/.claude/skills/event-modeling-design/SKILL.md +46 -5
- package/.claude/skills/event-modeling-discover/SKILL.md +43 -8
- package/.claude/skills/event-modeling-discover/reference/extract.md +6 -1
- package/.claude/skills/event-modeling-discover/reference/prd-rubric.md +102 -0
- package/.claude/skills/event-modeling-discover/reference/prd-spec-path.md +171 -0
- package/.claude/skills/event-modeling-engagement/SKILL.md +28 -6
- package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -4
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +18 -8
- package/.claude/skills/event-modeling-review/SKILL.md +1 -1
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +107 -10
- package/.claude/skills/event-modeling-shared/reference/methodology.md +268 -0
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +122 -15
- package/.claude/skills/event-modeling-shared/templates/slice.md +11 -3
- package/.claude-plugin/marketplace.json +2 -2
- package/dist/catalog/docJoin.d.ts +13 -5
- package/dist/catalog/docJoin.js +6 -1
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/docModelConsistencyValidate.js +160 -0
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/invariantsValidate.d.ts +2 -0
- package/dist/catalog/invariantsValidate.js +67 -1
- package/dist/catalog/invariantsValidate.js.map +1 -1
- package/dist/catalog/scenarioQualityValidate.d.ts +4 -0
- package/dist/catalog/scenarioQualityValidate.js +148 -0
- package/dist/catalog/scenarioQualityValidate.js.map +1 -0
- package/dist/catalog/scenarios.d.ts +5 -0
- package/dist/catalog/scenarios.js +80 -0
- package/dist/catalog/scenarios.js.map +1 -1
- package/dist/catalog/signedBodyValidate.d.ts +7 -0
- package/dist/catalog/signedBodyValidate.js +29 -0
- package/dist/catalog/signedBodyValidate.js.map +1 -0
- package/dist/catalog/sliceDoc.d.ts +53 -7
- package/dist/catalog/sliceDoc.js +89 -10
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +23 -2
- package/dist/catalog/sliceReadyValidate.js +54 -22
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/catalog/sliceSections.d.ts +3 -2
- package/dist/catalog/sliceSections.js +99 -9
- package/dist/catalog/sliceSections.js.map +1 -1
- package/dist/cli/ciInit.d.ts +4 -11
- package/dist/cli/ciInit.js +24 -6
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/coverage.d.ts +9 -0
- package/dist/cli/coverage.js +18 -0
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.d.ts +60 -17
- package/dist/cli/defer.js +187 -86
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/engagement.d.ts +46 -0
- package/dist/cli/engagement.js +156 -1
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/engagementFoundation.d.ts +47 -0
- package/dist/cli/engagementFoundation.js +164 -0
- package/dist/cli/engagementFoundation.js.map +1 -0
- package/dist/cli/frontmatterSurgery.d.ts +5 -0
- package/dist/cli/frontmatterSurgery.js +15 -0
- package/dist/cli/frontmatterSurgery.js.map +1 -1
- package/dist/cli/ledgerCheck.d.ts +5 -1
- package/dist/cli/ledgerCheck.js +50 -20
- package/dist/cli/ledgerCheck.js.map +1 -1
- package/dist/cli/markImplemented.d.ts +14 -10
- package/dist/cli/markImplemented.js +49 -1
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/prdTriage.d.ts +109 -0
- package/dist/cli/prdTriage.js +378 -0
- package/dist/cli/prdTriage.js.map +1 -0
- package/dist/cli/ratify.d.ts +14 -2
- package/dist/cli/ratify.js +34 -6
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/refsCheck.d.ts +78 -0
- package/dist/cli/refsCheck.js +153 -0
- package/dist/cli/refsCheck.js.map +1 -0
- package/dist/cli/render-inputs.d.ts +2 -0
- package/dist/cli/render-inputs.js +4 -0
- package/dist/cli/render-inputs.js.map +1 -1
- package/dist/cli/revise.d.ts +12 -3
- package/dist/cli/revise.js +43 -10
- package/dist/cli/revise.js.map +1 -1
- package/dist/cli/shape.d.ts +27 -0
- package/dist/cli/shape.js +77 -0
- package/dist/cli/shape.js.map +1 -0
- package/dist/cli/sliceConform.js +9 -0
- package/dist/cli/sliceConform.js.map +1 -1
- package/dist/cli/sliceIndex.d.ts +6 -1
- package/dist/cli/sliceIndex.js +28 -13
- package/dist/cli/sliceIndex.js.map +1 -1
- package/dist/cli/sliceNew.d.ts +4 -1
- package/dist/cli/sliceNew.js +26 -9
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/status.d.ts +26 -5
- package/dist/cli/status.js +28 -6
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/storylineSuggest.d.ts +26 -0
- package/dist/cli/storylineSuggest.js +252 -0
- package/dist/cli/storylineSuggest.js.map +1 -0
- package/dist/cli/upgrade.d.ts +15 -3
- package/dist/cli/upgrade.js +537 -8
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/upgradeReshape.d.ts +60 -0
- package/dist/cli/upgradeReshape.js +425 -0
- package/dist/cli/upgradeReshape.js.map +1 -0
- package/dist/cli.js +430 -57
- package/dist/cli.js.map +1 -1
- package/dist/emit/dot.d.ts +2 -0
- package/dist/emit/dot.js +44 -8
- package/dist/emit/dot.js.map +1 -1
- package/dist/emit/engagementJson.d.ts +4 -1
- package/dist/emit/engagementJson.js +27 -1
- package/dist/emit/engagementJson.js.map +1 -1
- package/dist/emit/json.d.ts +21 -1
- package/dist/emit/json.js +29 -2
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/ledgerJson.d.ts +1 -1
- package/dist/emit/ledgerJson.js +6 -1
- package/dist/emit/ledgerJson.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +3 -1
- package/dist/emit/queryJson.js.map +1 -1
- package/dist/emit/refsJson.d.ts +4 -0
- package/dist/emit/refsJson.js +19 -0
- package/dist/emit/refsJson.js.map +1 -0
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +6 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/theme.d.ts +1 -0
- package/dist/emit/theme.js +13 -0
- package/dist/emit/theme.js.map +1 -1
- package/dist/emit/validateJson.d.ts +5 -2
- package/dist/emit/validateJson.js +41 -2
- package/dist/emit/validateJson.js.map +1 -1
- package/dist/layout/grid.d.ts +5 -1
- package/dist/layout/grid.js +93 -2
- package/dist/layout/grid.js.map +1 -1
- package/dist/mcp/server.js +79 -14
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/edges.d.ts +7 -0
- package/dist/model/edges.js +33 -16
- package/dist/model/edges.js.map +1 -1
- package/dist/model/model.d.ts +33 -0
- package/dist/model/model.js +87 -3
- package/dist/model/model.js.map +1 -1
- package/dist/model/queryIndex.js +2 -2
- package/dist/model/queryIndex.js.map +1 -1
- package/dist/model/refs.js +8 -5
- package/dist/model/refs.js.map +1 -1
- package/dist/model/rules.d.ts +167 -1
- package/dist/model/rules.js +164 -3
- package/dist/model/rules.js.map +1 -1
- package/dist/model/shapeLint.d.ts +12 -0
- package/dist/model/shapeLint.js +170 -0
- package/dist/model/shapeLint.js.map +1 -0
- package/dist/model/storylines.d.ts +51 -0
- package/dist/model/storylines.js +188 -0
- package/dist/model/storylines.js.map +1 -0
- package/dist/model/validate.d.ts +6 -1
- package/dist/model/validate.js +317 -14
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/againSugar.d.ts +30 -0
- package/dist/parser/againSugar.js +105 -0
- package/dist/parser/againSugar.js.map +1 -0
- package/dist/parser/ast.d.ts +33 -0
- package/dist/parser/lexer.d.ts +9 -1
- package/dist/parser/lexer.js +17 -2
- package/dist/parser/lexer.js.map +1 -1
- package/dist/parser/parser.js +284 -4
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.js +1 -0
- package/dist/query/format.js.map +1 -1
- package/dist/query/verbs.d.ts +4 -0
- package/dist/query/verbs.js +30 -3
- package/dist/query/verbs.js.map +1 -1
- package/dist/render/drawEdges.js +100 -4
- package/dist/render/drawEdges.js.map +1 -1
- package/dist/render/render.js +20 -2
- package/dist/render/render.js.map +1 -1
- package/dist/render/sliceDiagram.js +5 -5
- package/dist/render/sliceDiagram.js.map +1 -1
- package/dist/render/storylineBands.d.ts +11 -0
- package/dist/render/storylineBands.js +80 -0
- package/dist/render/storylineBands.js.map +1 -0
- package/dist/render/storylineDiagram.d.ts +14 -0
- package/dist/render/storylineDiagram.js +142 -0
- package/dist/render/storylineDiagram.js.map +1 -0
- package/dist/roster/check.d.ts +32 -0
- package/dist/roster/check.js +92 -0
- package/dist/roster/check.js.map +1 -0
- package/dist/roster/context.d.ts +3 -0
- package/dist/roster/context.js +23 -0
- package/dist/roster/context.js.map +1 -0
- package/dist/roster/init.d.ts +15 -0
- package/dist/roster/init.js +52 -0
- package/dist/roster/init.js.map +1 -0
- package/dist/roster/roster.d.ts +79 -0
- package/dist/roster/roster.js +298 -0
- package/dist/roster/roster.js.map +1 -0
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/shared/reference/em-dsl.md +107 -10
- package/plugin/shared/reference/methodology.md +268 -0
- package/plugin/shared/reference/slice-doc-schema.md +122 -15
- package/plugin/shared/templates/slice.md +11 -3
- package/plugin/skills/conform/SKILL.md +3 -2
- package/plugin/skills/conform/reference/conform.md +7 -0
- package/plugin/skills/design/SKILL.md +46 -5
- package/plugin/skills/discover/SKILL.md +43 -8
- package/plugin/skills/discover/reference/extract.md +6 -1
- package/plugin/skills/discover/reference/prd-rubric.md +103 -0
- package/plugin/skills/discover/reference/prd-spec-path.md +172 -0
- package/plugin/skills/engagement/SKILL.md +28 -6
- package/plugin/skills/engagement/reference/engagement.md +5 -4
- package/plugin/skills/event-modeling/SKILL.md +1 -1
- package/plugin/skills/implement/SKILL.md +1 -1
- package/plugin/skills/implement/reference/implement.md +18 -8
- package/plugin/skills/review/SKILL.md +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when the user runs `/event-modeling` (with or without a phase name), or wants to resume an
|
|
6
6
|
event-modeling session without specifying which part of the process applies. Reads the model's
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-conform
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when checking a ratified event model (and its slice docs) for drift against the codebase
|
|
6
6
|
that implements it — advisory only, never a gate, never an unprompted edit — or when walking
|
|
@@ -44,7 +44,8 @@ Ruling on a finding is a human gate, like ratifying a slice
|
|
|
44
44
|
decides, and `em conform-supersede ... --locus <model|doc|code|none> --by <name>` records the
|
|
45
45
|
ruling on the findings record (and stamps the report) — never rule on your own judgment. Once
|
|
46
46
|
every finding touching a slice is ruled, `em slice conform <model-name>.em <key> --at <rev>`
|
|
47
|
-
certifies that version of the slice
|
|
47
|
+
certifies that version of the slice (`--at build:<id>` / `deploy:<id>` when the swept commit
|
|
48
|
+
will not stay reachable — a PR branch under squash/rebase merges; GH #261).
|
|
48
49
|
|
|
49
50
|
End of phase: state file's `Last conformance:` marker updated (via `em state set-conformance` —
|
|
50
51
|
refuses while any `implemented` slice still has an unruled finding; `--partial` escapes with a
|
|
@@ -319,8 +319,15 @@ slice with no unruled findings left:
|
|
|
319
319
|
|
|
320
320
|
```
|
|
321
321
|
em slice conform <model-name>.em <slice-key> --at <target-repo revision>
|
|
322
|
+
em slice conform <model-name>.em <slice-key> --at <kind>:<id> # e.g. build:1234 — what the sweep exercised, when its commit will not stay reachable (GH #261)
|
|
322
323
|
```
|
|
323
324
|
|
|
325
|
+
If you certified from a pull-request branch and the repo squash- or rebase-merges, the branch
|
|
326
|
+
HEAD will dangle once the branch is deleted. Either pass a commit the target branch will keep
|
|
327
|
+
(the merge commit) or record the deployment/build you actually swept as `--at build:<id>` /
|
|
328
|
+
`--at deploy:<id>` / `--at env:<id>` — and write the same string as the findings file's
|
|
329
|
+
`revision`, so the findings-check gate still matches.
|
|
330
|
+
|
|
324
331
|
— records `conformedVersion`/`conformedAt`/`conformedOn` on that slice's doc, so
|
|
325
332
|
`driftSignal` reads `in-sync` again (it reads `uncertified` for an implemented slice that's never
|
|
326
333
|
been through this) instead of just trusting `implementedIn`. Legal only for `status: implemented`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-design
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when structuring a draft event model into swimlanes and the four patterns (State Change,
|
|
6
6
|
State View, Automation, Translation), evaluating a model's structural completeness, or writing
|
|
@@ -65,7 +65,13 @@ evidence"). In short:
|
|
|
65
65
|
|
|
66
66
|
Goal: a structurally complete, **validated** model with correct patterns and swimlanes.
|
|
67
67
|
|
|
68
|
-
1. **Swimlanes & patterns (step 5).**
|
|
68
|
+
1. **Swimlanes & patterns (step 5).** **Name the storylines first**: the one main storyline (the
|
|
69
|
+
end-to-end journey) and the secondary ones (retire a thing, extend an attribute, reorganize).
|
|
70
|
+
Wrap each one's slices in a `storyline "Name" [source "url"] { slice … }` block (grammar and the
|
|
71
|
+
optional `after "<storyline>"` timeline clause: `em-dsl.md`) so the diagram gets a band per
|
|
72
|
+
story and `em render --storyline "Name"` can show one alone; slices keep their file order, and
|
|
73
|
+
a model can adopt storylines incrementally (`slice-outside-storyline` is only an advisory
|
|
74
|
+
warning) — but name them before you slice, not after. Then group events into **contexts** (bounded contexts /
|
|
69
75
|
aggregates) — ask which events share a consistency boundary and who owns them. Classify each
|
|
70
76
|
slice as one of the 4 patterns. **Share the slice between every automation or translation and
|
|
71
77
|
the command it triggers** (the reaction — processor/translation — together with the command
|
|
@@ -74,7 +80,21 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
74
80
|
directly**. Add `translation` slices for external inputs (externally triggered: external →
|
|
75
81
|
translation → command → event, no slice before) and for the system reacting to its own state
|
|
76
82
|
(internally triggered: read model in the slice before → translation → command → event).
|
|
77
|
-
2. **
|
|
83
|
+
2. **Storyline review — before any slice doc is scaffolded.** Read the timeline as a story, not a schema
|
|
84
|
+
(`../event-modeling-shared/reference/methodology.md`, "The story, not the schema"; em repo
|
|
85
|
+
`docs/storyline.md`). Name the **main storyline** (end-to-end happy path) and every
|
|
86
|
+
**secondary storyline** (retire, extend, reorganize), and group the slices under them; one
|
|
87
|
+
lifecycle block per entity (N × create/update/archive, one trailing view each) is the CRUD
|
|
88
|
+
shape — reshape it with the "Reshaping an existing model" checklist. Then the **intent test**
|
|
89
|
+
per command (would a business person say this name at this step in the story? an endpoint-shaped
|
|
90
|
+
name fails), the **question test** per view (write the question it answers; no question, no
|
|
91
|
+
read model; a child view only when its query needs what the parent view lacks), and the
|
|
92
|
+
**conditional-invariant signal** (invariants or fields that apply only "if `<field>` is set"
|
|
93
|
+
mean two intents in one command: split it). The `timeline-entity-clustered`,
|
|
94
|
+
`command-second-intent` and `automation-split-by-outcome` lints are the mechanical half; the
|
|
95
|
+
1.18.0 design exit gate is `em validate --shape`. Shape the model first, scaffold docs after: a rename,
|
|
96
|
+
split or merge from the reshape would orphan docs already wired with `--wire`. The `slice` phase is unchanged (timeline order).
|
|
97
|
+
3. **Elaborate scenarios — first pass (step 6).** Scaffold every slice's doc now, one per
|
|
78
98
|
slice, none skipped: `em slice new "<slice name>" --pattern <state-change|state-view|
|
|
79
99
|
automation|translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes
|
|
80
100
|
`slices/<slice-name>.md` at `status: draft` (the same command, flags, and `--wire`
|
|
@@ -95,7 +115,7 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
95
115
|
the one-command fast path: a near-free stub per undocumented slice, wired, in slice order
|
|
96
116
|
(MIL-184) — skip the per-slice `em slice new` calls above and deepen individual docs later
|
|
97
117
|
when the team is ready.
|
|
98
|
-
|
|
118
|
+
4. **Evaluate completeness (step 7).** Walk the model: every slice is a **complete** pattern, not a
|
|
99
119
|
half-slice — **every command has something that triggers it**, every command emits an event,
|
|
100
120
|
**every event is read by a read model**, **every read model has a consumer**, every view has a
|
|
101
121
|
source, every UI is reachable, every connection is
|
|
@@ -124,6 +144,19 @@ Goal: a structurally complete, **validated** model with correct patterns and swi
|
|
|
124
144
|
session and stage `contracts/<model key>.tsp` with the model edit — the one derived artifact
|
|
125
145
|
a design session produces, always by the command, never by hand.
|
|
126
146
|
|
|
147
|
+
5. **Shape exit gate (GH #282).** The model phase ends on the shape lints, not on your judgement
|
|
148
|
+
of the storyline: run `em validate <model>.em --shape` (add `--json` to read it; exit code is
|
|
149
|
+
always 0, so read the output). Every finding is either **fixed** in the model, or **accepted**
|
|
150
|
+
as one bullet in `.event-modeling.md` `## Decisions log`:
|
|
151
|
+
`- YYYY-MM-DD: shape-accepted: <rule> <refs> — <reason>`
|
|
152
|
+
The gate passes only when **every remaining finding, waived or not,** has such a bullet. A
|
|
153
|
+
baseline passed as `--waive-file <path>` (lines `<rule-code> <slice-key>`) only silences the CLI
|
|
154
|
+
count for an estate; it never replaces the bullet. Re-run until each remaining finding has its
|
|
155
|
+
bullet. **Refuse to move to the slice phase otherwise** (`em state set-phase slice` waits): the
|
|
156
|
+
same kind of exit gate as asserting the generated contract above. Do not accept a finding
|
|
157
|
+
without asking the user for the reason. The gate runs after doc scaffolding, so update or retire
|
|
158
|
+
wired docs for renamed, merged or split slices.
|
|
159
|
+
|
|
127
160
|
End of phase: render, update state (`em state set-phase slice` — the mechanical marker the state
|
|
128
161
|
machine expects), and stop. Every slice already has a draft doc ready to receive the deep spec,
|
|
129
162
|
but slicing is deliberate work the team starts when it's ready for it, not this phase's automatic
|
|
@@ -139,9 +172,17 @@ events already being settled, so working out of order means re-litigating an ear
|
|
|
139
172
|
contract mid-spec. Check `README.md`'s Slices table for what's already done (run `em slice index
|
|
140
173
|
<model-name>.em` first if it looks stale).
|
|
141
174
|
|
|
175
|
+
**Outcomes stay in the slice.** When the deep dive surfaces failure, retry or timeout, add the
|
|
176
|
+
outcome events (`Fulfilment Failed`, `Fulfilment Retry Scheduled`, ...) and their Given/When/Then
|
|
177
|
+
scenarios to the SAME slice, with retry policy and failure handling as invariants in its doc —
|
|
178
|
+
never a sibling slice per control-flow branch (1.18.0 adds the lint `automation-split-by-outcome`). A new slice
|
|
179
|
+
only when a different actor or a different trigger is involved. Canon: Dilger, "one business
|
|
180
|
+
action… two different possible outcomes" and "Linearize it!"; Dymitruk, "a few of these stories
|
|
181
|
+
to show how a command can and cannot succeed".
|
|
182
|
+
|
|
142
183
|
This is also where **branch / unhappy-path events** are discovered and added to the model — as a
|
|
143
184
|
slice's alternate/error flows surface (a rejection, removal, cancellation, decline, expiry), add
|
|
144
|
-
the
|
|
185
|
+
the outcome event to the same slice unless a different actor or trigger is involved, then re-render. The happy-path spine from earlier
|
|
145
186
|
phases is the starting point, not the finished event set. **Every new event needs its reader too**
|
|
146
187
|
— a rejection or cancellation that nothing projects will warn, and usually the missing piece is
|
|
147
188
|
real (someone has to see that the request was declined).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-discover
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting a brand-new event model from scratch — greenfield discovery: brainstorming
|
|
6
6
|
past-tense events, storyboarding the happy path, finding the commands and read models — or when
|
|
@@ -21,28 +21,40 @@ layout, the Socratic/validation discipline every phase follows) and
|
|
|
21
21
|
work — they are the source of truth. Run the preconditions there first.
|
|
22
22
|
|
|
23
23
|
**Existing system?** Use the `extract` phase below. **New feature inside an existing codebase,
|
|
24
|
-
not a whole-system extraction?** Stay in `discover`, but
|
|
25
|
-
Grep/Read adjacent real sources (OpenAPI
|
|
26
|
-
|
|
27
|
-
field tables (`event-modeling-design`).
|
|
24
|
+
not a whole-system extraction?** Stay in `discover`, but **only after the storyboard exists**
|
|
25
|
+
(step 2) and before locking in command/event names, Grep/Read adjacent real sources (OpenAPI
|
|
26
|
+
specs, DB migrations, existing DTOs/event classes in sibling contexts) rather than guessing
|
|
27
|
+
conventions — same check the `slice` phase applies to field tables (`event-modeling-design`).
|
|
28
|
+
Those sources fill operations no walkthrough touches; they never supply the story.
|
|
28
29
|
|
|
29
30
|
## Phase: `discover` — steps 1-4
|
|
30
31
|
|
|
31
32
|
Goal: a draft model of events, storyboard, commands, and views. Loose is OK; structure comes next.
|
|
32
33
|
|
|
33
|
-
1. **Brainstorm events (step 1).**
|
|
34
|
+
1. **Brainstorm events (step 1).** Draw the candidate events **from the walkthroughs and
|
|
35
|
+
journeys** (ask for them first; no walkthrough → *"what does success look like, start to
|
|
36
|
+
finish?"*): *"what happened, in the story's words?"* — business terms, never table or endpoint
|
|
37
|
+
vocabulary. Ask the user to name everything that happens, as past-tense
|
|
34
38
|
facts. Probe for missed state changes. For each candidate, apply the **"is it an event?"
|
|
35
39
|
test** (`methodology.md` step 1 — the "would this wake the CEO at 3am" heuristic):
|
|
36
40
|
reject derived values (belong in a read model) and telemetry/activity (not business state).
|
|
37
41
|
Don't silently drop rejections — park them in the state file's Decisions log with why, so
|
|
38
42
|
they aren't re-proposed later. Capture the survivors as a flat list.
|
|
39
|
-
2. **Plot / storyboard (step 2).**
|
|
43
|
+
2. **Plot / storyboard (step 2).** Start from the story, not the schema: ask for the spec's
|
|
44
|
+
**walkthroughs**, use cases and user journeys — or *"what does success look like, start to
|
|
45
|
+
finish?"* — and build the timeline from those (`methodology.md`, "The story, not the schema").
|
|
46
|
+
Name the **main storyline** (the end-to-end happy path) and each **secondary storyline**
|
|
47
|
+
(retire, extend, reorganize) before ordering anything; never one lifecycle block per entity
|
|
48
|
+
(the CRUD shape). The OpenAPI/migrations/resource reference comes **after** the storyboard,
|
|
49
|
+
only to fill operations no walkthrough touches. Order the events into the narrative. Identify **personas**
|
|
40
50
|
(actors) and the **UI** screens at each step. Add `persona` declarations and `ui` elements.
|
|
41
51
|
In a **headless/API** model there are no human personas or screens — identify the external
|
|
42
52
|
**callers** at each step instead; declare one persona per caller/role, and its `ui` boxes are
|
|
43
53
|
the API calls (see `methodology.md`).
|
|
44
54
|
3. **Inputs (step 3).** For each event, find the **command** that causes it (imperative name).
|
|
45
|
-
Form `command → event` slices (State Change pattern).
|
|
55
|
+
Form `command → event` slices (State Change pattern). Apply the **intent test**: name the
|
|
56
|
+
command for the intent a business person would say at this step of the story, not the
|
|
57
|
+
endpoint that carries it (`methodology.md`, "The story, not the schema"). Every command needs a **trigger** in the
|
|
46
58
|
same breath: the screen the user issues it from (a `ui` in the slice), or — for the Automation
|
|
47
59
|
and Translation patterns — the reaction that triggers it, also in this slice. A command
|
|
48
60
|
nothing points at is a write nobody can start. *"Who does this, and where are they when they
|
|
@@ -65,6 +77,29 @@ slice already reads "no doc yet" — no slice docs exist until the `slice` phase
|
|
|
65
77
|
Tell the user they can stop here and resume with `/event-modeling` (or invoke
|
|
66
78
|
`event-modeling-design` directly).
|
|
67
79
|
|
|
80
|
+
## Path: PRD or spec in (a document is the input)
|
|
81
|
+
|
|
82
|
+
Use this path when the user hands you a **PRD, requirements document or API spec** instead of
|
|
83
|
+
starting from a blank page. **Entry:** `/em:discover` (plugin) or `/event-modeling discover`
|
|
84
|
+
(repo skills), with the opening message **`Discover from this PRD/spec: <path>`**. **Read `reference/prd-spec-path.md`
|
|
85
|
+
and `reference/prd-rubric.md` before doing any work on it** — the path is a triage, not a
|
|
86
|
+
transcription: a document describes the system its authors imagined (resources, endpoints,
|
|
87
|
+
stack, quality targets), and a model copied from it comes out as CRUD-per-entity.
|
|
88
|
+
|
|
89
|
+
The steps, in order (detail in the reference): **0** pull the walkthroughs and name the main and
|
|
90
|
+
secondary **storylines** (the resource/endpoint reference is consulted last); **1** split into
|
|
91
|
+
single-claim statements, each quoting the source verbatim; **2** classify each against the
|
|
92
|
+
shipped rubric, plus the independent *"is this about the business, independent of how it's
|
|
93
|
+
built?"* check; **3** group by reaction (shared trigger + acting system = one slice; failure,
|
|
94
|
+
retry and timeout become outcome events and scenarios of that slice, never new slices); **4**
|
|
95
|
+
rewrite, don't drop (implementation details become business language linked to their source;
|
|
96
|
+
real tech choices and NFRs go to a constraints list that feeds the constitution); **5** record
|
|
97
|
+
`discovery/prd-triage.json` and run `em discover triage-check discovery/prd-triage.json`
|
|
98
|
+
(MCP: `discover_triage_check`) until it passes; **6** every low-confidence or disagreeing
|
|
99
|
+
statement becomes a Socratic question — never an invented answer. Rejections and parked
|
|
100
|
+
statements go in the state file's Decisions log with why, as in step 1. Then continue with
|
|
101
|
+
`discover` steps 1-4 on the surviving groups, with the storylines as the timeline's spine.
|
|
102
|
+
|
|
68
103
|
## Phase: `extract` — current-state model of an existing system
|
|
69
104
|
|
|
70
105
|
Goal: a faithful **current-state** model extracted from an existing system — the as-is sibling
|
|
@@ -76,7 +76,12 @@ it is fine to finish a round with `# TBD`s still parked.
|
|
|
76
76
|
|
|
77
77
|
- **R1 — Candidate events.** Extract (event-driven) or synthesize (procedural) the past-tense
|
|
78
78
|
facts; apply the event test; user confirms/renames/rejects. Ambiguous candidates → `# TBD`.
|
|
79
|
-
- **R2 — Timeline order.**
|
|
79
|
+
- **R2 — Timeline order.** First **name the as-is process(es)** — which business journey does the
|
|
80
|
+
system run today, and what is its outcome? Take it from the system's walkthroughs, user journeys
|
|
81
|
+
and docs, and from the people who use it — not from the OpenAPI/migrations/DTO grep, which fills
|
|
82
|
+
operations no journey touches and comes **after** (`methodology.md`, "The story, not the
|
|
83
|
+
schema"). Name the main storyline and each secondary one, then order the confirmed events into
|
|
84
|
+
that as-is narrative, never one block per entity. Identify the
|
|
80
85
|
*actual* actors/callers and the *real* UI or API surfaces (headless systems: still `ui`/`persona`
|
|
81
86
|
— one persona per caller/role, its `ui` boxes are the API calls, per `em-dsl.md`). **First
|
|
82
87
|
`em render` here.**
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# PRD/spec triage rubric — version 1.0
|
|
2
|
+
|
|
3
|
+
The shipped classification rubric for the PRD/spec path (`prd-spec-path.md`, step 2). It is data:
|
|
4
|
+
`em discover triage-check` rejects a `discovery/prd-triage.json` whose `rubricVersion` is not the
|
|
5
|
+
version below. Do not edit it per project; a changed rubric ships with a new `rubricVersion` in a
|
|
6
|
+
new `em` release.
|
|
7
|
+
|
|
8
|
+
## The independent check
|
|
9
|
+
|
|
10
|
+
Run on every statement in addition to its category: **"Is this about the business, independent of
|
|
11
|
+
how it is built?"** Record the answer as `aboutBusiness` (true/false), answering it separately from
|
|
12
|
+
the category. The table's `aboutBusiness` column is what the category *expects*.
|
|
13
|
+
|
|
14
|
+
## Categories
|
|
15
|
+
|
|
16
|
+
| Category id | What it is | aboutBusiness expected | Allowed outcomes |
|
|
17
|
+
|---|---|---|---|
|
|
18
|
+
| `business-fact` | Something that happens or is true in the business; candidate event or field. | true | modeled, rewritten, parked, question |
|
|
19
|
+
| `user-intent` | What an actor wants to accomplish; candidate command with its trigger. | true | modeled, rewritten, parked, question |
|
|
20
|
+
| `information-need` | What an actor needs to see or know to act; candidate read model. | true | modeled, rewritten, parked, question |
|
|
21
|
+
| `actor` | A person, role or calling system; candidate persona. | true | modeled, parked, question |
|
|
22
|
+
| `business-rule` | A constraint the business imposes; candidate invariant or scenario. | true | modeled, rewritten, parked, question |
|
|
23
|
+
| `external-system` | A system outside the boundary; candidate translation slice or constraint. | either | modeled, rewritten, constraint, parked, question |
|
|
24
|
+
| `implementation-detail` | How it is built. Rewritten in business language when it implies a business fact; a real tech choice goes to the constraints list. | false | rewritten, constraint, parked, question |
|
|
25
|
+
| `nfr` | Performance, availability, security, compliance: feeds the constitution, never a slice. | either | constraint, parked, question |
|
|
26
|
+
| `goal-background` | Why the product exists; context for the main storyline, not a slice. | true | parked, rewritten, question |
|
|
27
|
+
| `question` | An open question in the source; becomes a Socratic question, never an invented answer. | either | question, parked |
|
|
28
|
+
| `resource-or-endpoint` | Describes an API resource or endpoint. Rewritten to the intent it serves (one endpoint may carry several); never promoted to a command as-is. | false | rewritten, parked, question |
|
|
29
|
+
|
|
30
|
+
## Outcomes
|
|
31
|
+
|
|
32
|
+
`modeled` (joins a slice group as stated), `rewritten` (joins a group in business language, the
|
|
33
|
+
original linked through `quote`), `constraint` (constraints list), `parked` (a `reason`; also a
|
|
34
|
+
Decisions-log entry), `question` (a Socratic `question` for the human). `question` and `parked`
|
|
35
|
+
are allowed for every category: a doubt can always be asked, and an explicitly deferred intent is
|
|
36
|
+
legitimate when its `reason` says so.
|
|
37
|
+
|
|
38
|
+
## Rules the checker enforces
|
|
39
|
+
|
|
40
|
+
All of these are checked by `em discover triage-check`; write the record so they hold.
|
|
41
|
+
|
|
42
|
+
1. **Disagreement is a question.** If `aboutBusiness` contradicts the category's expectation
|
|
43
|
+
(a `business-fact` that names a table; an `implementation-detail` that states a business
|
|
44
|
+
fact), the outcome MUST be `question`. Put the proposed rewrite in the question text
|
|
45
|
+
("Is this a business fact? proposed: Stock is decremented when a pick is confirmed."); the
|
|
46
|
+
human resolves it and a later pass records `rewritten`.
|
|
47
|
+
2. **Low confidence is a question.** `confidence: low` means outcome `question`, whatever the category.
|
|
48
|
+
3. **An endpoint is never modeled as-is.** `resource-or-endpoint` is `rewritten` (to the intent it
|
|
49
|
+
serves), `parked` or `question` — never `modeled`.
|
|
50
|
+
4. **Only modeled and rewritten statements join a slice group.** They carry a declared `group` and
|
|
51
|
+
the `storyline` of that group. Every other outcome has `group: null` (and `storyline: null`),
|
|
52
|
+
except that a `question` may name the group it would join once answered (with that group's
|
|
53
|
+
storyline); that is a pointer only, never an anchor (rule 7).
|
|
54
|
+
5. `rewritten` needs `rewrite`; `parked` needs `reason`; `question` needs `question`; every
|
|
55
|
+
`constraint` appears in `constraints[]`.
|
|
56
|
+
6. **Provenance is checked, not declared.** Every statement says whether it came from a
|
|
57
|
+
`walkthrough` or from the `reference` (resource/endpoint reference, operational notes). A
|
|
58
|
+
`walkthrough` statement's quote must lie inside some storyline's span; a `reference`
|
|
59
|
+
statement's quote must lie outside every storyline span.
|
|
60
|
+
7. **A group is either anchored or reference-only.** An anchored group names a storyline and has at
|
|
61
|
+
least one `modeled` or `rewritten` `walkthrough` statement whose quote lies inside that storyline's span (a `question` never anchors: a group anchored by questions only is an error). A **reference-only
|
|
62
|
+
group** has only `reference` statements and **no storyline**: `storyline: null` on the group and
|
|
63
|
+
on its statements. It never joins a walkthrough storyline. The report lists reference-only
|
|
64
|
+
groups outside every storyline — operations no walkthrough touches; check these are not CRUD fill.
|
|
65
|
+
8. **One statement per claim.** A statement's normalised quote may not equal, contain or be contained in another statement's quote; the error names both.
|
|
66
|
+
9. **Quotes are verbatim** (Markdown emphasis marks, smart quotes and whitespace aside) and at
|
|
67
|
+
least 12 characters. A storyline `quote` is the **full** walkthrough span, start to finish.
|
|
68
|
+
|
|
69
|
+
## Rubric decisions
|
|
70
|
+
|
|
71
|
+
- `nfr` expects `aboutBusiness: either`: a retention or audit rule is a business NFR, so the check
|
|
72
|
+
must not force a disagreement on it.
|
|
73
|
+
- `external-system` also stays `either`: a system outside the boundary can be named in business
|
|
74
|
+
terms (the payment provider) or technical ones (a queue broker).
|
|
75
|
+
|
|
76
|
+
The checker cannot judge whether a classification is right, nor whether every claim in the
|
|
77
|
+
walkthrough has a statement; that is what the human review is for.
|
|
78
|
+
|
|
79
|
+
## Machine-readable copy
|
|
80
|
+
|
|
81
|
+
The same data as JSON. The checker's built-in copy is asserted identical to this block, and the
|
|
82
|
+
table above is asserted to match it, by `test/prdTriage.test.ts`.
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"rubricVersion": "1.0",
|
|
87
|
+
"independentCheck": "Is this about the business, independent of how it is built?",
|
|
88
|
+
"categories": [
|
|
89
|
+
{ "id": "business-fact", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "Something that happens or is true in the business; candidate event or field." },
|
|
90
|
+
{ "id": "user-intent", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "What an actor wants to accomplish; candidate command with its trigger." },
|
|
91
|
+
{ "id": "information-need", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "What an actor needs to see or know to act; candidate read model." },
|
|
92
|
+
{ "id": "actor", "aboutBusiness": true, "outcomes": ["modeled", "parked", "question"], "meaning": "A person, role or calling system; candidate persona." },
|
|
93
|
+
{ "id": "business-rule", "aboutBusiness": true, "outcomes": ["modeled", "rewritten", "parked", "question"], "meaning": "A constraint the business imposes; candidate invariant or scenario." },
|
|
94
|
+
{ "id": "external-system", "aboutBusiness": "either", "outcomes": ["modeled", "rewritten", "constraint", "parked", "question"], "meaning": "A system outside the boundary; candidate translation slice or constraint." },
|
|
95
|
+
{ "id": "implementation-detail", "aboutBusiness": false, "outcomes": ["rewritten", "constraint", "parked", "question"], "meaning": "How it is built. Rewritten in business language when it implies a business fact; a real tech choice goes to the constraints list." },
|
|
96
|
+
{ "id": "nfr", "aboutBusiness": "either", "outcomes": ["constraint", "parked", "question"], "meaning": "Performance, availability, security, compliance: feeds the constitution, never a slice." },
|
|
97
|
+
{ "id": "goal-background", "aboutBusiness": true, "outcomes": ["parked", "rewritten", "question"], "meaning": "Why the product exists; context for the main storyline, not a slice." },
|
|
98
|
+
{ "id": "question", "aboutBusiness": "either", "outcomes": ["question", "parked"], "meaning": "An open question in the source; becomes a Socratic question, never an invented answer." },
|
|
99
|
+
{ "id": "resource-or-endpoint", "aboutBusiness": false, "outcomes": ["rewritten", "parked", "question"], "meaning": "Describes an API resource or endpoint. Rewritten to the intent it serves (one endpoint may carry several); never promoted to a command as-is." }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# PRD/spec path — a document is the input
|
|
2
|
+
|
|
3
|
+
Read this **before doing any work on a PRD, requirements document or API spec**, together with
|
|
4
|
+
`prd-rubric.md` (the shipped classification rubric).
|
|
5
|
+
|
|
6
|
+
**Entry:** `/em:discover` (plugin) or `/event-modeling discover` (repo skills), with the opening
|
|
7
|
+
message **`Discover from this PRD/spec: <path>`**. This is the exact entry the eval protocol's
|
|
8
|
+
arm C cites. The path is a **triage**: a document
|
|
9
|
+
describes the system its authors imagined (resources, endpoints, stack, quality targets). Handed
|
|
10
|
+
one cold, the failure modes are over-decomposition along control flow, implementation flavour,
|
|
11
|
+
and CRUD-per-entity models shaped like the resource reference. The steps below prevent all three
|
|
12
|
+
by making every claim in the document earn its place in the model, visibly.
|
|
13
|
+
|
|
14
|
+
**Stance.** You are still extracting the domain from people, not inventing it. The document is
|
|
15
|
+
evidence. Anything it does not say, or says ambiguously, is a question (step 6), never a guess.
|
|
16
|
+
|
|
17
|
+
Setup: run the shared preconditions (`../../event-modeling-shared/reference/operating-principles.md`),
|
|
18
|
+
agree the input path with the user, and create `discovery/` next to the model. Record the input
|
|
19
|
+
path in the state file's Session inputs.
|
|
20
|
+
|
|
21
|
+
## Step 0 — Walkthroughs become storylines
|
|
22
|
+
|
|
23
|
+
Before splitting anything, find the document's **walkthroughs**: a PRD's user stories and
|
|
24
|
+
journeys, an API spec's Walkthroughs / use-case / "getting started" section.
|
|
25
|
+
|
|
26
|
+
- The **end-to-end journey** is the **main storyline** — the happy path, on a timeline, with no
|
|
27
|
+
branching ("a story of what success looks like"). Every other walkthrough is a **secondary
|
|
28
|
+
storyline** (retire, extend, reorganize...). Exactly one is main.
|
|
29
|
+
- The timeline is built from these. The resource/endpoint reference is consulted **last**, only to
|
|
30
|
+
fill operations no walkthrough touches.
|
|
31
|
+
- No walkthrough at all? Ask: *"what does success look like, start to finish?"* and have the
|
|
32
|
+
human first add the answer to the source document (or to a `discovery/walkthroughs.md` companion
|
|
33
|
+
that then becomes the triage `source`); a quote that is not in the source is rejected by design.
|
|
34
|
+
Do not synthesize a journey from the endpoint list.
|
|
35
|
+
- Record each storyline in `storylines[]` with its `id`, `name`, `main`, and `quote` — the **full**
|
|
36
|
+
walkthrough span, start to finish success story, verbatim (not its first sentence: the checker
|
|
37
|
+
anchors every group to this span). These become the design phase's `storyline` blocks, so the provenance travels
|
|
38
|
+
(`../../event-modeling-design/SKILL.md`, step 5; syntax in `../../event-modeling-shared/reference/em-dsl.md`).
|
|
39
|
+
|
|
40
|
+
## Step 1 — Split into single-claim statements
|
|
41
|
+
|
|
42
|
+
Split the input into **single-claim statements** — one fact, rule, need or description each. A
|
|
43
|
+
sentence with "and" usually holds two. Number them `S1`, `S2`, ... in source order. Each carries a
|
|
44
|
+
`quote` copied **verbatim** from the document (whitespace, Markdown emphasis marks and smart
|
|
45
|
+
quotes may differ; words may not; at least 12 characters). You may reword later (step 4) but never
|
|
46
|
+
in `quote`: the checker searches the document for it, and a quote it cannot find is an invented
|
|
47
|
+
claim. Every statement also records `provenance`: `walkthrough` for a claim made inside a
|
|
48
|
+
walkthrough span, `reference` for one from the resource/endpoint reference or operational notes.
|
|
49
|
+
**Every claim in a walkthrough gets a statement** — the carrier collecting, the delivery being
|
|
50
|
+
confirmed, the return before the due date — so nothing in the story is silently dropped; the
|
|
51
|
+
checker cannot see a missing one, so walk each walkthrough sentence by sentence.
|
|
52
|
+
|
|
53
|
+
## Step 2 — Classify
|
|
54
|
+
|
|
55
|
+
For each statement set:
|
|
56
|
+
|
|
57
|
+
- `category` — one id from `prd-rubric.md`.
|
|
58
|
+
- `aboutBusiness` — the independent check: *"is this about the business, independent of how it is
|
|
59
|
+
built?"* Answer it separately from the category, without looking at the category.
|
|
60
|
+
- `confidence` — `high` or `low`. Any doubt: `low` (a low-confidence statement is always a question).
|
|
61
|
+
|
|
62
|
+
When `aboutBusiness` contradicts what the category expects (the rubric's `aboutBusiness expected`
|
|
63
|
+
column), that disagreement is data, not judgement: the outcome MUST be `question` (step 4, step 6).
|
|
64
|
+
|
|
65
|
+
A `resource-or-endpoint` statement is **never promoted to a command as-is**: ask which intent(s)
|
|
66
|
+
the resource serves (one endpoint may carry several intents) and rewrite to those (step 4).
|
|
67
|
+
|
|
68
|
+
## Step 3 — Group by reaction
|
|
69
|
+
|
|
70
|
+
A **group** is one future slice. Statements sharing a **trigger** and an **acting system** are one
|
|
71
|
+
group (`groups[]`: `id`, `name`, `trigger`, `actor`, `storyline`). Follow the merged reaction
|
|
72
|
+
shape (`../../event-modeling-shared/reference/methodology.md`): a reaction, its command and its
|
|
73
|
+
event share one slice.
|
|
74
|
+
|
|
75
|
+
- **Failure, retry and timeout statements are not new slices.** They become outcome events and
|
|
76
|
+
Given/When/Then scenarios of the slice whose trigger they belong to; set `scenarioOf` to that
|
|
77
|
+
group's id.
|
|
78
|
+
- **Storyline check.** A statement joins the storyline whose **journey it advances**, not the
|
|
79
|
+
entity it mentions. A "Product" sentence in the retire walkthrough belongs to "Retire a
|
|
80
|
+
product", not to a Product lifecycle.
|
|
81
|
+
- One group per trigger-and-actor; never one group per entity or per endpoint.
|
|
82
|
+
- **A group is anchored or reference-only, never both.** An anchored group names a storyline and
|
|
83
|
+
holds at least one `walkthrough` statement quoted from inside that storyline's span. A group
|
|
84
|
+
built only from `reference` statements (operations no walkthrough touches) is reference-only:
|
|
85
|
+
`storyline: null` on the group and on its statements. It never joins a walkthrough storyline,
|
|
86
|
+
and the report lists it outside every storyline for the human to inspect.
|
|
87
|
+
- A claim is quoted once: no statement's quote may equal, contain or be contained in another's. Only `modeled`/`rewritten` walkthrough statements anchor a group; a `question` never does.
|
|
88
|
+
|
|
89
|
+
## Step 4 — Rewrite, don't drop
|
|
90
|
+
|
|
91
|
+
Nothing is silently discarded.
|
|
92
|
+
|
|
93
|
+
- An **implementation detail that implies a business fact** (*"the service writes a row to
|
|
94
|
+
`stock_levels` when a pick is confirmed"*): classify it `implementation-detail` with
|
|
95
|
+
`aboutBusiness: false` — they agree, so it is `rewritten`, with the business-language form in
|
|
96
|
+
`rewrite` (*"Stock is decremented when a pick is confirmed"*); the original stays in `quote`,
|
|
97
|
+
which is the link to its source. If you classified the same sentence `business-fact` but the
|
|
98
|
+
independent check says `false`, they **disagree**: the outcome is `question`, with the proposed
|
|
99
|
+
rewrite in the question text (*"Is this a business fact? proposed: Stock is decremented when a
|
|
100
|
+
pick is confirmed."*). The human resolves it and a later pass records `rewritten`.
|
|
101
|
+
- A **real technology choice or NFR** (*"must run on Postgres"*, *"p95 under 300 ms"*) gets outcome
|
|
102
|
+
`constraint` and an entry in `constraints[]` listing its statement ids. That list feeds the
|
|
103
|
+
project's constitution: hand it to the constitution's owner (the skills read the constitution,
|
|
104
|
+
never write it); it never becomes a slice.
|
|
105
|
+
- Anything else you set aside is `parked` with a `reason`, **and** recorded in the state file's
|
|
106
|
+
Decisions log with why (the same rule as rejected events in `discover` step 1), so it is not
|
|
107
|
+
re-proposed later.
|
|
108
|
+
|
|
109
|
+
## Step 5 — Record
|
|
110
|
+
|
|
111
|
+
Write `discovery/prd-triage.json` (UTF-8, 2-space indent):
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"prdTriageSchemaVersion": "1.0",
|
|
116
|
+
"rubricVersion": "1.0",
|
|
117
|
+
"source": "prd.md",
|
|
118
|
+
"storylines": [{ "id": "L1", "name": "Order to delivery", "main": true, "quote": "A customer places an order. We pick and ship it, and they get a tracking link." }],
|
|
119
|
+
"groups": [{ "id": "G1", "name": "Place Order", "trigger": "customer submits checkout", "actor": "Storefront", "storyline": "L1" }],
|
|
120
|
+
"statements": [
|
|
121
|
+
{ "id": "S1", "quote": "A customer places an order.", "category": "user-intent", "aboutBusiness": true, "confidence": "high", "provenance": "walkthrough", "outcome": "modeled", "group": "G1", "storyline": "L1" },
|
|
122
|
+
{ "id": "S2", "quote": "must respond within 300 ms", "category": "nfr", "aboutBusiness": false, "confidence": "high", "provenance": "reference", "outcome": "constraint", "group": null, "storyline": null },
|
|
123
|
+
{ "id": "S3", "quote": "writes a row to stock_levels", "category": "business-fact", "aboutBusiness": false, "confidence": "high", "provenance": "reference", "outcome": "question", "group": null, "storyline": null, "question": "Is this a business fact? proposed: Stock is decremented when a pick is confirmed." }
|
|
124
|
+
],
|
|
125
|
+
"constraints": [{ "id": "C1", "text": "Checkout responds within 300 ms", "statements": ["S2"] }]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Per statement: `id`, `quote`, `category`, `aboutBusiness`, `confidence`, `provenance`, `outcome`
|
|
130
|
+
(`modeled | rewritten | constraint | parked | question`), `group` and `storyline` (set for
|
|
131
|
+
`modeled`/`rewritten`, otherwise `null`), plus `rewrite` / `reason` / `question` /
|
|
132
|
+
`scenarioOf` where the outcome needs them. **Every statement has a category and an outcome;
|
|
133
|
+
every modeled or rewritten statement has a group.** The rules the checker enforces are listed in
|
|
134
|
+
`prd-rubric.md` ("Rules the checker enforces"): disagreement and low confidence are questions, an
|
|
135
|
+
endpoint is never modeled, group and storyline only for modeled/rewritten (otherwise `null`),
|
|
136
|
+
provenance verified against the storyline spans (a `walkthrough` quote lies inside one, a
|
|
137
|
+
`reference` quote outside all), no shared quotes, and every group either anchored by a walkthrough
|
|
138
|
+
statement inside its storyline's span or reference-only (`"storyline": null` on the group and its
|
|
139
|
+
statements, listed in the report outside every storyline).
|
|
140
|
+
|
|
141
|
+
Then run, and fix until it passes:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
em discover triage-check discovery/prd-triage.json # MCP: discover_triage_check
|
|
145
|
+
em discover triage-check discovery/prd-triage.json --markdown > discovery/prd-triage.md
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`--markdown` prints the human-readable view (storylines, slice groups with their statements,
|
|
149
|
+
constraints, parked, questions); save it next to the JSON. The checker verifies shape, the rubric
|
|
150
|
+
version, verbatim quotes, and the outcome rules; **it cannot judge whether your classification is
|
|
151
|
+
right**, whether every walkthrough claim has a statement, or whether the Decisions-log entry for
|
|
152
|
+
each parked or rejected statement was actually written (that entry is prose-only and unchecked) —
|
|
153
|
+
that is what the human review is for. Read the report's **reference-only groups** list: those
|
|
154
|
+
are operations no walkthrough touches; check they are not CRUD fill. Also confirm each
|
|
155
|
+
**storyline quote really is a walkthrough span**: storyline spans are self-declared and the
|
|
156
|
+
checker cannot know which sections of the document are walkthroughs. The `--markdown` view lists
|
|
157
|
+
the storylines with their quotes for exactly this review.
|
|
158
|
+
|
|
159
|
+
## Step 6 — Questions, never inventions
|
|
160
|
+
|
|
161
|
+
Every `low` confidence statement, every statement where `aboutBusiness` contradicts the
|
|
162
|
+
category's expectation, and every `question` category statement gets outcome `question` and a
|
|
163
|
+
Socratic `question` (a disagreement's question carries the proposed rewrite). Ask them one concern at a time, in the story's words. Record each answer in the state
|
|
164
|
+
file and update the record (the statement is re-classified; re-run the checker). If the document
|
|
165
|
+
and the human disagree, the human wins and the disagreement is a Decisions-log entry.
|
|
166
|
+
|
|
167
|
+
## Hand-off
|
|
168
|
+
|
|
169
|
+
Continue with `discover` steps 1-4 (`../SKILL.md`) on the surviving groups: the storylines are the
|
|
170
|
+
timeline's spine, each group seeds one slice, and the constraints list goes to the project
|
|
171
|
+
constitution. `discovery/prd-triage.json` stays in the repo as provenance for the model.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-engagement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when leading an engagement: building a named set of ratified event-modeling slices
|
|
6
6
|
(`em engagement`) into one independent PR per slice, each against main, by dispatching the
|
|
@@ -47,9 +47,17 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
|
|
|
47
47
|
beside the model, or `.specify/memory/constitution.md`). STOP if it is missing or its
|
|
48
48
|
`ratifiedBy:` is empty (spec-kit: no `**Ratified**:` footer). Say so and point at
|
|
49
49
|
`event-modeling-implement`'s §7; never draft house rules to get moving.
|
|
50
|
-
2. **Foundation
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
2. **Foundation is in the code.** Do not ask the human whether the foundation PR (implement.md
|
|
51
|
+
§8) landed — check: `em engagement foundation <model>.em <slug> --code <repo root>` (GH #240;
|
|
52
|
+
`--json` when you need the fields). It reports every event the engagement's slices emit or
|
|
53
|
+
consume as `present`, `incomplete` (which fields, which tag fields are missing — named), or
|
|
54
|
+
`missing-event`. Any `missing-event`: STOP — the foundation has not landed for that event; ask
|
|
55
|
+
for the foundation PR and confirm it merged into `main` (`gh pr view <n> --json state` shows
|
|
56
|
+
`MERGED`), then re-run. Any `incomplete`: **one question to the human**, listing every gap the
|
|
57
|
+
report names (an implementer never discovers these alone) — the fix is a foundation follow-up
|
|
58
|
+
on `main`, never a slice PR. All `present`: go on. No slice branch is cut before this is clean.
|
|
59
|
+
The check is a text scan of the target tree, not a compiler: a `present` event may still fail
|
|
60
|
+
to type-check in the slice PR, and that is the slice PR's job to surface.
|
|
53
61
|
3. **Agent models.** Read the line `- **Agent models:** implementer=<model>,
|
|
54
62
|
validator=<model>, reviewer=<model>, critic=<model|codex>`. If it is absent, say once:
|
|
55
63
|
"no Agent models line — using implementer=sonnet, validator=sonnet, reviewer=sonnet,
|
|
@@ -72,12 +80,23 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
|
|
|
72
80
|
Run `em engagement plan <model>.em <slug>` (`--json` when you need the fields). Present it in
|
|
73
81
|
plain terms: each level, its width against the ceiling (`parallel`), each slice's branch (every
|
|
74
82
|
base is `main`), and every held slice with its reason (`not-ready`,
|
|
75
|
-
`upstream-outside-engagement-unmerged`, or `human`). Then
|
|
83
|
+
`upstream-outside-engagement-unmerged`, or `human`). Then the plan's **`pre-flight:` block** (GH
|
|
84
|
+
#239): the model-wide gaps the engagement's slices share — a `repeated-invariant` with no single
|
|
85
|
+
enforcing slice, an `event-without-tag` whose consistency boundary is undeclared, a
|
|
86
|
+
`shared-trigger` (one `ui`, two slices, no endpoint owner), a `doc-model-mismatch`, a `shape` (a
|
|
87
|
+
`em validate --shape` lint fires on the slices; the answer is a `shape-accepted: <rule> <refs> —
|
|
88
|
+
<reason>` bullet in `.event-modeling.md` `## Decisions log`, or a model fix). These are
|
|
89
|
+
exactly what every implementer would otherwise stop on and report separately. Put them to the
|
|
90
|
+
human **in the same single question round** as the ceiling, one bullet each with the slices it
|
|
91
|
+
spans, and ask for a ruling on each (the answer goes where it belongs: the model, the foundation
|
|
92
|
+
PR, a slice doc, or `.event-modeling.md` for a deferral). Then ask exactly one question:
|
|
76
93
|
|
|
77
94
|
> "Ceiling N from the plan; proceed?"
|
|
78
95
|
|
|
79
96
|
Ask it once per engagement. If the human names a lower number, use it for this session. **Never
|
|
80
97
|
ask "which slice first"**: the levels decide the order, and the ceiling decides how many at once.
|
|
98
|
+
A pre-flight finding never holds a slice: if the human says "proceed anyway" on one, dispatch
|
|
99
|
+
and make sure each implementer's brief carries the ruling, so no agent rediscovers it.
|
|
81
100
|
A held slice is never started; the plan releases it when its hold clears.
|
|
82
101
|
|
|
83
102
|
## 3. Per level: cut the worktree, then dispatch the implementer
|
|
@@ -154,7 +173,10 @@ You never merge.
|
|
|
154
173
|
`main`: `git switch -c engagement/<slug>-level-<n> main`, run
|
|
155
174
|
`em slice mark-implemented <model>.em <key> <pr-url>` for each slice merged in the level,
|
|
156
175
|
then `em slice index <model>.em`, commit, and `gh pr create --base main`. The human merges it
|
|
157
|
-
like any other PR.
|
|
176
|
+
like any other PR. If `mark-implemented` printed `opened draft v<n+1>` for a slice, its doc in
|
|
177
|
+
this PR reads `status: draft`: say so in the hand-back and paste the command's notice into the PR
|
|
178
|
+
body — `shippedVersion:`/`implementedIn:` are the record that v<n> was implemented, `status:` is
|
|
179
|
+
the next version's state, so the reviewer does not read it as a slice that was never marked.
|
|
158
180
|
4. Recompute: `em engagement plan <model>.em <slug>`. A merge can release an
|
|
159
181
|
`upstream-outside-engagement-unmerged` hold once that upstream's doc reads `implemented`.
|
|
160
182
|
Continue with step 3 for anything newly startable.
|
|
@@ -74,11 +74,12 @@ constitution. The implementer stops and reports it as the doc line plus the ques
|
|
|
74
74
|
4. Carry on with every other startable slice. Never answer the question yourself, never edit the
|
|
75
75
|
doc, and never let the implementer guess.
|
|
76
76
|
|
|
77
|
-
A question the build can finish without (it does not block the slice) is not a gap:
|
|
77
|
+
A question the build can finish without (it does not block the slice) is not a gap: defer it with
|
|
78
78
|
`em slice defer <model>.em <key> "<question>" --until v<n> --decision "<what this version does>"`
|
|
79
|
-
(GH #
|
|
80
|
-
|
|
81
|
-
at merge opens v<
|
|
79
|
+
(GH #253). On a ratified doc that appends the already-deferred `- [x]` item to the doc's Open
|
|
80
|
+
Questions, outside `ratifiedHash` — the hash and `--slice-ready` stay green, and the question is
|
|
81
|
+
visible in the ratified doc; `mark-implemented` at merge opens v<n> as a draft with it reopened
|
|
82
|
+
as `- [ ]`. Never write a `- [ ]` into the
|
|
82
83
|
ratified doc, and do not run `em slice revise` for it (an unshipped ratified doc refuses
|
|
83
84
|
`revise` without `--withdraw`).
|
|
84
85
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.18.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when building a single ratified event-modeling slice (status: ready-to-implement) into
|
|
6
6
|
merged, tested code — the one phase where the agent builds rather than facilitates. Gates on
|