forgedock 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +53 -8
  2. package/bin/batch-runner.mjs +339 -0
  3. package/bin/demo.mjs +92 -7
  4. package/bin/engine/phases.mjs +24 -2
  5. package/bin/engine/state.mjs +8 -3
  6. package/bin/engine-cli.mjs +177 -5
  7. package/bin/forgedock.mjs +409 -26
  8. package/bin/hooks/interactive-engine.mjs +509 -0
  9. package/bin/hooks/pre-tool-use.mjs +498 -0
  10. package/bin/hooks/subagent-stop-enforce.mjs +197 -0
  11. package/bin/journey.mjs +72 -14
  12. package/bin/registry.mjs +139 -0
  13. package/bin/report.mjs +447 -0
  14. package/bin/runner.mjs +70 -20
  15. package/bin/settings-hook.mjs +235 -1
  16. package/commands/adopt.md +4 -1
  17. package/commands/analytics.md +4 -1
  18. package/commands/audit-agents.md +110 -27
  19. package/commands/audit.md +20 -1
  20. package/commands/autopilot.md +518 -361
  21. package/commands/changelog.md +2 -1
  22. package/commands/ci-audit.md +2 -1
  23. package/commands/cleanup.md +161 -1
  24. package/commands/compat-audit.md +2 -1
  25. package/commands/deploy-info.md +58 -1
  26. package/commands/deploy-pr.md +485 -0
  27. package/commands/design-bench.md +5 -1
  28. package/commands/design-render-critique-loop.md +1 -1
  29. package/commands/diagnose.md +2 -1
  30. package/commands/explain.md +2 -1
  31. package/commands/fix-ci.md +577 -0
  32. package/commands/forge-stats.md +121 -2
  33. package/commands/forgedock-init.md +1 -1
  34. package/commands/geo-audit.md +3 -0
  35. package/commands/incident-response.md +2 -1
  36. package/commands/issue.md +23 -2
  37. package/commands/milestone.md +77 -12
  38. package/commands/optimize.md +2 -1
  39. package/commands/orchestrate/config.md +67 -0
  40. package/commands/orchestrate/phase-1-resolve.md +159 -0
  41. package/commands/orchestrate/phase-2-triage.md +126 -0
  42. package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
  43. package/commands/orchestrate/phase-3-dependency.md +591 -0
  44. package/commands/orchestrate/phase-4-execution.md +962 -0
  45. package/commands/orchestrate/phase-5-cleanup.md +47 -0
  46. package/commands/orchestrate/phase-6-report.md +198 -0
  47. package/commands/orchestrate/safety.md +62 -0
  48. package/commands/orchestrate.md +25 -2045
  49. package/commands/pipeline-health/config.md +34 -0
  50. package/commands/pipeline-health/phase-1-context.md +180 -0
  51. package/commands/pipeline-health/phase-2-metrics.md +1729 -0
  52. package/commands/pipeline-health/phase-3-analyze.md +204 -0
  53. package/commands/pipeline-health/phase-4-proposals.md +117 -0
  54. package/commands/pipeline-health/phase-5-report.md +284 -0
  55. package/commands/pipeline-health/phase-6-summary.md +52 -0
  56. package/commands/pipeline-health.md +25 -2401
  57. package/commands/pipeline-resume.md +24 -1
  58. package/commands/pipeline-status.md +65 -0
  59. package/commands/qa-sweep.md +4 -1
  60. package/commands/quality-gate.md +248 -10
  61. package/commands/recover-orphans.md +576 -0
  62. package/commands/replay.md +2 -1
  63. package/commands/review-pr-agents/api.md +135 -0
  64. package/commands/review-pr-agents/auth.md +137 -0
  65. package/commands/review-pr-agents/billing.md +101 -0
  66. package/commands/review-pr-agents/concurrency.md +145 -0
  67. package/commands/review-pr-agents/database.md +103 -0
  68. package/commands/review-pr-agents/frontend.md +89 -0
  69. package/commands/review-pr-agents/infra.md +385 -0
  70. package/commands/review-pr-agents/protocols.md +185 -0
  71. package/commands/review-pr-agents/scraper.md +185 -0
  72. package/commands/review-pr-agents/security.md +406 -0
  73. package/commands/review-pr-agents.md +45 -1722
  74. package/commands/review-pr-staging.md +196 -40
  75. package/commands/review-pr.md +591 -52
  76. package/commands/rollback.md +2 -1
  77. package/commands/scope.md +2 -1
  78. package/commands/security-audit.md +2 -1
  79. package/commands/signal-planner.md +623 -0
  80. package/commands/sync-ecosystem.md +1 -0
  81. package/commands/test-gate.md +17 -1
  82. package/commands/validate.md +2 -1
  83. package/commands/work-on/build/architect.md +28 -0
  84. package/commands/work-on/build/context.md +2 -0
  85. package/commands/work-on/build/implement.md +3 -1
  86. package/commands/work-on/build/validate.md +26 -7
  87. package/commands/work-on/build.md +163 -24
  88. package/commands/work-on/close.md +130 -3
  89. package/commands/work-on/decompose.md +19 -1
  90. package/commands/work-on/investigate.md +117 -2
  91. package/commands/work-on/review.md +24 -4
  92. package/commands/work-on-monolithic.md +7 -2
  93. package/commands/work-on.md +202 -4
  94. package/docs/BRAND.md +14 -7
  95. package/docs/CI.md +16 -2
  96. package/docs/CODEX.md +36 -1
  97. package/docs/CONFIG.md +5 -8
  98. package/docs/FORGE-PROTOCOL.md +15 -1064
  99. package/docs/anthropic-devrel-outreach.md +2 -2
  100. package/docs/articles/command-decomposition-token-savings.md +214 -0
  101. package/docs/articles/model-release-playbook.md +131 -0
  102. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
  103. package/docs/claude-breakpoints.json +75 -5
  104. package/docs/design/abc-benchmark.md +1 -1
  105. package/docs/design/design-spec-schema.md +1 -1
  106. package/docs/design/divergent-generation.md +1 -1
  107. package/docs/design/eval-gate-runbook.md +178 -0
  108. package/docs/design/show-hn-draft.md +26 -1
  109. package/docs/design/token-cost-baseline-1298.md +59 -0
  110. package/docs/eval/README.md +120 -0
  111. package/docs/eval/corpus/seed-v1.json +6 -0
  112. package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
  113. package/docs/site/annotations-explained.md +24 -0
  114. package/docs/site/command-learning-path.md +51 -14
  115. package/docs/site/command-reference.md +386 -111
  116. package/docs/site/for-companies.md +95 -0
  117. package/docs/site/forge-annotation-protocol.md +12 -256
  118. package/docs/site/getting-started.md +43 -4
  119. package/docs/site/github-is-the-memory.md +113 -0
  120. package/docs/site/how-it-works.md +3 -13
  121. package/docs/site/index.md +9 -1
  122. package/docs/spec/eval-run-result.md +147 -0
  123. package/docs/spec/forge-protocol-v1.md +441 -18
  124. package/docs/spec/label-state-machine.md +55 -0
  125. package/docs/spec/review-protocol.md +158 -0
  126. package/docs/spec-graph-schema.md +28 -0
  127. package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
  128. package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
  129. package/examples/forgedock-demo/README.md +41 -22
  130. package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
  131. package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
  132. package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
  133. package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
  134. package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
  135. package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
  136. package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
  137. package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
  138. package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
  139. package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
  140. package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
  141. package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
  142. package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
  143. package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
  144. package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
  145. package/examples/forgedock-demo/scripts/smoke.js +18 -1
  146. package/examples/forgedock-demo/src/db.js +36 -11
  147. package/examples/forgedock-demo/src/routes/notes.js +106 -9
  148. package/examples/forgedock-demo/src/server.js +4 -1
  149. package/package.json +3 -1
  150. package/packages/protocol/LICENSE +21 -0
  151. package/packages/protocol/src/cli.js +135 -0
  152. package/packages/protocol/src/emit.js +146 -0
  153. package/packages/protocol/src/index.js +43 -0
  154. package/packages/protocol/src/parse.js +254 -0
  155. package/packages/protocol/src/types.js +171 -0
  156. package/packages/protocol/src/validate.js +122 -0
  157. package/scripts/bench-topology-cost.mjs +372 -0
  158. package/scripts/check-command-docs-drift.sh +198 -0
  159. package/scripts/check-protocol-restatements.sh +176 -0
  160. package/scripts/check-registry/README.md +72 -0
  161. package/scripts/check-registry/manifest.json +6 -0
  162. package/scripts/code-index.sh +454 -0
  163. package/scripts/conformance-check.mjs +168 -0
  164. package/scripts/doctor-pipeline-state.sh +484 -0
  165. package/scripts/eval-gate-baseline.json +17 -0
  166. package/scripts/eval-gate-scorecard.mjs +242 -0
  167. package/scripts/eval-scorecard-aggregator.mjs +252 -0
  168. package/scripts/flaky-quarantine.sh +241 -0
  169. package/scripts/forge-annotation.sh +567 -0
  170. package/scripts/issue-dedup.sh +236 -0
  171. package/scripts/validate-annotation-node.mjs +233 -0
  172. package/scripts/worktree-lifecycle.sh +3 -3
  173. package/templates/devdocs/agent/using-forgedock.md +14 -0
  174. package/docs/site/.vitepress/config.mjs +0 -85
