@izkac/forgekit 0.1.7 → 0.3.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.
@@ -0,0 +1,74 @@
1
+ # Operator brief — `brief.html`
2
+
3
+ Every tracked change (openspec or specs engine) ends its plan phase with an
4
+ **operator brief**: one self-contained HTML file at
5
+ `<changeDir>/brief.html` that a human can read in two minutes and understand
6
+ *what will be built* — without reading proposal.md, design.md, or tasks.md.
7
+
8
+ The plan-approval checkpoint is only as strong as the operator's comprehension.
9
+ The specs are written for agents; the brief is the translation for the human
10
+ who approves them. `forge phase implement` **refuses** while the brief is
11
+ missing, unstamped, or stale.
12
+
13
+ ## Who writes it
14
+
15
+ You (the agent), at the end of the plan phase — after the specs are final,
16
+ before `forge phase implement`. The CLI never generates prose; it only stamps
17
+ freshness and opens the file.
18
+
19
+ ## Workflow
20
+
21
+ ```bash
22
+ # 1. specs are final (proposal.md / design.md / tasks.md)
23
+ # 2. write <changeDir>/brief.html (structure below)
24
+ forge brief stamp # records specs hash + opens it in the operator's browser
25
+ forge phase implement --tasks-total <N> # hard-gated on a fresh stamped brief
26
+ ```
27
+
28
+ If any spec file changes later, the brief goes **stale** — update the affected
29
+ sections and `forge brief stamp` again. `forge brief check` reports status.
30
+ Genuine edge case (operator explicitly waives it):
31
+ `forge phase implement --allow-incomplete "<reason>"`.
32
+
33
+ ## Writing rules
34
+
35
+ Audience: a smart human who has NOT read the specs and doesn't want to.
36
+ Plain language. No spec-speak, no requirement IDs, no file paths in headings.
37
+ If a sentence would not make sense to a project stakeholder outside this
38
+ session, rewrite it.
39
+
40
+ Structure (sections, in order — skip a section only when truly empty):
41
+
42
+ 1. **TL;DR** — 2-3 sentences: what will exist after this change that doesn't
43
+ today, and why it's worth doing.
44
+ 2. **What you'll get** — the observable outcomes, bulleted. Behavior, not
45
+ implementation ("you can send a message to any session from one terminal",
46
+ not "a registry module under lib/").
47
+ 3. **How it works** — the shape of the solution in one short narrative plus a
48
+ **mermaid diagram** where a picture beats prose (flow, sequence, or state —
49
+ whichever fits; skip the diagram for trivial changes rather than forcing one).
50
+ 4. **What changes for you** — new commands/screens/steps the operator will
51
+ use; anything that behaves differently than before.
52
+ 5. **Risks and open questions** — honest, short. What could go wrong, what was
53
+ deliberately deferred, what the operator should keep an eye on.
54
+ 6. **Out of scope** — what this change deliberately does NOT do.
55
+ 7. **Work overview** — task groups from tasks.md compressed to one line each,
56
+ with rough size (n tasks). Not the full task list.
57
+
58
+ ## File rules
59
+
60
+ - One file, self-contained: inline CSS, no build step, no local assets.
61
+ - Mermaid via CDN is fine (`<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js">`
62
+ + `mermaid.initialize({ startOnLoad: true })`; diagrams in `<pre class="mermaid">` blocks).
63
+ Trade-off accepted: diagrams need internet to render; the text must stand on
64
+ its own without them.
65
+ - Readable defaults: max-width ~48rem/prose, system font stack, dark-on-light.
66
+ Keep styling minimal — this is a memo, not a product page.
67
+ - Do not remove the `<!-- forge-brief-specs-hash:… -->` comment `forge brief
68
+ stamp` inserts; re-stamping updates it.
69
+
70
+ ## Archive
71
+
72
+ `brief.html` lives in the change dir, so it archives with the change
73
+ (`changes/archive/…`) and remains the human-readable record of what was
74
+ approved — useful input for archive→ADR.
@@ -45,12 +45,13 @@ task.
45
45
  - To shrink scope: stop and ask the user. Do not silently checkbox around gaps.
46
46
  - Prefer `DONE_WITH_CONCERNS` / incomplete tasks over green checkboxes.
47
47
 
48
- ## 5. E2E means product loop, not job slice
48
+ ## 5. E2E means an executed product loop, not prose
49
49
 
50
50
  Before claiming the change complete:
51
51
 
52
- 1. Run (or document exact commands for) the **closed product loop** through the
53
- live entry points, **or**
52
+ 1. Author the **closed product loop** as executable steps in `e2e.json`
53
+ (`forge e2e init`), run it against the live entry points
54
+ (`forge e2e run`), and get a **green run** — **or**
54
55
  2. Leave an explicit **`BLOCKED`** list in `verify-evidence.md` — and do **not**
55
56
  mark the change complete / advance to `done`.
56
57
 
@@ -65,8 +66,19 @@ next run's OUTPUT DIFFERS from the baseline
65
66
 
66
67
  Example: ingest→Parquet plus a thin run→`.sav` does **not** verify a
67
68
  governance loop; analyze→proposals→ratify→run-applies-decisions does.
