@milehimikey/em 1.14.1 → 1.15.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 +3 -3
- package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
- package/.claude/skills/event-modeling-design/SKILL.md +29 -18
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-engagement/SKILL.md +54 -54
- package/.claude/skills/event-modeling-engagement/reference/engagement.md +5 -19
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +29 -23
- package/.claude/skills/event-modeling-review/SKILL.md +13 -3
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +230 -227
- package/.claude/skills/event-modeling-shared/reference/operating-principles.md +3 -3
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +58 -27
- package/.claude/skills/event-modeling-shared/templates/constitution.md +5 -7
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +12 -0
- package/dist/catalog/docJoin.d.ts +17 -1
- package/dist/catalog/docJoin.js +7 -1
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/driftSignal.d.ts +16 -12
- package/dist/catalog/driftSignal.js +14 -9
- package/dist/catalog/driftSignal.js.map +1 -1
- package/dist/catalog/sliceDoc.d.ts +51 -0
- package/dist/catalog/sliceDoc.js +47 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.js +12 -0
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/cli/conformScope.d.ts +4 -0
- package/dist/cli/conformScope.js +2 -2
- package/dist/cli/conformScope.js.map +1 -1
- package/dist/cli/coverage.js +7 -3
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.d.ts +61 -2
- package/dist/cli/defer.js +204 -23
- package/dist/cli/defer.js.map +1 -1
- package/dist/cli/engagement.d.ts +13 -5
- package/dist/cli/engagement.js +26 -19
- package/dist/cli/engagement.js.map +1 -1
- package/dist/cli/findings.d.ts +2 -2
- package/dist/cli/findings.js +2 -2
- package/dist/cli/frontmatterSurgery.d.ts +3 -3
- package/dist/cli/frontmatterSurgery.js +3 -3
- package/dist/cli/frontmatterSurgery.js.map +1 -1
- package/dist/cli/markImplemented.d.ts +20 -9
- package/dist/cli/markImplemented.js +112 -14
- package/dist/cli/markImplemented.js.map +1 -1
- package/dist/cli/ratify.d.ts +36 -6
- package/dist/cli/ratify.js +130 -35
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/review.js +3 -3
- package/dist/cli/review.js.map +1 -1
- package/dist/cli/revise.d.ts +57 -0
- package/dist/cli/revise.js +207 -0
- package/dist/cli/revise.js.map +1 -0
- package/dist/cli/sliceConform.d.ts +4 -3
- package/dist/cli/sliceConform.js +29 -12
- package/dist/cli/sliceConform.js.map +1 -1
- package/dist/cli/status.d.ts +8 -0
- package/dist/cli/status.js +7 -4
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/upgrade.js +7 -4
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli.js +118 -77
- package/dist/cli.js.map +1 -1
- package/dist/emit/json.d.ts +1 -1
- package/dist/emit/json.js +13 -1
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +4 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/mcp/server.js +5 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/rules.d.ts +8 -0
- package/dist/model/rules.js +8 -0
- package/dist/model/rules.js.map +1 -1
- package/dist/model/sliceDocIndex.d.ts +3 -0
- package/dist/model/sliceDocIndex.js +5 -4
- package/dist/model/sliceDocIndex.js.map +1 -1
- package/dist/templates.d.ts +1 -1
- package/dist/templates.js +5 -7
- package/dist/templates.js.map +1 -1
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/shared/reference/em-dsl.md +230 -227
- package/plugin/shared/reference/operating-principles.md +3 -3
- package/plugin/shared/reference/slice-doc-schema.md +58 -27
- package/plugin/shared/templates/constitution.md +5 -7
- package/plugin/skills/conform/SKILL.md +1 -1
- package/plugin/skills/design/SKILL.md +29 -18
- package/plugin/skills/discover/SKILL.md +1 -1
- package/plugin/skills/engagement/SKILL.md +54 -54
- package/plugin/skills/engagement/reference/engagement.md +5 -19
- package/plugin/skills/event-modeling/SKILL.md +3 -3
- package/plugin/skills/implement/SKILL.md +1 -1
- package/plugin/skills/implement/reference/implement.md +29 -23
- package/plugin/skills/review/SKILL.md +13 -3
- package/dist/cli/reratify.d.ts +0 -58
- package/dist/cli/reratify.js +0 -238
- package/dist/cli/reratify.js.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.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
|
|
7
7
|
`.event-modeling.md` state (or the given phase name) and routes to the right focused skill —
|
|
8
8
|
event-modeling-discover, event-modeling-design, event-modeling-implement, event-modeling-conform,
|
|
9
9
|
or event-modeling-review — or, for building a planned set of ready slices through scoped
|
|
10
|
-
sub-agents to
|
|
10
|
+
sub-agents to one PR per slice against main (an `em engagement`), event-modeling-engagement. If you already
|
|
11
11
|
know which of those applies — starting a new model, extracting from existing code,
|
|
12
12
|
slicing/writing specs, implementing a ratified slice, leading an engagement, checking drift, or
|
|
13
13
|
running a live/stakeholder view — invoke that skill directly instead of this one.
|
|
@@ -28,7 +28,7 @@ phase lives in.
|
|
|
28
28
|
| `implement` | `event-modeling-implement` — building one ratified slice into merged, tested code |
|
|
29
29
|
| `conform`, `validate` | `event-modeling-conform` — drift-checking a model against its codebase, walking validation diagnostics |
|
|
30
30
|
| `watch`, `review` | `event-modeling-review` — the live browser viewer, facilitated stakeholder walkthroughs |
|
|
31
|
-
| `engagement` | `event-modeling-engagement` — build a planned set of ready slices through scoped sub-agents to
|
|
31
|
+
| `engagement` | `event-modeling-engagement` — build a planned set of ready slices through scoped sub-agents to one PR per slice, each against main |
|
|
32
32
|
|
|
33
33
|
## Routing logic
|
|
34
34
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-conform
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-design
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.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
|
|
@@ -51,10 +51,10 @@ evidence"). In short:
|
|
|
51
51
|
- **Evidence rule.** The `.em` model and the slice docs are the evidence for modeling
|
|
52
52
|
decisions. Never read implementation source, generated contracts or `specs/` to decide a
|
|
53
53
|
modeling question — ask the user. Code is read only in `extract` and `conform`.
|
|
54
|
-
- **Version rule.** Never bump a draft's `version:` on edit. Before any `em slice
|
|
54
|
+
- **Version rule.** Never bump a draft's `version:` on edit. Before any `em slice revise`,
|
|
55
55
|
run `em status <model>.em --json`: pre-release = the model's `modelVersion` entry has
|
|
56
|
-
`design: null` **and** `slices.byStatus.
|
|
57
|
-
`
|
|
56
|
+
`design: null` **and** `slices.byStatus.shipped === 0`. Pre-release → never run
|
|
57
|
+
`revise`; edit `draft`/`reviewed` docs in place. Released → the revision path in
|
|
58
58
|
the `slice` phase below.
|
|
59
59
|
- **Pre-commit check.** Stage the session's files, run `em system scope --staged` (STOP on any
|
|
60
60
|
`seam-crossing`), then `git diff --cached --name-only` (STOP on any path outside this model's
|
|
@@ -151,7 +151,7 @@ For each slice:
|
|
|
151
151
|
it in place and leave its `version:` alone. If `slices/<slice-name>.md` already exists with
|
|
152
152
|
`status: implemented` (or is ratified and needs a change), run `em status <model>.em --json`
|
|
153
153
|
first. **Pre-release** (the model's `modelVersion` entry has `design: null` and
|
|
154
|
-
`slices.byStatus.
|
|
154
|
+
`slices.byStatus.shipped === 0`): never run `em slice revise`; a ratified doc holds a
|
|
155
155
|
human sign-off, so STOP, park the change as an open question, and let the ratifier decide.
|
|
156
156
|
**Released** (either condition false): a doc with `status: implemented` is a
|
|
157
157
|
re-ratification, not fresh authoring: hold a Socratic
|
|
@@ -212,6 +212,11 @@ For each slice:
|
|
|
212
212
|
`--slice-ready` refuses it). A doc written before em 1.14 has no markers; leave it as it is
|
|
213
213
|
unless you are re-creating it (`em slice new … --wire --force`, carrying the prose across).
|
|
214
214
|
A question this version will not answer is deferred with `em slice defer <model> <key> "<question>" --until v<n> --decision "<what this version does>"` — never left `- [ ]`, never deleted, never answered by guessing.
|
|
215
|
+
When the question lives on the diagram as an `issue "..."` note rather than on the doc, use
|
|
216
|
+
`em slice defer <model> <key> --from-issue "<text>" --until v<n> --decision "<what this version does>"`
|
|
217
|
+
instead: it writes the deferred item into the doc's Open Questions and removes the note in one
|
|
218
|
+
step. A question that is *answered* is an edit to the authored section plus deleting the note —
|
|
219
|
+
never a deferral.
|
|
215
220
|
2. **First-time authoring:** scaffold the doc mechanically rather than hand-writing the
|
|
216
221
|
frontmatter — `em slice new "<slice name>" --pattern <state-change|state-view|automation|
|
|
217
222
|
translation> --swimlane "<Persona> → <Context>" --wire <model>.em` writes `slices/<slice-name>.md`
|
|
@@ -236,23 +241,29 @@ For each slice:
|
|
|
236
241
|
lineage key(s) by hand (`split-from`/`merged-from`/`superseded-by`, `<slice-key>@v<N>` grammar
|
|
237
242
|
— see `../event-modeling-shared/reference/slice-doc-schema.md` for the full schema; `em validate` catches a malformed one
|
|
238
243
|
after the fact, see the `lineage-*` rules below).
|
|
239
|
-
**
|
|
244
|
+
**Revision (step 0) — released models only.** Confirm the model is released first
|
|
240
245
|
(`em status <model>.em --json`: the `modelVersion` entry's `design` is not `null`, or
|
|
241
|
-
`slices.byStatus.
|
|
246
|
+
`slices.byStatus.shipped > 0`); on a pre-release model never run `revise`. The doc
|
|
242
247
|
already exists, so `em slice new` doesn't apply here
|
|
243
248
|
(it refuses to overwrite an existing file without `--force`, and forcing would blow away the
|
|
244
|
-
doc's authored body) — run `em slice
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
`
|
|
249
|
+
doc's authored body) — run `em slice revise <model>.em <slice-key>` instead (MIL-283): it
|
|
250
|
+
opens the next version as a **`draft`** in the existing frontmatter — `version` bumped,
|
|
251
|
+
`status: draft`, the prior version's review and sign-off cleared — while the shipped version
|
|
252
|
+
stays shipped in the shipped record (`implementedIn:`/`shippedVersion:`, untouched). If a
|
|
253
|
+
question was deferred to this version, `em slice mark-implemented` already opened the draft
|
|
254
|
+
at merge and the question is back on the list; `revise` then refuses ("the next version is
|
|
255
|
+
already open") and you simply edit. The same command revises a ratified doc that **never
|
|
256
|
+
shipped** (`ready-to-implement` with `ratifiedBy` set — a gap answered mid-build): the
|
|
257
|
+
ratification is withdrawn and the draft opens. Either way the new version is a new spec:
|
|
258
|
+
write the delta into `## Delta`, walk it in a review session (`em slice review --by`), and
|
|
259
|
+
only then does `em slice ratify --by <name>` sign it. **Commit before ratifying (MIL-284):**
|
|
260
|
+
`em slice ratify` records the commit and body hash it signs and refuses a doc with uncommitted
|
|
261
|
+
changes — finish the doc's edits (deferrals included: `em slice defer` rewrites a body line, so
|
|
262
|
+
a deferral after sign-off trips `slice-ready-body-changed-since-ratification`), commit, then
|
|
263
|
+
ratify. A `draft`/`reviewed` doc is simply edited, and its `version:` never moves.
|
|
254
264
|
**Public-touching slices (MIL-238).** On a slice that owns a `public` command, event or view,
|
|
255
|
-
`em slice ratify --by <name>`
|
|
265
|
+
`em slice ratify --by <name>` refuses without one of two flags (`revise` takes neither — the
|
|
266
|
+
confirmation belongs to the new version's ratification): pass
|
|
256
267
|
`--meaning-unchanged` when this version does not change what the public contract means, or
|
|
257
268
|
`--contract-change "<why>"` when a consumer must read the change differently. Without
|
|
258
269
|
either, both refuse with `slice "<key>" touches the public surface — pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-discover
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.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
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-engagement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when leading an engagement: building a named set of ratified event-modeling slices
|
|
6
|
-
(`em engagement`) into
|
|
7
|
-
em-reviewer and em-critic sub-agents, level by level, and handing
|
|
8
|
-
|
|
9
|
-
build one slice by hand, use event-modeling-implement instead.
|
|
6
|
+
(`em engagement`) into one independent PR per slice, each against main, by dispatching the
|
|
7
|
+
em-implementer, em-validator, em-reviewer and em-critic sub-agents, level by level, and handing
|
|
8
|
+
the human each PR with its evidence as it passes review. The lead session orchestrates and never
|
|
9
|
+
writes slice code itself. To build one slice by hand, use event-modeling-implement instead.
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Event Modeling — engagement (lead session)
|
|
13
13
|
|
|
14
14
|
Goal: take an engagement (a named chunk of the model, `<model dir>/engagements/<slug>.md`) from
|
|
15
15
|
its plan to merged PRs. You are the **lead**: you cut worktrees, dispatch scoped sub-agents,
|
|
16
|
-
record every step in the Ledger with `em engagement set`, and hand the human
|
|
17
|
-
merge
|
|
16
|
+
record every step in the Ledger with `em engagement set`, and hand the human one PR per slice,
|
|
17
|
+
each cut from and targeting `main`, to merge in any order. You never write slice code, never
|
|
18
|
+
merge, and never rebase a slice branch.
|
|
19
|
+
|
|
20
|
+
An engagement is a *related set* of isolated slices — a workflow, a lifecycle — built together.
|
|
21
|
+
It is not a stack: no slice branch is ever cut from another slice's branch, and no PR ever
|
|
22
|
+
targets another PR (MIL-280). The foundation PR (implement.md §8) already holds every event, and
|
|
23
|
+
a slice never reaches into a sibling's code (§8 rule 3), so each PR compiles, tests and merges
|
|
24
|
+
on its own. Levels order the work for the human's review and your dispatch; they never gate a
|
|
25
|
+
merge.
|
|
18
26
|
|
|
19
27
|
**Read `reference/engagement.md` before the first dispatch.** It holds the Ledger state machine,
|
|
20
|
-
the evidence bundle format, the
|
|
21
|
-
|
|
28
|
+
the evidence bundle format, the gap protocol and the model-selection rule this file uses by
|
|
29
|
+
name. Each sub-agent runs `event-modeling-implement`'s contract
|
|
22
30
|
(`../event-modeling-implement/reference/implement.md`) for its one slice; that contract is
|
|
23
31
|
theirs, not yours.
|
|
24
32
|
|
|
@@ -42,21 +50,17 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
|
|
|
42
50
|
2. **Foundation PR merged.** Ask the human for the foundation PR (implement.md §8) and confirm it
|
|
43
51
|
has merged into `main` (`gh pr view <n> --json state` shows `MERGED`). STOP if there is none
|
|
44
52
|
or it is still open. No slice branch is cut before it lands.
|
|
45
|
-
3. **
|
|
46
|
-
`- **Merge strategy:** merge-commits-when-stacked`. STOP if the line is absent or names any
|
|
47
|
-
other value: tell the human the engagement needs that norm and point at the constitution
|
|
48
|
-
template's "Review and merge norms" prompt
|
|
49
|
-
(`../event-modeling-shared/templates/constitution.md`). The constitution is the human's to
|
|
50
|
-
amend and ratify, never yours.
|
|
51
|
-
4. **Agent models.** Read the line `- **Agent models:** implementer=<model>,
|
|
53
|
+
3. **Agent models.** Read the line `- **Agent models:** implementer=<model>,
|
|
52
54
|
validator=<model>, reviewer=<model>, critic=<model|codex>`. If it is absent, say once:
|
|
53
55
|
"no Agent models line — using implementer=sonnet, validator=sonnet, reviewer=sonnet,
|
|
54
56
|
critic=opus", and proceed. Apply the model-selection rule in `reference/engagement.md`
|
|
55
|
-
(the critic never runs on the implementer's model).
|
|
56
|
-
|
|
57
|
+
(the critic never runs on the implementer's model). A constitution that still carries a
|
|
58
|
+
`- **Merge strategy:**` line from em ≤ 1.14.2 is fine: the line is ignored, never a reason to
|
|
59
|
+
stop — PRs merge with whatever strategy the project uses.
|
|
60
|
+
4. **Worktrees are ignored.** `git check-ignore -q .claude/worktrees/x` must succeed. If it
|
|
57
61
|
fails, STOP and ask the human to add `.claude/worktrees/` to `.gitignore` in its own commit
|
|
58
62
|
on `main`.
|
|
59
|
-
|
|
63
|
+
5. **The engagement exists.** `em engagement status <model>.em <slug>`. If there is no such
|
|
60
64
|
engagement, ask the human which slices it covers (a list, a context, or "everything
|
|
61
65
|
downstream of X") and run `em engagement new <model>.em <slug> --slices a,b,c` (or
|
|
62
66
|
`--context <C>`, or `--downstream-of <ref>`) `--by "<their name>"`. When `new` warns that the
|
|
@@ -66,9 +70,9 @@ Run the shared preconditions first (tool check, bundle currency, locate the mode
|
|
|
66
70
|
## 2. Plan and confirm the ceiling once
|
|
67
71
|
|
|
68
72
|
Run `em engagement plan <model>.em <slug>` (`--json` when you need the fields). Present it in
|
|
69
|
-
plain terms: each level, its width against the ceiling (`parallel`), each slice's branch
|
|
70
|
-
base, and every held slice with its reason (`not-ready`,
|
|
71
|
-
`
|
|
73
|
+
plain terms: each level, its width against the ceiling (`parallel`), each slice's branch (every
|
|
74
|
+
base is `main`), and every held slice with its reason (`not-ready`,
|
|
75
|
+
`upstream-outside-engagement-unmerged`, or `human`). Then ask exactly one question:
|
|
72
76
|
|
|
73
77
|
> "Ceiling N from the plan; proceed?"
|
|
74
78
|
|
|
@@ -78,13 +82,14 @@ A held slice is never started; the plan releases it when its hold clears.
|
|
|
78
82
|
|
|
79
83
|
## 3. Per level: cut the worktree, then dispatch the implementer
|
|
80
84
|
|
|
81
|
-
Work level by level, in order
|
|
82
|
-
|
|
83
|
-
to the ceiling of slices in flight (`building`, `validating` or `review`)
|
|
84
|
-
parallel
|
|
85
|
+
Work level by level, in order: a level's slices are dispatched before the next level's, so the
|
|
86
|
+
human sees upstream slices first. Nothing in level n+1 waits for a merge — every slice is cut
|
|
87
|
+
from `main`. Keep up to the ceiling of slices in flight (`building`, `validating` or `review`)
|
|
88
|
+
at once, dispatched in parallel; when a slot frees, take the next not-held slice in level order.
|
|
89
|
+
For each slice the plan lists as not held:
|
|
85
90
|
|
|
86
|
-
1. Take `base` from the plan for this slice
|
|
87
|
-
|
|
91
|
+
1. Take `base` from the plan for this slice. It is always `main`. **Never the current HEAD**,
|
|
92
|
+
never another slice's branch, and never a branch you picked yourself.
|
|
88
93
|
2. If `impl/<key>` already exists (`git rev-parse --verify --quiet impl/<key>`) or
|
|
89
94
|
`.claude/worktrees/<key>` already exists, STOP for that slice and report it. Never delete,
|
|
90
95
|
reuse or reset someone's branch.
|
|
@@ -94,17 +99,16 @@ parallel. For each slice the plan lists as not held:
|
|
|
94
99
|
`em engagement set <model>.em <slug> <key> --state building --branch impl/<key> --base <base>`
|
|
95
100
|
5. Dispatch `em-implementer` (`em:em-implementer` under the plugin) on the implementer model.
|
|
96
101
|
Its prompt is ONLY the slice key and the absolute worktree path. It reads its own spec, the
|
|
97
|
-
constitution and the implement contract. Give it no plan, no other slice, and no merge
|
|
98
|
-
|
|
102
|
+
constitution and the implement contract. Give it no plan, no other slice, and no merge
|
|
103
|
+
instructions.
|
|
99
104
|
|
|
100
105
|
## 4. Validate, review, criticise
|
|
101
106
|
|
|
102
107
|
When the implementer returns a PR URL (and a per-invariant test map):
|
|
103
108
|
|
|
104
109
|
1. `em engagement set <model>.em <slug> <key> --state validating --pr <url>`. Check the PR's
|
|
105
|
-
base: `gh pr view <url> --json baseRefName` must
|
|
106
|
-
|
|
107
|
-
base.
|
|
110
|
+
base: `gh pr view <url> --json baseRefName` must be `main`. If not, fix it with
|
|
111
|
+
`gh pr edit <url> --base main`. That is a lead step; the implementer never changes a base.
|
|
108
112
|
2. Dispatch `em-validator` (`em:em-validator`) with the slice key and the worktree path. It
|
|
109
113
|
returns one PASS/FAIL line per check and `OVERALL: PASS` or a failure.
|
|
110
114
|
3. On `OVERALL: PASS`: `em engagement set <model>.em <slug> <key> --state review`. Dispatch
|
|
@@ -125,36 +129,31 @@ When the implementer returns a PR URL (and a per-invariant test map):
|
|
|
125
129
|
human.
|
|
126
130
|
6. `minor` findings do not loop. They go in the evidence bundle.
|
|
127
131
|
|
|
128
|
-
## 5. Hand the human
|
|
132
|
+
## 5. Hand the human each PR as it passes
|
|
129
133
|
|
|
130
134
|
When a slice passes review: `em engagement set <model>.em <slug> <key> --state awaiting-merge`.
|
|
131
|
-
Hand the human the
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- delete the head branch on merge, so GitHub retargets the PRs that stacked on it.
|
|
135
|
+
Hand the human the PR with its evidence bundle (`reference/engagement.md`): the validator table,
|
|
136
|
+
the reviewer's and critic's findings and any disagreement, and the per-invariant test map. Every
|
|
137
|
+
PR is independent — against `main`, carrying only its own slice — so the human merges them in
|
|
138
|
+
any order, with the project's usual merge strategy (squash included), and nothing else needs
|
|
139
|
+
retargeting or restacking. Suggest level order (upstream slices first) because it reads better,
|
|
140
|
+
not because anything depends on it.
|
|
138
141
|
|
|
139
142
|
You never merge.
|
|
140
143
|
|
|
141
144
|
## 6. After each human merge
|
|
142
145
|
|
|
143
146
|
1. Update `main` in your own checkout: `git switch main && git pull --ff-only`.
|
|
144
|
-
2.
|
|
145
|
-
must be empty. For each PR still listed (the head branch was not deleted),
|
|
146
|
-
`gh pr edit <n> --base main`. Then record the new base on each dependent, keeping its state:
|
|
147
|
-
`em engagement set <model>.em <slug> <dependent> --state <its state> --base main`.
|
|
148
|
-
3. `em engagement set <model>.em <slug> <key> --state merged`, then remove the worktree:
|
|
147
|
+
2. `em engagement set <model>.em <slug> <key> --state merged`, then remove the worktree:
|
|
149
148
|
`git worktree remove .claude/worktrees/<key>`.
|
|
150
|
-
|
|
149
|
+
3. When every slice of a level is `merged` or `gap`, open one follow-up PR for that level from
|
|
151
150
|
`main`: `git switch -c engagement/<slug>-level-<n> main`, run
|
|
152
151
|
`em slice mark-implemented <model>.em <key> <pr-url>` for each slice merged in the level,
|
|
153
152
|
then `em slice index <model>.em`, commit, and `gh pr create --base main`. The human merges it
|
|
154
153
|
like any other PR.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
step 3 for anything newly startable.
|
|
154
|
+
4. Recompute: `em engagement plan <model>.em <slug>`. A merge can release an
|
|
155
|
+
`upstream-outside-engagement-unmerged` hold once that upstream's doc reads `implemented`.
|
|
156
|
+
Continue with step 3 for anything newly startable.
|
|
158
157
|
|
|
159
158
|
## 7. Gaps
|
|
160
159
|
|
|
@@ -182,11 +181,12 @@ constitution), follow the gap protocol (`reference/engagement.md`):
|
|
|
182
181
|
| Rule | Because |
|
|
183
182
|
|---|---|
|
|
184
183
|
| Never hand-edit `engagements/<slug>.md` | `em engagement set` and `close` are the only write paths; the Ledger table is generated |
|
|
185
|
-
| Never
|
|
186
|
-
| Never
|
|
184
|
+
| Never cut a slice branch from another slice's branch, or make a PR target another PR | Every slice PR is cut from and targets `main` (MIL-280); a stack turns isolated slices into one landing and adds merge ceremony the contract never needed |
|
|
185
|
+
| Never rebase a slice branch | The branch is the implementer's; the lead orchestrates and records, it does not rewrite history |
|
|
187
186
|
| Never run the implementer's work yourself | The lead orchestrates; code comes from a scoped implementer working from its own read of the spec |
|
|
188
187
|
| Never dispatch beyond the ceiling | The ceiling was confirmed once for the engagement; exceeding it breaks that agreement |
|
|
189
|
-
| Never cut a slice branch from the current HEAD | The base
|
|
190
|
-
| Never
|
|
188
|
+
| Never cut a slice branch from the current HEAD | The base is `main` from the plan; the lead's HEAD may be anything |
|
|
189
|
+
| Never hold a PR back for an upstream merge | Slices do not depend on each other's branches (§8 rules 2 and 3); level order is for reading, not gating |
|
|
190
|
+
| Never merge a PR | The human merges, in any order |
|
|
191
191
|
| Never show the critic the reviewer's findings | The critic's value is an independent view; disagreement is a finding |
|
|
192
192
|
| Never start a held slice, or ask "which slice first" | The plan decides order and holds; the human confirms only the ceiling |
|
|
@@ -26,17 +26,17 @@ closed engagement refuses every `set`.
|
|
|
26
26
|
`em engagement close <model>.em <slug>` succeeds only when every slice is `merged` (recorded or
|
|
27
27
|
inferred) or `gap`; `em engagement status` reports this as `closable`.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
Every slice's `base` is `main` (MIL-280): recorded once at `building`, never changed. A Ledger
|
|
30
|
+
that still shows an `impl/<upstream>` base came from em ≤ 1.14.2; `plan` reports `main` and the
|
|
31
|
+
next `set` on that slice should record `--base main`.
|
|
31
32
|
|
|
32
33
|
## The evidence bundle (step 5)
|
|
33
34
|
|
|
34
|
-
Hand the human one block per PR
|
|
35
|
+
Hand the human one block per PR as it passes review, in this shape:
|
|
35
36
|
|
|
36
37
|
```markdown
|
|
37
38
|
### <level n> · `<key>` · <PR URL>
|
|
38
|
-
Base:
|
|
39
|
-
Merge with: a merge commit (<a dependent is open | squash allowed: no open dependent>)
|
|
39
|
+
Base: `main` · Ledger: awaiting-merge · Independent: merges in any order with the project's usual strategy
|
|
40
40
|
|
|
41
41
|
Validator (em-validator, <model>):
|
|
42
42
|
| Check | Result |
|
|
@@ -60,20 +60,6 @@ Per-invariant tests (from em-implementer):
|
|
|
60
60
|
|
|
61
61
|
Copy the agents' lines verbatim; never summarise a finding away.
|
|
62
62
|
|
|
63
|
-
## The retarget check (step 6.2)
|
|
64
|
-
|
|
65
|
-
GitHub retargets every open PR whose base was a merged head branch to the merged PR's base, but
|
|
66
|
-
only when that head branch is deleted. After each merge of `impl/<key>`:
|
|
67
|
-
|
|
68
|
-
1. `gh pr list --base impl/<key> --state open --json number,headRefName` must return `[]`.
|
|
69
|
-
2. For each PR it does list, run `gh pr edit <number> --base main`. Then record it:
|
|
70
|
-
`em engagement set <model>.em <slug> <dependent> --state <its current state> --base main`.
|
|
71
|
-
3. Confirm with `gh pr view <number> --json baseRefName`.
|
|
72
|
-
|
|
73
|
-
Because the lower PR merged with a merge commit, the dependent's diff against `main` shrinks to
|
|
74
|
-
its own commits by itself. Never rebase it. If its diff still shows the upstream's commits, the
|
|
75
|
-
lower PR was squashed: STOP and tell the human. Restacking that PR is their decision.
|
|
76
|
-
|
|
77
63
|
## The gap protocol (step 7)
|
|
78
64
|
|
|
79
65
|
A gap is a question only the model can answer: the doc is wrong, incomplete, or contradicts the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-implement
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.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
|
|
@@ -158,11 +158,15 @@ undocumented ordering, a contradiction with adjacent code. The discipline:
|
|
|
158
158
|
answered open question or a small ratified delta alongside your fix, so the decision is
|
|
159
159
|
recorded instead of buried in an implementation diff.
|
|
160
160
|
- **How a delta is ratified on a doc that never shipped** (it is `ready-to-implement` with
|
|
161
|
-
`ratifiedBy` set): once the human has answered, the doc changes by `em slice
|
|
162
|
-
<model>.em <slice-key>` (
|
|
163
|
-
the
|
|
164
|
-
|
|
165
|
-
|
|
161
|
+
`ratifiedBy` set): once the human has answered, the doc changes by `em slice revise
|
|
162
|
+
<model>.em <slice-key>` (MIL-283: opens the next version as a `draft` — `version:` bumped,
|
|
163
|
+
the old sign-off cleared; the ratification of the unshipped version is withdrawn),
|
|
164
|
+
the answer is written into the doc and committed, the room reviews it (`em slice review
|
|
165
|
+
--by`), and the human re-signs with `em slice ratify
|
|
166
|
+
<model>.em <slice-key> --by <name>` (it records the commit it signs and refuses uncommitted
|
|
167
|
+
changes, MIL-284) — on a slice owning a `public` element that `ratify` also needs
|
|
168
|
+
`--meaning-unchanged` or `--contract-change "<why>"` (MIL-238; `revise` takes neither — the
|
|
169
|
+
confirmation belongs to the new version's sign-off). That is the human's step, not
|
|
166
170
|
yours — you never run `ratify`, and
|
|
167
171
|
the doc is not ratified again until they do; resume the build after that.
|
|
168
172
|
- **Never edit the ratified doc to record your own answer**, and never quietly pick a behavior
|
|
@@ -228,7 +232,15 @@ a bump here is a ledger defect.
|
|
|
228
232
|
`em slice mark-implemented <model>.em <slice-key> <pr-url>` does the flip for you (MIL-103) —
|
|
229
233
|
resolves the doc via the same note-binding join `--slice-ready` uses, is idempotent on a re-run
|
|
230
234
|
with the same URL, and refuses (never silently overwrites) if the doc is already `implemented`
|
|
231
|
-
with a different URL.
|
|
235
|
+
with a different URL. It also refuses a doc that isn't `ready-to-implement` (MIL-277): if it
|
|
236
|
+
reports `doc is \`status: draft\``/`reviewed`, the slice was never ratified — stop and surface
|
|
237
|
+
that to the human rather than editing the frontmatter by hand; the §1 gate should have caught it.
|
|
238
|
+
Prefer it over hand-editing the doc's frontmatter. It also writes the **shipped record**
|
|
239
|
+
(`shippedVersion:`/`shippedRef:`/`shippedOn:`, MIL-284) — what every reader decides "has this
|
|
240
|
+
shipped?" on since 1.15.0 — and, when the ratified doc deferred a question to the next version,
|
|
241
|
+
**opens that version as a `draft` on the same write** (MIL-283: `status: draft`, `version` bumped,
|
|
242
|
+
the question back to `- [ ]`; the version you built stays shipped). If it prints `opened draft
|
|
243
|
+
v<N+1>`, say so in your report: the slice has known work, and a design session, not you, decides it.
|
|
232
244
|
|
|
233
245
|
Then, if the project keeps a model README (from `../../event-modeling-shared/templates/model-readme.md`), run
|
|
234
246
|
`em slice index <model-name>.em` so its generated Slices table reflects the new status and
|
|
@@ -308,23 +320,17 @@ sibling slice's package to reuse it — the boundary the constitution drew is go
|
|
|
308
320
|
contract into a pre-empted slice.
|
|
309
321
|
2. **It merges before any slice PR opens.** Every slice branch is cut *after* the foundation PR
|
|
310
322
|
has landed on `main` — never from a commit that predates it, and never alongside an open,
|
|
311
|
-
unmerged foundation PR.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
merge strategy applies. Because: a squash rewrites the lower branch's commits into one new
|
|
323
|
-
commit on `main`, so the dependent branch still carries the originals and its diff against
|
|
324
|
-
`main` shows them again — it then needs a hand rebase (`git rebase --onto main <old base
|
|
325
|
-
tip>`). A merge commit keeps the original commits: once the lower branch is merged and
|
|
326
|
-
deleted, the dependent is retargeted to `main` and its diff shrinks to its own commits with
|
|
327
|
-
no rebase.
|
|
323
|
+
unmerged foundation PR. Every slice branch is cut from `main` and every slice PR targets
|
|
324
|
+
`main` — inside an engagement (`em engagement plan` names `main` as every slice's base) and
|
|
325
|
+
outside one alike; never from another slice's branch, never targeting another slice's PR. A
|
|
326
|
+
slice PR never carries foundation files. Because: a slice PR opened while the foundation is
|
|
327
|
+
still in review shows a diff dominated by files the slice didn't write and can't be held
|
|
328
|
+
accountable for, and its merge depends on someone else's review timeline instead of its own.
|
|
329
|
+
And because the foundation already holds every event and rule 3 keeps a slice out of its
|
|
330
|
+
siblings' code, no slice needs another slice's branch to compile or test: a PR cut from a
|
|
331
|
+
sibling's branch (a "stack") carries a dependency this contract forbids, and turns N isolated
|
|
332
|
+
slices into one landing with merge-commit and retargeting ceremony attached. `main` already
|
|
333
|
+
contains the foundation; that is all a slice needs.
|
|
328
334
|
|
|
329
335
|
3. **A slice never creates, edits, or reaches into another slice's code.** It *imports* events —
|
|
330
336
|
only events — from wherever the foundation placed them; a sibling slice's handlers, storage,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: event-modeling-review
|
|
3
|
-
em-version: 1.
|
|
3
|
+
em-version: 1.15.0
|
|
4
4
|
description: >-
|
|
5
5
|
Use when starting em's live browser viewer (`em watch --serve`) so a team can watch a model
|
|
6
6
|
update in real time, or facilitating a SCHEDULED stakeholder walkthrough that steps through
|
|
@@ -53,10 +53,20 @@ walk each one with the user, same as any open issue. Update the state file's Par
|
|
|
53
53
|
section with who attended, and run `em state set-review <date>` to set the `Last stakeholder
|
|
54
54
|
review:` marker (mirrors `Last conformance:`).
|
|
55
55
|
|
|
56
|
-
**Per-slice outcome.**
|
|
56
|
+
**Per-slice outcome.** Walk the slice's questions — the doc's `## Open Questions` and every
|
|
57
|
+
`issue "..."` note the room added to its elements — and give each one of three endings:
|
|
58
|
+
|
|
59
|
+
- **Answered in the room** → edit the doc's authored section with the answer and delete the
|
|
60
|
+
`issue` note by hand. Defer is never used to record an answer.
|
|
61
|
+
- **Raised in the room, not for this version** → `em slice defer <model> <key> --from-issue "<text>" --until v<n> --decision "<what this version does>"`:
|
|
62
|
+
promotes the captured `issue` into the doc's Open Questions as a deferred item, mirrors it
|
|
63
|
+
into the state file and removes the red note — one command, no hand edit mid-session.
|
|
64
|
+
- **Already on the doc, not for this version** → the positional form. A question this version will not answer is deferred with `em slice defer <model> <key> "<question>" --until v<n> --decision "<what this version does>"` — never left `- [ ]`, never deleted, never answered by guessing.
|
|
65
|
+
|
|
66
|
+
Then, and only then: a slice with nothing left `- [ ]` and no open `issue` →
|
|
57
67
|
`em slice review <model>.em <key> --by <name>` (flips its doc to `status: reviewed` and records
|
|
58
68
|
`reviewedBy:`/`reviewedOn:`). Anything still open stays `draft` — the walkthrough doesn't decide
|
|
59
|
-
it, the next session or the open-questions list does.
|
|
69
|
+
it, the next session or the open-questions list does.
|
|
60
70
|
|
|
61
71
|
**The facilitator never ratifies, never offers to ratify, and never suggests ratification in a
|
|
62
72
|
review session. Ratification is a separate human gate after review**
|