@@ -0,0 +1,147 @@
1
+ # Eval Run-Result JSON Schema
2
+
3
+ **Spec version**: 1.0.0
4
+ **Stable since**: issue #1285
5
+
6
+ This document defines the machine-readable JSON shapes consumed and produced by
7
+ the ForgeDock pipeline eval harness:
8
+
9
+ - **Per-run result** — one object per issue, written by the batch driver
10
+ (`bin/batch-runner.mjs`) after each headless `/work-on` run.
11
+ - **Scorecard** — aggregate computed by `scripts/eval-scorecard-aggregator.mjs`
12
+ from an array of per-run results; consumed by the CI regression gate
13
+ (`scripts/eval-gate-scorecard.mjs`, issue #1286) and the publishing pipeline.
14
+
15
+ ---
16
+
17
+ ## Per-Run Result
18
+
19
+ Each headless run of a single corpus issue produces one JSON object:
20
+
21
+ ```jsonc
22
+ {
23
+ // Required fields
24
+ "issue": 1234, // integer — GitHub issue number
25
+ "status": "success", // "success" | "failure" | "incomplete" | "error"
26
+ "wallClockMs": 42000, // integer — wall-clock duration of the run (ms)
27
+ "interventionCount": 0, // integer — number of human interventions (see below)
28
+
29
+ // Optional fields (nullable — do NOT block on missing upstream data)
30
+ "cost": null, // null | number — token/USD cost; null until #1255 lands
31
+ "iterations": 23, // integer — tool-use loop iteration count
32
+ "stopReason": "end_turn", // string — Anthropic stop_reason or "max_iterations"
33
+ "error": null, // null | string — error message when status === "error"
34
+ "specVersion": "1.0.21", // string — forgedock package version at run time
35
+ "model": "claude-sonnet-4-5", // string — model used for the run
36
+ "runAt": "2026-07-04T00:00:00.000Z" // ISO-8601 timestamp
37
+ }
38
+ ```
39
+
40
+ ### `status` values
41
+
42
+ | Value | Meaning |
43
+ |--------------|------------------------------------------------------------------------------|
44
+ | `success` | Run completed; the issue reached `workflow:merged` or equivalent terminal state |
45
+ | `failure` | Run completed but the issue did not reach a terminal success state |
46
+ | `incomplete` | Run stopped due to `max_tokens` or `max_iterations` — result is unreliable |
47
+ | `error` | The runner threw an unhandled exception (network, API, crash) |
48
+
49
+ ### `interventionCount` definition
50
+
51
+ A human intervention is counted when **any** of the following occur during a run:
52
+
53
+ 1. The `needs-human` label is applied to the issue by the pipeline.
54
+ 2. A manual `gh` command is executed outside the automated runner loop.
55
+ 3. A FORGE annotation comment is posted by a human (not the bot account) during the run window.
56
+
57
+ Runs where no human interaction occurs have `interventionCount: 0`.
58
+
59
+ ---
60
+
61
+ ## Batch Driver Output File
62
+
63
+ `bin/batch-runner.mjs` writes a JSON object containing the per-run array plus
64
+ top-level metadata:
65
+
66
+ ```jsonc
67
+ {
68
+ "corpus_version": "v1", // string | null — corpus version label
69
+ "spec_version": "1.0.21", // string | null — forgedock version at run time
70
+ "model": "claude-sonnet-4-5", // string | null — model used
71
+ "generated_at": "2026-07-04T00:00:00.000Z",
72
+ "runs": [ ...PerRunResult ]
73
+ }
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Corpus File
79
+
80
+ The batch driver accepts a corpus file (JSON) listing issues to run:
81
+
82
+ ```jsonc
83
+ {
84
+ "corpus_version": "v1", // string — semver or label for the corpus snapshot
85
+ "run_id": "run-2026-07-04-1", // string — optional unique run identifier
86
+ "run_mode": "full", // "full" | "subset" — passed through to scorecard
87
+ "spec_sha": "abc123", // string | null — git SHA of commands/ at run time
88
+ "issues": [1001, 1002, 1003] // integer[] — GitHub issue numbers
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Scorecard
95
+
96
+ `scripts/eval-scorecard-aggregator.mjs` reads the batch driver output and emits
97
+ a scorecard in the format consumed by `scripts/eval-gate-scorecard.mjs` (#1286):
98
+
99
+ ```jsonc
100
+ {
101
+ "schema_version": "1", // string — always "1" (schema identifier)
102
+ "run_id": "run-2026-07-04-1", // string | null — from corpus metadata
103
+ "generated_at": "2026-07-04T00:00:00.000Z",
104
+ "corpus_size": 20, // integer — from corpus metadata (defaults to issues_run)
105
+ "issues_run": 20, // integer — total runs in the input
106
+ "successful_runs": 17, // integer — runs with status === "success"
107
+ "failed_runs": 2, // integer — runs with status === "failure"
108
+ "success_rate_pct": 85, // number [0,100] — successful_runs / issues_run * 100 (2dp)
109
+ "mean_wall_clock_ms": 38200, // number | null — arithmetic mean wall-clock
110
+ "median_wall_clock_ms": 35000, // number | null — median wall-clock
111
+ "total_intervention_count": 1, // integer — sum of interventionCount across all runs
112
+ "cost": null, // null | number — sum of per-run cost; null if any run has cost: null
113
+ "run_mode": "full", // "full" | "subset"
114
+ "spec_sha": "abc123" // string | null — git SHA of commands/ at run time
115
+ }
116
+ ```
117
+
118
+ **Important**: `incomplete` and `error` status runs count against `success_rate_pct`
119
+ (they reduce `issues_run` denominator's numerator). This ensures the gate catches
120
+ hangs and crashes, not just logic failures.
121
+
122
+ ### Methodology rules (enforced by the scorecard aggregator)
123
+
124
+ 1. **Minimum sample size**: fewer than `MIN_RUNS` (currently **5**) scoreable
125
+ (`success` or `failure`) runs causes the aggregator to exit non-zero rather
126
+ than emit a misleading rate. Mirrors `bench-scorecard.mjs`'s `MIN_RUNS` rule.
127
+ 2. **Malformed input**: missing required fields (`issue`, `status`,
128
+ `wallClockMs`, `interventionCount`) or non-integer/non-string values cause
129
+ exit code 1 (validation error).
130
+ 3. **Cost is nullable**: if any run has `cost: null`, the scorecard's
131
+ `cost` is `null`. The field becomes numeric only when every run reports a
132
+ real cost value (post-#1255).
133
+ 4. **Rate consistency**: `success_rate_pct` is always computed as
134
+ `round(successful_runs / issues_run * 100, 2)`. The CI gate (#1286) validates
135
+ this computed value matches the reported value.
136
+
137
+ ---
138
+
139
+ ## Stability contract
140
+
141
+ - Field names are stable. New **optional** fields may be added at any time
142
+ without a version bump.
143
+ - Removing or renaming a field is a breaking change and requires a spec version
144
+ bump and a GitHub issue.
145
+ - Consumers **must** treat unknown fields as ignorable (forward-compatibility).
146
+ - The CI gate sub-issue (#1286) and publishing sub-issue (#1287) may depend on
147
+ this schema without waiting for upstream changes.
@@ -453,6 +453,15 @@ artifact so a sub-issue builder can fetch upstream context directly.
453
453
 
454
454
  These markers carry no Markdown body; their presence is the signal.
455
455
 
456
+ **Phase boundary markers** (appear in pipeline command specs):
457
+
458
+ | Marker | Meaning |
459
+ |--------|---------|
460
+ | `<!-- FORGE:DISPATCHER — {desc} -->` | Marks the Universal Phase Dispatcher — the single source of truth for phase transitions and routing logic |
461
+ | `<!-- FORGE:PHASE_COMPLETE — {desc} -->` | Inter-phase boundary; documents that a phase completed and names the next phase so agents do not treat an intermediate result as terminal |
462
+
463
+ **Issue-comment control markers** (posted to issue comments):
464
+
456
465
  | Marker | Meaning |
457
466
  |--------|---------|
458
467
  | `<!-- FORGE:REVIEW_STARTED -->` | The review phase has been invoked for this issue |
@@ -466,6 +475,255 @@ needed.
466
475
 
467
476
  ---
468
477
 
478
+ ### 4.4 Design pipeline annotations
479
+
480
+ These annotations drive the UI Taste Harness — the design-generation pipeline
481
+ that produces a landing page from a design-blind product brief. They carry
482
+ design intent across the investigate → architect → generate → critique → close
483
+ stages, exactly as the lifecycle annotations carry code context across
484
+ investigate → build → review.
485
+
486
+ #### `FORGE:DESIGN_CONTEXT`
487
+
488
+ - **Written by**: the `/design` design-investigate stage
489
+ - **Read by**: design-architect stage (grounds the rationale), close phase (audit trail)
490
+ - **Completion sentinel**: `<!-- FORGE:DESIGN_CONTEXT:COMPLETE -->`
491
+
492
+ The design analog of `FORGE:CONTEXT`: the parsed brief (message / audience /
493
+ single objection), the grammar pulled from the reference corpus, and the recent
494
+ signature moves / archetypes / palettes from design-memory that this design must
495
+ diverge from. Opens the `FORGE:DESIGN_*` chain.
496
+
497
+ ```
498
+ <!-- FORGE:DESIGN_CONTEXT -->
499
+ ## Design Context — {product}
500
+
501
+ **Message:** {one thing the page must say}
502
+ **Audience / objection:** {who} — must overcome: {objection}
503
+ **Corpus grammar:** {relevant traits / archetype priors}
504
+ **Diverge from (memory):** {recent signature moves / archetypes / palettes to avoid}
505
+ <!-- FORGE:DESIGN_CONTEXT:COMPLETE -->
506
+ ```
507
+
508
+ #### `FORGE:DESIGN_RATIONALE`
509
+
510
+ - **Written by**: the design-architect agent
511
+ - **Read by**: the generate agent (the spec it produces), the render → vision-critique loop, and reviewers
512
+ - **Emitted**: before `FORGE:DESIGN_SPEC`
513
+
514
+ The designer's diary — the reasoning-before-generation step. Captures a
515
+ seven-element chain of thought (intent/feeling, audience/objection,
516
+ communication hierarchy, direction + rejected alternatives, signature move,
517
+ what's being tried this time, non-goals). MUST carry at least one explicitly
518
+ rejected alternative, a named signature move, and a `→ Produces DESIGN_SPEC`
519
+ link.
520
+
521
+ ```
522
+ <!-- FORGE:DESIGN_RATIONALE -->
523
+ ## Design Rationale — {product}
524
+
525
+ **Intent / feeling:** {one message} · {one feeling}
526
+ **Audience / objection:** {who} — must overcome: {objection}
527
+ **Communication hierarchy:** 1) {…} 2) {…} 3) {…}
528
+ **Direction:** {archetype} — because {reasoning}
529
+ - Considered & rejected: {alt A} (because {…}); {alt B} (because {…})
530
+ **Signature move:** {the one non-obvious idea}
531
+ **Trying this time:** {technique/learning} (from memory: avoiding {prior move})
532
+ **Non-goals:** {what this won't do}
533
+
534
+ → Produces DESIGN_SPEC: {link}
535
+ ```
536
+
537
+ #### `FORGE:DESIGN_CANDIDATES`
538
+
539
+ - **Written by**: the generate agent (divergent-generation step)
540
+ - **Read by**: the taste-judge (selects the winner), close phase (audit trail), design-memory (to diverge from past winners)
541
+ - **Emitted**: after `FORGE:DESIGN_RATIONALE`, before `FORGE:DESIGN_SPEC`
542
+
543
+ The variance lever's audit record: the one committed archetype (never blended),
544
+ the N distinct directions generated within it, and the independent taste-judge's
545
+ scores and selection. The selection judge is distinct from the critique loop —
546
+ anti-Goodhart.
547
+
548
+ ```
549
+ <!-- FORGE:DESIGN_CANDIDATES -->
550
+ ## Design Candidates — {product}
551
+
552
+ **Archetype (committed):** {one of the corpus ids}
553
+ **Directions:**
554
+ 1. {concept} — signature: {move} — {distinguishing grammar/tokens}
555
+ 2. {concept} — signature: {move} — {…}
556
+ **Judge scores:** 1) {score} 2) {score} …
557
+ **Selected:** #{n} — because {reason}
558
+
559
+ → Winner produces DESIGN_SPEC: {link}
560
+ ```
561
+
562
+ #### `FORGE:DESIGN_SPEC`
563
+
564
+ - **Written by**: the design-architect agent
565
+ - **Read by**: the generate agent (constrains output), the deterministic anti-slop linter, the render → vision-critique loop, and the close phase agent
566
+
567
+ A structured, machine-checkable representation of one page's design language.
568
+ Produced by `FORGE:DESIGN_RATIONALE` — not authored from nowhere. The flow is
569
+ rationale → spec → page. Full field-by-field schema lives in
570
+ `docs/design/design-spec-schema.md`.
571
+
572
+ ````
573
+ <!-- FORGE:DESIGN_SPEC -->
574
+ ## Design Spec — {product}
575
+
576
+ ```jsonc
577
+ {
578
+ "meta": { "product": "…", "archetype": "…", "corpus_version": "…", "rationale_ref": "…" },
579
+ "typography": { "display_family": "…", "body_family": "…", "scale_ratio": …, "weights": […] },
580
+ "color": { "mode": "…", "background": "#…", "foreground": "#…", "accent": "#…",
581
+ "rules": ["no-default-tailwind-palette", "contrast>=4.5"] },
582
+ "spacing": { "base_unit_px": …, "scale": […] },
583
+ "radius": { "scale": […] },
584
+ "shadow": { "tokens": […] },
585
+ "motion": { "vocabulary": […], "reduced_motion": "required" },
586
+ "layout_grammar":{ "sections": [ { "id": "…", "purpose": "…", "density": "…" } ], "rhythm": "…" },
587
+ "effects_plan": { "per_section": [ … ], "budget": { … }, "never": [ … ] },
588
+ "negatives": [ … ],
589
+ "acceptance": { "perf_budget": { … }, "a11y": { … }, "divergence_ref": "…" }
590
+ }
591
+ ```
592
+
593
+ → Produced by FORGE:DESIGN_RATIONALE: {link}
594
+ ````
595
+
596
+ #### `FORGE:CRITIQUE`
597
+
598
+ - **Written by**: the vision-critique loop (one annotation per iteration)
599
+ - **Read by**: the iterate step (consumes its findings), close phase (improvement trajectory audit)
600
+ - **Completion sentinel**: `<!-- FORGE:CRITIQUE:COMPLETE -->`
601
+
602
+ One annotation per render → critique iteration — the page's improvement
603
+ trajectory as an auditable trail. Records the deterministic lint floor result,
604
+ the desktop+mobile render, the perceptual findings, and the verdict. The critic
605
+ is strictly independent from the benchmark judge — anti-Goodhart.
606
+
607
+ ```
608
+ <!-- FORGE:CRITIQUE -->
609
+ ## Critique — {product} · iteration {i}/{max}
610
+
611
+ **Lint floor:** {PASS | fixed N hard findings}
612
+ **Render:** desktop + mobile captured
613
+ **Perceptual findings:**
614
+ - N{n}: {what was observed in the render} → {correction}
615
+ **Verdict:** {PASS | ITERATE | BUDGET-EXHAUSTED}
616
+ <!-- FORGE:CRITIQUE:COMPLETE -->
617
+ ```
618
+
619
+ #### `FORGE:USER_FEEDBACK`
620
+
621
+ - **Written by**: the `/design` user-feedback stage
622
+ - **Read by**: the surgical re-generation step, close phase (audit trail)
623
+ - **Completion sentinel**: `<!-- FORGE:USER_FEEDBACK:COMPLETE -->`
624
+ - **Not produced** in automated (benchmark) runs
625
+
626
+ The structured record of one user-feedback round. There MAY be multiple
627
+ `FORGE:USER_FEEDBACK` annotations on a single issue if the user iterates.
628
+ `FORGE:USER_FEEDBACK` MAY modify a section's visual execution but MUST NOT
629
+ change the committed `meta.archetype` or the signature move from
630
+ `FORGE:DESIGN_RATIONALE` — those choices are locked once the spec is committed.
631
+
632
+ ```
633
+ <!-- FORGE:USER_FEEDBACK -->
634
+ ## User Feedback — {product} · round {n}
635
+
636
+ **Section target:** {section ID from layout_grammar.sections, or "all" for page-wide feedback}
637
+ **Feedback type:** {asset | emotion | direction | freeform}
638
+ **Asset URL:** {URL or "none"}
639
+ **Modification:** {structured description of what to change}
640
+ **Emotion target:** {trust | speed | power | craft | play | unchanged}
641
+ **Satisfied:** {yes | no — "no" loops back after re-generation}
642
+ **Freeform notes:** {verbatim user input not captured in the structured fields}
643
+ <!-- FORGE:USER_FEEDBACK:COMPLETE -->
644
+ ```
645
+
646
+ #### `FORGE:BENCH_SCORECARD`
647
+
648
+ - **Written by**: the `/design-bench` benchmark rig
649
+ - **Read by**: harness developers (fitness signal), milestone tracker, pipeline-health
650
+ - **Completion sentinel**: `<!-- FORGE:BENCH_SCORECARD:COMPLETE -->`
651
+
652
+ The result of one ABC benchmark run. Arm A is the harness output, arm B is a
653
+ raw one-shot model, arm C is the real reference page (gold standard). The
654
+ annotation carries win-rates, the A-vs-B harness delta, rubric distributions
655
+ (mean + stdev) across n≥3 runs, mean slop counts, and a judge-calibration check
656
+ (C must beat A and B — otherwise the judge is miscalibrated).
657
+
658
+ ````
659
+ <!-- FORGE:BENCH_SCORECARD -->
660
+ ## ABC Benchmark Scorecard
661
+
662
+ **Corpus version**: {ver} · **Generation model (A & B)**: {model} · **Judge model**: {independent judge}
663
+ **Products**: {n_products} · **Runs/product**: {n}
664
+
665
+ | Arm | Win-rate vs C | A-vs-B | Mean slop |
666
+ |-----|---------------|--------|-----------|
667
+ | A | {wr} | {a_vs_b} | {slop_A} |
668
+ | B | {wr} | — | {slop_B} |
669
+
670
+ **Judge calibration**: {ok | MISCALIBRATED — N runs where C lost (suspect)}
671
+
672
+ ```json
673
+ {scorecard.json from bench-scorecard.mjs}
674
+ ```
675
+
676
+ <!-- FORGE:BENCH_SCORECARD:COMPLETE -->
677
+ ````
678
+
679
+ #### `FORGE:DESIGN_SHIPPED`
680
+
681
+ - **Written by**: the `/design` design-close stage
682
+ - **Read by**: design-memory (persists the realized outcome), milestone tracker, pipeline-health
683
+ - **Completion sentinel**: `<!-- FORGE:DESIGN_SHIPPED:COMPLETE -->`
684
+ - **Terminal annotation** for the design pipeline (analogous to `workflow:merged` for code)
685
+
686
+ Closes the design pipeline. Posted only when the design passes the full
687
+ definition of done — critique-rubric threshold, perf budget, a11y check, and
688
+ the divergence check. Records the final realized outcome written to design-memory
689
+ so the next design can diverge from it.
690
+
691
+ ```
692
+ <!-- FORGE:DESIGN_SHIPPED -->
693
+ ## Design Shipped — {product}
694
+
695
+ **Archetype:** {committed id} · **Signature move:** {the hook}
696
+ **Gates:** rubric {pass} · perf {pass} · a11y {pass} · divergence {distinct from prior}
697
+ **Critique iterations:** {n}
698
+ **Written to memory:** {palette/type/effects/learnings summary}
699
+ <!-- FORGE:DESIGN_SHIPPED:COMPLETE -->
700
+ ```
701
+
702
+ ---
703
+
704
+ ### 4.5 Audit annotations
705
+
706
+ These annotations are posted to issue or PR comments by audit commands
707
+ (`/audit`, `/audit-agents`, `/security-audit`) after running structured code
708
+ audits.
709
+
710
+ #### `FORGE:AUDIT`
711
+
712
+ - **Written by**: audit command agents (`/audit`, `/audit-agents`)
713
+ - **Location**: issue or PR comment
714
+
715
+ Posted after running a structured code or agent audit. Body content varies by
716
+ audit type.
717
+
718
+ #### `FORGE:SECURITY_AUDIT`
719
+
720
+ - **Written by**: the `/security-audit` command
721
+ - **Location**: issue comment
722
+
723
+ Posted after completing a 4-phase security posture audit.
724
+
725
+ ---
726
+
469
727
  ## 5. The Context Chain
470
728
 
471
729
  Lifecycle annotations form an ordered chain. Each stage reads the outputs of all
@@ -512,22 +770,11 @@ Annotations record *what happened*; labels record *where a unit of work is* so a
512
770
  consumer can determine the current stage without reading every comment. The
513
771
  protocol reserves the `workflow:` label namespace:
514
772
 
515
- | Label | Meaning |
516
- |-------|---------|
517
- | `workflow:investigating` | Investigation in progress |
518
- | `workflow:ready-to-build` | Investigation complete, build not started |
519
- | `workflow:building` | Build in progress |
520
- | `workflow:in-review` | Pull request open, review active |
521
- | `workflow:merged` | Pull request merged, work item closed |
522
- | `workflow:invalid` | Closed as invalid |
523
- | `workflow:decomposed` | Split into sub-issues |
524
- | `needs-human` | Blocked; human intervention required |
525
-
526
- **Terminal labels** (processing stops when any is set): `workflow:merged`,
527
- `workflow:invalid`, `workflow:decomposed`, `needs-human`.
528
-
529
- Labels and annotations are complementary: labels give a fast state lookup,
530
- annotations give the full context behind that state.
773
+ > **Canonical reference**: [`docs/spec/label-state-machine.md`](label-state-machine.md)
774
+ >
775
+ > The full state table, transition diagram, terminal labels, and label-exclusivity
776
+ > pattern are defined there. Labels and annotations are complementary: labels give
777
+ > a fast state lookup, annotations give the full context behind that state.
531
778
 
532
779
  ---
533
780
 
@@ -739,7 +986,141 @@ which tool or model produced it — interoperates with this consumer unchanged.
739
986
 
740
987
  ---
741
988
 
742
- ## 10. Versioning
989
+ ## 10. Nested-Command Decomposition Pattern
990
+
991
+ Large command specs that grow past ~50 KB become expensive to load in full on
992
+ every invocation, even when a given run only exercises a fraction of the spec's
993
+ surface. The **nested-command decomposition pattern** addresses this by splitting
994
+ a large spec into a top-level file and one or more supporting sub-files in a
995
+ subdirectory of the same name.
996
+
997
+ ### 10.1 When to decompose
998
+
999
+ Decompose a command spec into a `commands/<name>/` directory when **any two** of
1000
+ the following are true:
1001
+
1002
+ - The spec file exceeds **~30 KB** (token budget becomes significant).
1003
+ - The spec has **two or more separable sub-phases** that are only reached along
1004
+ specific execution paths (e.g., a build phase that is skipped for trivial
1005
+ tasks).
1006
+ - The spec delegates to **distinct named skill scopes** (e.g.,
1007
+ `work-on:build:context`, `work-on:build:architect`) that have their own
1008
+ input/output contracts.
1009
+ - The spec is invoked by other commands that benefit from loading only a subset
1010
+ of its logic (e.g., `orchestrate` spawns `work-on` but only needs its outer
1011
+ routing logic, not every inline sub-phase).
1012
+
1013
+ Do **not** decompose for organizational preference alone. Every subdirectory
1014
+ adds a graph node and must be maintained when the parent spec changes. If a spec
1015
+ is small and its phases are always executed together, keep it as a single file.
1016
+
1017
+ ### 10.2 Naming convention
1018
+
1019
+ ```
1020
+ commands/
1021
+ work-on.md ← top-level entry point (dispatcher + universal rules)
1022
+ work-on/ ← sub-specs, same name as the top-level file
1023
+ build.md ← sub-command (invocable as work-on:build)
1024
+ build/ ← sub-sub-specs for build
1025
+ context.md
1026
+ architect.md
1027
+ implement.md
1028
+ validate.md
1029
+ investigate.md
1030
+ review.md
1031
+ close.md
1032
+ decompose.md
1033
+ ```
1034
+
1035
+ Rules:
1036
+ - The subdirectory name **MUST** match the stem of the top-level spec file
1037
+ (e.g., `work-on.md` → `work-on/`).
1038
+ - Sub-files are named after the sub-phase they implement (lowercase,
1039
+ hyphenated). They are invocable as `<parent>:<sub-file-stem>` via the Skill
1040
+ tool (e.g., `Skill(skill="work-on:build:context", ...)`).
1041
+ - Sub-files that go to depth 3 (e.g., `work-on/build/context.md`) follow the
1042
+ same pattern recursively: their subdirectory is `work-on/build/context/` if
1043
+ further decomposition is ever needed.
1044
+
1045
+ ### 10.3 Automatic pick-up by the installer and graph
1046
+
1047
+ No manual registration is required. Two mechanisms pick up sub-files
1048
+ automatically:
1049
+
1050
+ **Installer (`bin/forgedock.mjs`)**: The `findMarkdownFiles()` helper performs a
1051
+ recursive directory walk over `commands/` (skipping `node_modules` and
1052
+ dot-directories). Every `.md` file discovered — at any depth — is symlinked into
1053
+ `~/.claude/commands/` at the same relative path. A file at
1054
+ `commands/work-on/build/context.md` is installed as
1055
+ `~/.claude/commands/work-on/build/context.md`, making it reachable by Claude
1056
+ Code's Skill resolver as `work-on:build:context`.
1057
+
1058
+ **Spec graph builder (`scripts/build-spec-graph.mjs`)**: The `walk()` function
1059
+ in the builder performs the same recursive directory walk over `commands/`,
1060
+ discovering all spec files regardless of nesting depth. Each discovered file
1061
+ becomes a graph node. The `load-set` query uses `CONTAINS` edges (written when a
1062
+ parent spec references a sub-spec via `Skill()`) to resolve the minimal spec set
1063
+ for a given entry command.
1064
+
1065
+ ### 10.4 Token-saving effect
1066
+
1067
+ Because the installer symlinks sub-specs at their actual nested paths, Claude
1068
+ Code's selective spec loading (Phase 0 of `/work-on`) can load each sub-spec
1069
+ only when execution reaches that sub-phase — skipped sub-phases contribute zero
1070
+ tokens to the session context. The spec knowledge graph's `load-set` query
1071
+ computes the minimal reachable set from the entry command, excluding sub-specs
1072
+ that are never reached by that command's execution graph.
1073
+
1074
+ The measured token savings from decomposing `/work-on` and applying
1075
+ `load-set`-driven selective loading are documented in
1076
+ `docs/articles/command-decomposition-token-savings.md`. The same methodology
1077
+ can be applied to any command spec that meets the decomposition criteria in
1078
+ Section 10.1.
1079
+
1080
+ ---
1081
+
1082
+ ## 11. Adopting FORGE in Your Own Pipeline <!-- renumbered from §10 -->
1083
+
1084
+ FORGE is an open format. Any tool that can read and write platform comments can
1085
+ participate — no dependency on a specific framework, model, or vendor.
1086
+
1087
+ **Minimum viable adoption**:
1088
+
1089
+ 1. Pick the annotation types relevant to your pipeline (`FORGE:INVESTIGATOR` +
1090
+ `FORGE:BUILDER` is a good starting point).
1091
+ 2. Write your agent prompts to post annotated comments after each phase.
1092
+ 3. Write downstream agent prompts to read those comments before starting.
1093
+
1094
+ **Implementation checklist**:
1095
+
1096
+ 1. **Read existing annotations** before starting work on an issue:
1097
+
1098
+ ```bash
1099
+ gh api repos/{OWNER}/{REPO}/issues/{NUMBER}/comments \
1100
+ --jq '.[] | select(.body | contains("FORGE:")) | {id: .id, body: .body}'
1101
+ ```
1102
+
1103
+ 2. **Write annotations** using the schemas in Section 4 after completing each phase.
1104
+
1105
+ 3. **Check for existing annotations** before writing (idempotency):
1106
+
1107
+ ```bash
1108
+ EXISTING=$(gh api repos/{OWNER}/{REPO}/issues/{NUMBER}/comments \
1109
+ --jq '.[] | select(
1110
+ .body | (contains("FORGE:INVESTIGATOR") and contains("INVESTIGATION:COMPLETE"))
1111
+ ) | .id')
1112
+ if [ -n "$EXISTING" ]; then echo "Already investigated — skip"; fi
1113
+ ```
1114
+
1115
+ 4. **Respect label state** — check `workflow:*` labels (Section 6) to determine
1116
+ the current phase and whether the work item is in a terminal state.
1117
+
1118
+ 5. **Use text-contains filtering** as the primary query interface. All FORGE
1119
+ implementations can assume `gh api` or equivalent is available.
1120
+
1121
+ ---
1122
+
1123
+ ## 12. Versioning
743
1124
 
744
1125
  This document specifies **version 1.0**.
745
1126
 
@@ -754,7 +1135,36 @@ Annotations do not carry an explicit version field. Conforming consumers
754
1135
 
755
1136
  ---
756
1137
 
757
- ## 11. Acknowledgements
1138
+ ## 13. Reference Implementation
1139
+
1140
+ The canonical reference implementation of this specification is published as a
1141
+ separate, MIT-licensed npm package:
1142
+
1143
+ **`@forgedock/protocol`** — available at `packages/protocol/` in the ForgeDock
1144
+ repository.
1145
+
1146
+ It provides:
1147
+
1148
+ - `parse(commentBody)` — extracts all annotations from a comment body string
1149
+ - `validate(annotation)` — checks conformance per §3–4; returns `{ valid, errors, warnings }`
1150
+ - `emit(type, fields)` — produces well-formed annotation strings
1151
+ - `emitPartial(type)` — produces the partial sentinel for a type (§3.3)
1152
+
1153
+ A conformance suite in `packages/protocol/fixtures/` covers all 13 reserved
1154
+ types with valid and invalid examples. The CLI runner can be invoked against any
1155
+ fixtures directory:
1156
+
1157
+ ```bash
1158
+ npx @forgedock/protocol fixtures/
1159
+ ```
1160
+
1161
+ **Library version and spec version move together**: a library at version `1.x`
1162
+ implements spec version 1.0. Breaking spec changes (§11, major revisions)
1163
+ require a library major version bump.
1164
+
1165
+ ---
1166
+
1167
+ ## 14. Acknowledgements
758
1168
 
759
1169
  The FORGE Annotation Protocol was first developed and proven in a production
760
1170
  autonomous-development pipeline, where it coordinated investigator, builder,
@@ -762,6 +1172,19 @@ and reviewer agents across tens of thousands of issues. This specification
762
1172
  generalizes that wire format into a tool-neutral, openly licensed standard so
763
1173
  that any agent pipeline can adopt and interoperate with it.
764
1174
 
1175
+ ### Conformance note — Codex adapter (second implementation)
1176
+
1177
+ The Codex-native adapter (`.agents/skills/*/SKILL.md` in the ForgeDock
1178
+ repository) constitutes a second independent implementation of this protocol.
1179
+ It reads the same `commands/*.md` workflow specs and produces/consumes FORGE
1180
+ annotations through a different runtime (different tool calls, different
1181
+ worktree paths, different repo-resolution conventions) than the Claude Code
1182
+ path. Both implementations have been validated against
1183
+ `scripts/conformance-check.mjs`, the repository's automated conformance suite
1184
+ for this specification. This provides concrete evidence of vendor neutrality —
1185
+ the wire format is not incidentally compatible with one runtime; it functions
1186
+ as designed across distinct agent frameworks.
1187
+
765
1188
  ---
766
1189
 
767
1190
  *FORGE Annotation Protocol v1.0 — released under