68
- Record it under a `## Product loop` heading in `verify-evidence.md` —
69
- the mechanical gate looks for it.
69
+
70
+ The mechanical gate requires a green, **current** `e2e-results.json` (its
71
+ steps hash must match `e2e.json`) whenever the spine has real rows.
72
+ Describing the loop in `verify-evidence.md` no longer satisfies the gate —
73
+ prose cannot prove wiring. Each step is `{ name, cmd, expect?, timeoutMs? }`:
74
+ exit code 0 required, `expect` (regex) matched against the output. Steps must
75
+ assert **domain side effects** — a step list that would pass against a
76
+ stubbed handler is invalid (rule 3 applies to e2e steps too).
77
+
78
+ `e2e.json` may set `"notApplicable": "<reason>"` only when the loop cannot be
79
+ driven by any command (e.g. requires a physical device). Reviewers police the
80
+ reason; "no time" or "covered by unit tests" is a REJECT. Keep a short loop
81
+ narrative under `## Product loop` in `verify-evidence.md` as reviewer context.
70
82
 
71
83
  ## 6. Job-kind closure
72
84
 
@@ -126,9 +138,9 @@ Then either:
126
138
  (e.g. `"sync HTTP only — no async producer/consumer"`). That is the honest
127
139
  opt-out; missing `spine.json` is not.
128
140
 
129
- Product-loop evidence in `verify-evidence.md` is required when the spine has
130
- real rows. Prefer `notApplicable` for sync-only changes instead of inventing a
131
- fake loop.
141
+ An executed product loop (`forge e2e run`, green + current results) is
142
+ required when the spine has real rows. Prefer `notApplicable` for sync-only
143
+ changes instead of inventing a fake loop.
132
144
 
133
145
  ## Reviewer REJECT checklist (mandatory)
134
146
 
@@ -141,6 +153,8 @@ REJECT the task (or final review → `NOT READY`) if any of:
141
153
  - Spec requirement has a library but no named runtime owner
142
154
  - Deferred wiring without a registered open deferral (`forge defer list`)
143
155
  - Spine row for this capability missing or library-only
156
+ - E2E steps would pass against a stubbed handler (no domain side-effect
157
+ assertions), or `e2e.json` opts out via `notApplicable` without a real reason
144
158
 
145
159
  ## Plan seam (every change)
146
160
 
@@ -148,10 +162,14 @@ Before apply-ready:
148
162
 
149
163
  1. `forge spine init` — **always**. Fill rows for each capability, or set
150
164
  `notApplicable` with a reason (sync-only / docs-only).
151
- 2. If the change involves workers, job queues, handlers, or cross-runtime
165
+ 2. When the spine has real rows, `forge e2e init` the acceptance **steps are
166
+ a plan deliverable**: author (or task out) the `e2e.json` step list that
167
+ drives the loop and asserts its side effects.
168
+ 3. If the change involves workers, job queues, handlers, or cross-runtime
152
169
  calls, `tasks.md` MUST also include:
153
170
  - Explicit **wiring** tasks per job kind / entry point → domain pipeline
154
- - One **product-loop acceptance** task (last implement task, before verify)
171
+ - One **product-loop acceptance** task (last implement task, before
172
+ verify) — its output is a green `forge e2e run`
155
173
 
156
174
  Missing spine = plan not ready. Keyword guesses about “jobs in scope” are not
157
175
  an excuse to skip the spine.
@@ -34,14 +34,17 @@ job, …) that invokes the implementing code. Cross-check against `spine.json`
34
34
  - UI/API reads a collection or artifact nothing in the production path writes → **`NOT READY`**
35
35
  - Missing E2E fixture path with no explicit `BLOCKED` in `verify-evidence.md` → **`NOT READY`**
36
36
 
37
- ## Product-loop evidence (required)
37
+ ## Product-loop acceptance (required — executed, not described)
38
38
 
39
- `verify-evidence.md` must contain a `## Product loop` section proving the
40
- **closed loop** (produce → consume → decision changes output), or an explicit
41
- `BLOCKED` list. A single job slice (e.g. ingest→file) or a library-level E2E
42
- does **not** count as platform E2E.
39
+ `forge e2e check` must be green: `e2e.json` steps drive the **closed loop**
40
+ (produce → consume → decision changes output) and `e2e-results.json` records a
41
+ green, current run (steps hash matches). A single job slice (e.g. ingest→file)
42
+ or a library-level E2E does **not** count as platform E2E. Read the steps —
43
+ would they pass against a stubbed handler? If yes, they prove nothing.
43
44
 
44
- - No product-loop section and no `BLOCKED` → **`NOT READY`**
45
+ - No green, current e2e run and no `BLOCKED` in `verify-evidence.md` → **`NOT READY`**
46
+ - E2E steps assert no domain side effects (would pass on a stub) → **`NOT READY`**
47
+ - `e2e.json` `notApplicable` without a reason no command could overcome → **`NOT READY`**
45
48
  - `BLOCKED` present → **`NOT READY`** (honest, but not READY)
46
49
  - Unresolved deferrals in `forge defer list` → **`NOT READY`**
47
50
 
@@ -43,6 +43,7 @@ Diff range: {DIFF_RANGE} <!-- e.g. `git diff` (uncommitted) or BASE..HEAD -->
43
43
  - Brief authorized a stub / “wire later” for a path this change claims
44
44
  - Wiring is deferred **without a registered open deferral** — the packet must show `forge defer list` output naming this task's deferral; "wiring in §9" with no registry entry is a REJECT
45
45
  - The task claims a capability whose `spine.json` row is missing or library-only (empty runtimeOwner / writes / evidence)
46
+ - The task authored or touched `e2e.json` steps that would pass against a stubbed handler (no domain side-effect assertions), or set `notApplicable` without a real reason
46
47
 
47
48
  **Code quality:**
48
49