forgedock 1.1.1 → 1.1.2

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 (171) 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 +20 -0
  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 +68 -19
  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 +80 -8
  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/design-bench.md +5 -1
  27. package/commands/design-render-critique-loop.md +1 -1
  28. package/commands/diagnose.md +2 -1
  29. package/commands/explain.md +2 -1
  30. package/commands/forge-stats.md +121 -2
  31. package/commands/forgedock-init.md +1 -1
  32. package/commands/geo-audit.md +3 -0
  33. package/commands/incident-response.md +2 -1
  34. package/commands/issue.md +23 -2
  35. package/commands/milestone.md +77 -12
  36. package/commands/optimize.md +2 -1
  37. package/commands/orchestrate/config.md +67 -0
  38. package/commands/orchestrate/phase-1-resolve.md +159 -0
  39. package/commands/orchestrate/phase-2-triage.md +126 -0
  40. package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
  41. package/commands/orchestrate/phase-3-dependency.md +591 -0
  42. package/commands/orchestrate/phase-4-execution.md +962 -0
  43. package/commands/orchestrate/phase-5-cleanup.md +47 -0
  44. package/commands/orchestrate/phase-6-report.md +198 -0
  45. package/commands/orchestrate/safety.md +62 -0
  46. package/commands/orchestrate.md +25 -2045
  47. package/commands/pipeline-health/config.md +34 -0
  48. package/commands/pipeline-health/phase-1-context.md +180 -0
  49. package/commands/pipeline-health/phase-2-metrics.md +1729 -0
  50. package/commands/pipeline-health/phase-3-analyze.md +204 -0
  51. package/commands/pipeline-health/phase-4-proposals.md +117 -0
  52. package/commands/pipeline-health/phase-5-report.md +284 -0
  53. package/commands/pipeline-health/phase-6-summary.md +52 -0
  54. package/commands/pipeline-health.md +25 -2401
  55. package/commands/pipeline-resume.md +24 -1
  56. package/commands/pipeline-status.md +65 -0
  57. package/commands/qa-sweep.md +4 -1
  58. package/commands/quality-gate.md +248 -10
  59. package/commands/replay.md +2 -1
  60. package/commands/review-pr-agents/api.md +135 -0
  61. package/commands/review-pr-agents/auth.md +137 -0
  62. package/commands/review-pr-agents/billing.md +101 -0
  63. package/commands/review-pr-agents/concurrency.md +145 -0
  64. package/commands/review-pr-agents/database.md +103 -0
  65. package/commands/review-pr-agents/frontend.md +89 -0
  66. package/commands/review-pr-agents/infra.md +385 -0
  67. package/commands/review-pr-agents/protocols.md +185 -0
  68. package/commands/review-pr-agents/scraper.md +185 -0
  69. package/commands/review-pr-agents/security.md +406 -0
  70. package/commands/review-pr-agents.md +45 -1722
  71. package/commands/review-pr-staging.md +196 -40
  72. package/commands/review-pr.md +591 -52
  73. package/commands/rollback.md +2 -1
  74. package/commands/scope.md +2 -1
  75. package/commands/security-audit.md +2 -1
  76. package/commands/signal-planner.md +623 -0
  77. package/commands/sync-ecosystem.md +1 -0
  78. package/commands/test-gate.md +17 -1
  79. package/commands/validate.md +2 -1
  80. package/commands/work-on/build/architect.md +28 -0
  81. package/commands/work-on/build/context.md +2 -0
  82. package/commands/work-on/build/implement.md +3 -1
  83. package/commands/work-on/build/validate.md +26 -7
  84. package/commands/work-on/build.md +163 -24
  85. package/commands/work-on/close.md +130 -3
  86. package/commands/work-on/decompose.md +19 -1
  87. package/commands/work-on/investigate.md +117 -2
  88. package/commands/work-on/review.md +24 -4
  89. package/commands/work-on-monolithic.md +7 -2
  90. package/commands/work-on.md +202 -4
  91. package/docs/BRAND.md +14 -7
  92. package/docs/CI.md +2 -2
  93. package/docs/CODEX.md +36 -1
  94. package/docs/CONFIG.md +5 -8
  95. package/docs/FORGE-PROTOCOL.md +15 -1064
  96. package/docs/anthropic-devrel-outreach.md +2 -2
  97. package/docs/articles/command-decomposition-token-savings.md +214 -0
  98. package/docs/articles/model-release-playbook.md +131 -0
  99. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
  100. package/docs/claude-breakpoints.json +75 -5
  101. package/docs/design/abc-benchmark.md +1 -1
  102. package/docs/design/design-spec-schema.md +1 -1
  103. package/docs/design/divergent-generation.md +1 -1
  104. package/docs/design/eval-gate-runbook.md +178 -0
  105. package/docs/design/show-hn-draft.md +26 -1
  106. package/docs/design/token-cost-baseline-1298.md +59 -0
  107. package/docs/eval/README.md +117 -0
  108. package/docs/eval/corpus/seed-v1.json +6 -0
  109. package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
  110. package/docs/site/annotations-explained.md +24 -0
  111. package/docs/site/command-learning-path.md +51 -14
  112. package/docs/site/command-reference.md +339 -113
  113. package/docs/site/for-companies.md +95 -0
  114. package/docs/site/forge-annotation-protocol.md +12 -256
  115. package/docs/site/getting-started.md +43 -4
  116. package/docs/site/github-is-the-memory.md +113 -0
  117. package/docs/site/how-it-works.md +3 -13
  118. package/docs/site/index.md +9 -1
  119. package/docs/spec/eval-run-result.md +147 -0
  120. package/docs/spec/forge-protocol-v1.md +441 -18
  121. package/docs/spec/label-state-machine.md +55 -0
  122. package/docs/spec/review-protocol.md +158 -0
  123. package/docs/spec-graph-schema.md +28 -0
  124. package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
  125. package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
  126. package/examples/forgedock-demo/README.md +41 -22
  127. package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
  128. package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
  129. package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
  130. package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
  131. package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
  132. package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
  133. package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
  134. package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
  135. package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
  136. package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
  137. package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
  138. package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
  139. package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
  140. package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
  141. package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
  142. package/examples/forgedock-demo/scripts/smoke.js +18 -1
  143. package/examples/forgedock-demo/src/db.js +36 -11
  144. package/examples/forgedock-demo/src/routes/notes.js +106 -9
  145. package/examples/forgedock-demo/src/server.js +4 -1
  146. package/package.json +3 -1
  147. package/packages/protocol/LICENSE +21 -0
  148. package/packages/protocol/src/cli.js +135 -0
  149. package/packages/protocol/src/emit.js +146 -0
  150. package/packages/protocol/src/index.js +43 -0
  151. package/packages/protocol/src/parse.js +229 -0
  152. package/packages/protocol/src/types.js +171 -0
  153. package/packages/protocol/src/validate.js +122 -0
  154. package/scripts/bench-topology-cost.mjs +372 -0
  155. package/scripts/check-command-docs-drift.sh +198 -0
  156. package/scripts/check-protocol-restatements.sh +176 -0
  157. package/scripts/check-registry/README.md +72 -0
  158. package/scripts/check-registry/manifest.json +6 -0
  159. package/scripts/code-index.sh +454 -0
  160. package/scripts/conformance-check.mjs +168 -0
  161. package/scripts/doctor-pipeline-state.sh +484 -0
  162. package/scripts/eval-gate-baseline.json +17 -0
  163. package/scripts/eval-gate-scorecard.mjs +242 -0
  164. package/scripts/eval-scorecard-aggregator.mjs +252 -0
  165. package/scripts/flaky-quarantine.sh +241 -0
  166. package/scripts/forge-annotation.sh +567 -0
  167. package/scripts/issue-dedup.sh +236 -0
  168. package/scripts/validate-annotation-node.mjs +233 -0
  169. package/scripts/worktree-lifecycle.sh +3 -3
  170. package/templates/devdocs/agent/using-forgedock.md +14 -0
  171. package/docs/site/.vitepress/config.mjs +0 -85
@@ -0,0 +1,55 @@
1
+ # Workflow Label State Machine
2
+
3
+ **Canonical reference** — all pipeline commands and docs point here instead of restating this table inline.
4
+
5
+ See also: [FORGE Annotation Protocol §6](forge-protocol-v1.md#6-label-state-machine) for the protocol-level specification.
6
+
7
+ ---
8
+
9
+ ## States
10
+
11
+ | Label | Meaning | Set by |
12
+ |-------|---------|--------|
13
+ | `workflow:investigating` | Investigation phase active | Investigator agent |
14
+ | `workflow:ready-to-build` | Investigation complete, build not started | Investigator agent |
15
+ | `workflow:building` | Build phase active | Builder agent |
16
+ | `workflow:in-review` | PR created, review active | Orchestrator agent |
17
+ | `workflow:merged` | PR merged, issue closed | Close phase agent |
18
+ | `workflow:invalid` | Issue closed as invalid | Investigator agent |
19
+ | `workflow:decomposed` | Issue decomposed into sub-issues | Decomposer agent |
20
+ | `needs-human` | Pipeline blocked, human intervention required | Any agent on error |
21
+
22
+ ## Transitions
23
+
24
+ ```
25
+ (open)
26
+ → workflow:investigating [Phase 1: Investigate]
27
+ → workflow:ready-to-build [Phase 2: Investigation complete]
28
+ → workflow:building [Phase 3: Build started]
29
+ → workflow:in-review [Phase 4: PR created]
30
+ → workflow:merged [TERMINAL] [Phase 5: PR merged]
31
+ → workflow:invalid [TERMINAL] [Any phase: closed as invalid]
32
+ → workflow:decomposed [TERMINAL] [Phase 2: split into sub-issues]
33
+ → needs-human [TERMINAL] [Any phase: pipeline blocked]
34
+ ```
35
+
36
+ ## Terminal Labels
37
+
38
+ Processing stops when any of these labels is set:
39
+
40
+ - `workflow:merged`
41
+ - `workflow:invalid`
42
+ - `workflow:decomposed`
43
+ - `needs-human`
44
+
45
+ ## Label Exclusivity
46
+
47
+ At most one `workflow:*` label should be active on an issue at any time. When transitioning, always remove all other `workflow:*` labels:
48
+
49
+ ```bash
50
+ gh issue edit {NUMBER} -R {REPO} \
51
+ --add-label "workflow:building" \
52
+ --remove-label "workflow:investigating,workflow:ready-to-build,workflow:in-review,workflow:merged,workflow:invalid,workflow:decomposed"
53
+ ```
54
+
55
+ This is enforced by `scripts/transition-label.sh` — use `resolve_script 'transition-label'` rather than calling `gh issue edit` directly when possible.
@@ -0,0 +1,158 @@
1
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
2
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
3
+
4
+ # Review Protocol — Normative Reference
5
+
6
+ **This is the single normative source for the Evidence-Based Review Protocol and the Structured Findings Protocol.**
7
+
8
+ These protocols are referenced by:
9
+ - `commands/review-pr-agents.md` — agent catalog (includes this via pointer)
10
+ - `commands/review-pr.md` — PR review orchestrator (reads agent catalog which references this)
11
+ - `commands/review-pr-staging.md` — staging review orchestrator (references this directly)
12
+
13
+ Do not duplicate these protocols in any other file. When updating either protocol, update only this file.
14
+
15
+ ---
16
+
17
+ ## Evidence-Based Review Protocol (ALL Agents Follow)
18
+
19
+ Every agent MUST follow this protocol:
20
+
21
+ ### 1. Start From the PR Diff
22
+ ```bash
23
+ # Verify review is still current before reading diff
24
+ CURRENT_SHA=$(gh pr view [PR_NUMBER] --json headRefOid --jq '.headRefOid')
25
+ if [ "$CURRENT_SHA" != "[REVIEW_SHA]" ]; then
26
+ echo "WARNING: PR HEAD changed during review. Review may be stale."
27
+ echo "Review pinned to: [REVIEW_SHA_SHORT]"
28
+ echo "Current HEAD: $(echo $CURRENT_SHA | cut -c1-7)"
29
+ fi
30
+
31
+ gh pr diff [PR_NUMBER] --name-only
32
+ gh pr diff [PR_NUMBER]
33
+ ```
34
+
35
+ **Hot-spot prior**:
36
+ [CHURN_CONTEXT]
37
+
38
+ If a file you are reviewing is listed above as a hot-spot, apply deeper scrutiny to it — high historical churn correlates with defect density. Prefer tracing that file's full code paths (Evidence-Based Review Protocol §2) over a quick pattern scan, and weight ambiguous findings in hot-spot files toward LIKELY rather than POSSIBLE.
39
+
40
+ ### 2. Dynamic Exploration
41
+ - From each changed file, follow imports and function calls
42
+ - Trace data flows across service boundaries (API → Redis → Worker)
43
+ - Search for related code: `grep -rn "function_name" services/`
44
+
45
+ ### 3. Validation Before Reporting
46
+
47
+ | Confidence | Criteria | Action |
48
+ |------------|----------|--------|
49
+ | **CONFIRMED** | Traced the full code path, found specific lines proving the bug | Report as blocking — P1 issue |
50
+ | **LIKELY** | Code pattern suggests issue but mitigations might exist elsewhere | Report with caveat — P2 issue |
51
+ | **POSSIBLE** | Suspicious pattern but couldn't trace the full flow | Report as informational — P3 advisory (non-blocking) |
52
+ | **UNFOUNDED** | Looked for the issue but found mitigations/correct handling | Do NOT report |
53
+
54
+ ### 3.5 REPRODUCTION GATE — Required Before CONFIRMED Classification
55
+
56
+ **MANDATORY**: Before classifying any finding as CONFIRMED, you MUST document one of the following forms of reproduction evidence in your report. A pattern match alone is not sufficient.
57
+
58
+ **Acceptable reproduction evidence (one of)**:
59
+ - **(a) Full code path trace**: List the execution chain from PR-changed code to the failure point. Minimum: 3 steps with specific file + line for each. Example: `services/api/app/routers/billing.py:142 → credits.py:check_balance():87 → returns None → caller at billing.py:148 raises AttributeError`. The chain must terminate at the actual failure — not at "and then it could fail."
60
+ - **(b) Specific input demonstration**: Provide concrete input values that trigger the failure. Example: `POST /api/v1/scrape with {"url": "http://internal:6432/"}` → `requests.get()` hits internal DB port → SSRF confirmed. The values must be specific (not "if an attacker provides a malicious URL") and must map to actual code in the PR diff.
61
+
62
+ **Downgrade rule**: If you cannot produce either (a) or (b) after a reasonable trace attempt, you MUST classify the finding as **POSSIBLE** — not CONFIRMED or LIKELY. Do NOT use CONFIRMED when the finding is based on:
63
+ - A suspicious pattern without tracing whether the condition is reachable via changed code
64
+ - A theoretical exploit path not grounded in specific lines from the diff
65
+ - A heuristic ("this type of code often has X bug") without verification
66
+
67
+ **POSSIBLE findings are informational advisories** — they are logged and tracked but do NOT block merge and do NOT trigger mandatory fix PRs. When in doubt, POSSIBLE is the correct classification. <!-- Added: forge#371 -->
68
+
69
+ ### 4. SEVERITY CLASSIFICATION — TRACE THE IMPACT
70
+
71
+ **CRITICAL RULE: Never dismiss a finding as "minor", "cosmetic", or "harmless" without tracing its downstream impact.** If you spot something unusual (redundant code, odd patterns, duplicated values), ask: "Does this cause a runtime error, data corruption, or wrong behavior in any code path that touches it?" Trace forward through every consumer of the construct.
72
+
73
+ **Severity decision tree:**
74
+ 1. Will this error at runtime? → **HIGH or CRITICAL** (not "minor redundancy")
75
+ 2. Will this produce wrong data silently? → **HIGH**
76
+ 3. Will this cause degraded performance? → **MEDIUM**
77
+ 4. Is it genuinely cosmetic with no runtime impact after tracing all consumers? → **LOW**
78
+
79
+ If you're unsure whether something is cosmetic or a runtime error, **assume it's a runtime error** and flag it for investigation. A false positive costs a minute of review time. A missed runtime error costs production downtime.
80
+
81
+ ### 5. INTERACTION ANALYSIS — "Pre-existing" Is Not "Safe"
82
+
83
+ **CRITICAL RULE: Never dismiss a finding as "pre-existing, not introduced by this PR" without checking whether NEW code in the PR interacts with the pre-existing construct to create a bug.**
84
+
85
+ A redundant import, an unused variable, or a duplicated constant may be harmless in isolation. But new code added in the same scope can turn it into a crash. Example: a local `import os` inside a function is harmless until new code above it calls `os.getenv()` — Python treats `os` as local for the entire function scope, causing `UnboundLocalError` before the import line is reached.
86
+
87
+ **Before dismissing anything as "pre-existing":**
88
+ 1. List every NEW line in the PR that references the pre-existing construct
89
+ 2. For each reference, ask: "Does the pre-existing construct cause this new line to fail at runtime?"
90
+ 3. If yes → CONFIRMED finding, not a dismissal
91
+
92
+ ### 6. FALSE POSITIVE PREVENTION
93
+
94
+ **Before claiming variable scope issues:** Read the FULL function, count indentation levels, check if/else structure.
95
+
96
+ **Before claiming type/unit mismatches:** Trace the variable to its source. Check if naming is misleading (e.g., `balanceCents` might hold microcents).
97
+
98
+ **Before claiming missing functions/imports:** `grep -rn "functionName" .` — check re-exports, aliases.
99
+
100
+ **Before claiming unreachable code:** Check all callers, dynamic dispatch, test code.
101
+
102
+ **Before dismissing redundant imports as harmless:** In Python, a local `import X` inside a function makes `X` a local variable for the ENTIRE function scope. Any use of `X` before that import line will raise `UnboundLocalError`. Check whether any code (existing or new) references `X` before the local import. This is a CONFIRMED CRITICAL if found — it crashes at runtime.
103
+
104
+ ### 7. Report Format
105
+
106
+ Every finding must include:
107
+ - **File:Line** — Exact location
108
+ - **Code snippet** — The problematic code
109
+ - **Evidence** — Why this is a bug (show the code path)
110
+ - **Confidence** — CONFIRMED/LIKELY/POSSIBLE
111
+ - **What you checked** — List files you read to verify
112
+
113
+ ---
114
+
115
+ ## Structured Findings Protocol
116
+
117
+ **All review agents MUST include a machine-readable findings block at the end of their PR comment.** This is NON-OPTIONAL. Without structured findings, the review system cannot create GitHub issues, and findings die as unread PR comments. Every finding that doesn't become a GitHub issue is a finding that will never be addressed.
118
+
119
+ ### Format
120
+
121
+ Append this block at the very end of your comment (after the `---` footer line, still inside the EOF heredoc). It uses HTML comments so it's invisible in rendered markdown:
122
+
123
+ `<!-- REVIEW-FINDINGS-START -->`
124
+ `<!-- FINDING:PREFIX-N|CONFIDENCE|SEVERITY|file.py:line|One-line summary -->`
125
+ `<!-- REVIEW-FINDINGS-END -->`
126
+
127
+ ### Rules
128
+
129
+ 1. **Include ALL findings at CONFIRMED, LIKELY, and POSSIBLE confidence** — every finding becomes a GitHub issue. Nothing stays as just a PR comment. **POSSIBLE findings are informational advisories (P3/non-blocking)** — they are tracked but do not require a fix PR and do not block merge. CONFIRMED and LIKELY findings are blocking at P1/P2 respectively.
130
+ 2. **One line per finding** — sequential numbering (PREFIX-1, PREFIX-2, ...)
131
+ 3. **Confidence**: `CONFIRMED`, `LIKELY`, or `POSSIBLE`
132
+ 4. **Severity**: `CRITICAL`, `HIGH`, `MEDIUM`, or `LOW`
133
+ 5. **Location**: Exact `file:line` reference
134
+ 6. **Summary**: Concise one-line description (no pipe `|` characters in summary)
135
+ 7. **Empty block**: If no findings at all, include just the START/END markers
136
+ 8. **HTML comments**: The block is invisible in rendered markdown but parseable by the review system
137
+
138
+ ### Domain Prefixes
139
+
140
+ | Agent | Prefix |
141
+ |-------|--------|
142
+ | General Security | `SEC` |
143
+ | Auth Conventions | `AUTH` |
144
+ | Billing Integrity | `BILL` |
145
+ | Concurrency | `CONC` |
146
+ | Scraper Logic | `SCRP` |
147
+ | Frontend Quality | `FE` |
148
+ | API Design | `API` |
149
+ | Database & Migration | `DB` |
150
+ | Infrastructure | `INFRA` |
151
+ | Config Schema | `CFG` |
152
+
153
+ ### Example
154
+
155
+ `<!-- REVIEW-FINDINGS-START -->`
156
+ `<!-- FINDING:SEC-1|CONFIRMED|HIGH|services/api/app/routers/scrape.py:45|SQL injection via unsanitized user input in query parameter -->`
157
+ `<!-- FINDING:SEC-2|LIKELY|MEDIUM|services/worker/worker/queues.py:312|Potential SSRF through user-controlled proxy URL -->`
158
+ `<!-- REVIEW-FINDINGS-END -->`
@@ -395,3 +395,31 @@ task-relevant spec set instead of letting the agent load blindly.
395
395
 
396
396
  Shipping the wiring is deferred because no hook-infrastructure layer exists in
397
397
  the repo yet; this section is the spec that a later issue implements against.
398
+
399
+ ## Nested-Command Decomposition and the Graph
400
+
401
+ The spec graph's `walk()` function (in `build-spec-graph.mjs`) and the
402
+ `load-set` query together enable the nested-command decomposition pattern. A
403
+ brief summary is given here; the full naming convention, decomposition criteria,
404
+ and token-saving effect are documented in
405
+ **`docs/spec/forge-protocol-v1.md` § 10 (Nested-Command Decomposition
406
+ Pattern)**.
407
+
408
+ **How nested specs become graph nodes**: `walk()` recursively discovers every
409
+ `commands/**/*.md` file at any depth. Each file is registered as a `cmd:` node
410
+ whose id follows the Skill() colon-delimited form (`cmd:work-on:build:context`
411
+ for `commands/work-on/build/context.md`). `CONTAINS` edges are inferred when a
412
+ parent spec references a child via `Skill(skill="<name>", ...)`.
413
+
414
+ **How `load-set` exploits decomposition**: `load-set <command>` seeds at the
415
+ command's node and walks `CONTAINS` and `REQUIRES` edges forward. A decomposed
416
+ command like `work-on` returns only the 11 files its execution graph actually
417
+ reaches — not the full ~44-spec corpus. Sub-specs that belong to `work-on/build/`
418
+ but are only invoked under specific conditions (e.g., `context.md` is skipped for
419
+ TRIVIAL tasks) can be added or removed from the reachable set by updating the
420
+ `CONTAINS` edges in the parent spec, without changing the query logic.
421
+
422
+ **Token-saving measurement**: See
423
+ `docs/articles/command-decomposition-token-savings.md` for before/after token
424
+ counts for `/review-pr` and `/orchestrate` following their spec decompositions
425
+ in #1271 and #1272.
@@ -0,0 +1,181 @@
1
+ # Economic Self-Governance — Design Spec
2
+
3
+ **Date:** 2026-07-04
4
+ **Status:** Design — ready to build
5
+ **Tracking:** #1317 (economics layer), epic #1320 (five foundations of autonomy)
6
+ **Scope:** Risk×cost go/no-go scoring function, budget-aware scheduler, and backpressure model. Unifies #1313 (preserve `needs-human`) and #1314 (autopilot `--yes` for low-risk) into a single decision model.
7
+
8
+ ---
9
+
10
+ ## 1. Motivation
11
+
12
+ Safety Rule 3 in `/orchestrate` today reads: "no artificial concurrency limit — spawn as many agents as there are issues." That is the opposite of autonomy. Autonomy is **knowing when not to act**.
13
+
14
+ The current decision surface has three static switches:
15
+
16
+ | Surface | Policy | Problem |
17
+ |---------|--------|---------|
18
+ | `/work-on` solo | Ask human at every ambiguity | Over-asks on clear issues |
19
+ | `/orchestrate` | "NEVER ask… merge anyway" | Under-asks on high-risk changes |
20
+ | `/autopilot` | Gate every fix | Blocks low-risk wins behind human review |
21
+
22
+ None of these is a decision — they are static switches baked into prose. The result: an agent either burns compute on issues it should not touch, or stalls on issues it could safely auto-run. Neither is economic.
23
+
24
+ The fix is a **self-governing scheduler** that treats compute as a budget and makes an explicit go/no-go per issue before spawning any agent.
25
+
26
+ ---
27
+
28
+ ## 2. Goals / Non-goals
29
+
30
+ **Goals**
31
+ - A scoring function `(expected_cost, risk_tier, confidence) → {auto, escalate, defer}` runs before each issue is dispatched.
32
+ - Per-run and per-wave budget caps with backpressure replace the "no artificial concurrency limit" rule.
33
+ - `#1313` (preserve `needs-human` for high-risk) and `#1314` (autopilot `--yes` for low-risk) both fall out of the single model as threshold configurations — not separate flags.
34
+ - The decision and its inputs are recorded in `FORGE:ECONOMICS` so runs are auditable.
35
+
36
+ **Non-goals**
37
+ - Real-time token streaming cost measurement (post-run accounting only, fed by #1255/#1295).
38
+ - The durable engine state machine (#1256) — assumed as a substrate but not implemented here.
39
+ - Per-turn interruption of in-flight agents (this spec is pre-dispatch).
40
+
41
+ ---
42
+
43
+ ## 3. Locked Decisions
44
+
45
+ 1. **Decision granularity: per-issue, pre-dispatch.** The go/no-go is computed once before an agent is spawned. Mid-run escalation is a separate concern.
46
+ 2. **Three-outcome model: `auto | escalate | defer`.** `auto` = spawn with no human gate. `escalate` = post a comment and wait for human approval. `defer` = place back in queue with lower priority, do not block the wave.
47
+ 3. **Budget authority: the orchestrator holds the budget, not individual agents.** Agents report estimated cost; the orchestrator decides whether to spend it.
48
+ 4. **Score inputs are observable.** Every input to the scoring function is logged in `FORGE:ECONOMICS` before any agent runs — so a human can audit why an issue was auto-run or escalated.
49
+ 5. **Thresholds are configurable in `forge.yaml`.** Default thresholds ship with the spec; operators can tighten or loosen them without editing command files.
50
+
51
+ ---
52
+
53
+ ## 4. Architecture
54
+
55
+ ### 4.1 Scoring Function
56
+
57
+ ```
58
+ score(issue) → { decision, reasoning, estimated_cost, risk_tier, confidence }
59
+ ```
60
+
61
+ **Inputs:**
62
+
63
+ | Input | Source | Type |
64
+ |-------|--------|------|
65
+ | `expected_cost` | Historical cost-per-issue data (#1255/#1295) or heuristic (label + size estimate) | USD float |
66
+ | `risk_tier` | Domain risk tag on issue label (`risk:low`, `risk:medium`, `risk:high`) or inferred from affected paths | `low \| medium \| high` |
67
+ | `confidence` | FORGE:INVESTIGATOR confidence field, or `0.5` if no investigation comment exists | 0.0–1.0 |
68
+ | `budget_remaining` | Current wave budget minus committed spend | USD float |
69
+ | `needs_human` | Issue has `needs-human` label | bool |
70
+
71
+ **Decision matrix (defaults):**
72
+
73
+ | risk_tier | confidence | expected_cost | decision |
74
+ |-----------|-----------|---------------|----------|
75
+ | `low` | ≥ 0.7 | ≤ $0.50 | `auto` |
76
+ | `low` | ≥ 0.7 | > $0.50 | `escalate` |
77
+ | `low` | < 0.7 | any | `escalate` |
78
+ | `medium` | ≥ 0.8 | ≤ $0.30 | `auto` |
79
+ | `medium` | any other | any | `escalate` |
80
+ | `high` | any | any | `escalate` |
81
+ | any | any | > budget_remaining | `defer` |
82
+ | `needs_human=true` | any | any | `escalate` (always) |
83
+
84
+ Thresholds are overridable via `forge.yaml → economics`:
85
+
86
+ ```yaml
87
+ economics:
88
+ auto_cost_ceiling_usd: 0.50 # max cost for auto-run (low risk)
89
+ medium_auto_cost_ceiling_usd: 0.30
90
+ auto_confidence_floor: 0.70
91
+ medium_confidence_floor: 0.80
92
+ wave_budget_usd: 5.00 # per-wave budget cap
93
+ run_budget_usd: 20.00 # per-run (session) budget cap
94
+ ```
95
+
96
+ ### 4.2 Budget Tracker
97
+
98
+ A simple stateful accumulator maintained by the orchestrator across the wave:
99
+
100
+ ```
101
+ budget_tracker = {
102
+ wave_limit: float, # from forge.yaml or --budget flag
103
+ wave_committed: float, # sum of expected_cost for auto-dispatched issues
104
+ wave_actual: float, # sum of reported actual cost from completed agents
105
+ run_limit: float,
106
+ run_committed: float,
107
+ }
108
+ ```
109
+
110
+ `defer` fires when `wave_committed + expected_cost > wave_limit * 0.90` (10% buffer to absorb cost overruns).
111
+
112
+ Backpressure: when the wave budget is exhausted, remaining issues are set to `workflow:deferred` label and the orchestrator reports a budget summary. They are the first candidates in the next wave.
113
+
114
+ ### 4.3 FORGE:ECONOMICS Annotation
115
+
116
+ Written to the issue before the agent is spawned (or before posting the escalation comment):
117
+
118
+ ```html
119
+ <!-- FORGE:ECONOMICS
120
+ decision: auto
121
+ risk_tier: low
122
+ confidence: 0.82
123
+ expected_cost_usd: 0.18
124
+ budget_remaining_usd: 3.47
125
+ wave: 1
126
+ rationale: "low-risk label, high investigation confidence, well within budget"
127
+ timestamp: 2026-07-04T12:00:00Z
128
+ -->
129
+ ```
130
+
131
+ Downstream stages (verification gate, provenance) can read this annotation to understand the economic context of the decision.
132
+
133
+ ### 4.4 Integration Points
134
+
135
+ **`/orchestrate`**: Phase 2B (issue selection) gains a `score_issues()` step before dispatching agents. Issues that score `escalate` are held; `auto` issues proceed; `defer` issues are re-queued.
136
+
137
+ **`/autopilot`**: The `--fix` phase queries the scoring function instead of the current "gate every fix" heuristic. `--yes` flag sets `auto_confidence_floor: 0.0` and raises cost ceilings — effectively the current `--yes` behavior, but explicit and auditable.
138
+
139
+ **`/work-on`**: Solo interactive use is unaffected. The scoring function is opt-in via `forge.yaml → economics.solo_mode: enabled`.
140
+
141
+ ---
142
+
143
+ ## 5. Implementation Plan
144
+
145
+ ### Increment 1: Scoring function + FORGE:ECONOMICS (no budget tracking)
146
+ - Add `score_issue()` logic to `/orchestrate` Phase 2B.
147
+ - Read domain risk labels and FORGE:INVESTIGATOR confidence.
148
+ - Emit `FORGE:ECONOMICS` annotation.
149
+ - `escalate` path posts a comment and adds `needs-human` label; agent is not spawned.
150
+ - `defer` path is treated as `escalate` in this increment.
151
+
152
+ ### Increment 2: Budget tracker + backpressure
153
+ - Add `budget_tracker` state to orchestrator.
154
+ - Read `forge.yaml → economics` thresholds.
155
+ - `defer` path sets `workflow:deferred` label and skips the issue.
156
+ - Post wave budget summary at end of orchestrator run.
157
+
158
+ ### Increment 3: Unify #1313 and #1314
159
+ - Remove hard-coded "NEVER ask" language from `/orchestrate`.
160
+ - Remove hard-coded "gate every fix" from `/autopilot`.
161
+ - Both commands delegate to the scoring function with appropriate threshold profiles (`orchestrate` uses `medium_confidence_floor`, `autopilot --yes` raises ceilings).
162
+
163
+ ---
164
+
165
+ ## 6. Open Questions
166
+
167
+ - **Cost estimation without history**: For issues with no historical data, the default heuristic is label-based (`bug` → $0.20, `feat` → $0.40, `epic` → $1.00). This needs calibration once #1255 data is available.
168
+ - **Risk tag inference**: If no `risk:*` label exists, infer from affected paths (e.g., changes to `bin/`, `commands/quality-gate.md`, or CI workflows → `risk:high`). Path-based inference is a follow-on to Increment 1.
169
+ - **Wave vs. run budget interaction**: A "run" spans multiple waves in `/autopilot`. The run budget should be the outer limit; wave budget is the inner pacing mechanism.
170
+
171
+ ---
172
+
173
+ ## 7. References
174
+
175
+ - #1317 — this issue
176
+ - #1255, #1295, #1296, #1297 — cost-per-issue accounting (feeds `expected_cost`)
177
+ - #1249 — per-agent model/effort tiering (feeds `expected_cost`)
178
+ - #1313 — preserve `needs-human` for high-risk (subsumed by this spec)
179
+ - #1314 — autopilot `--yes` for low-risk (subsumed by this spec)
180
+ - #1320 — five foundations epic (economics layer)
181
+ - #1256 — durable engine (substrate for stateful budget tracking)
@@ -0,0 +1,189 @@
1
+ # Signed, Replayable Provenance Trail — Design Spec
2
+
3
+ **Date:** 2026-07-04
4
+ **Status:** Design — ready to build
5
+ **Tracking:** #1318 (provenance layer), epic #1320 (five foundations of autonomy)
6
+ **Depends on:** #1256 (durable engine run-log — replayability requires a committed step log)
7
+ **Scope:** Integrity guarantee + replayability layer on top of the existing FORGE annotation protocol (#1291–1294). Every autonomous PR carries a signed attestation linking decisions → verification evidence → alternatives rejected.
8
+
9
+ ---
10
+
11
+ ## 1. Motivation
12
+
13
+ For an organization to allow autonomous merges to production, every change needs a complete, verifiable record of *why it was made, what was verified, and what alternatives were considered and rejected* — reproducibly.
14
+
15
+ Today provenance is scattered `FORGE:*` comments with no integrity guarantee:
16
+
17
+ | Gap | Current state | Problem |
18
+ |-----|--------------|---------|
19
+ | Integrity | Comments are plain Markdown, mutable | Any party can edit or delete them after the fact |
20
+ | Completeness | Each annotation covers one phase | No single artifact links decision → evidence → alternatives |
21
+ | Replayability | State is prose — humans can read it but tools cannot deterministically replay it | Resume re-parses prose heuristically |
22
+ | Attestation | No signed artifact exists | Human reviewers have no cryptographic basis to trust "the agent said it was safe" |
23
+
24
+ **Trust, not capability, is the blocker to auto-merge.** This spec adds integrity + replayability + a signed attestation on top of the existing FORGE protocol, without replacing it.
25
+
26
+ ---
27
+
28
+ ## 2. Goals / Non-goals
29
+
30
+ **Goals**
31
+ - Each autonomous PR carries a `FORGE:PROVENANCE` attestation that links: investigation decision → build decisions → verification evidence → rejected alternatives.
32
+ - A run is replayable from its provenance record + durable engine run-log (#1256).
33
+ - The provenance record validates against the FORGE protocol conformance suite (#1291).
34
+ - Integrity is achieved via a content hash over the structured annotation chain — no external PKI required for v1.
35
+
36
+ **Non-goals**
37
+ - Hardware-rooted signing (TPM, HSM) — out of scope for v1; the content hash gives tamper-evidence without it.
38
+ - Retroactive provenance for runs completed before this spec ships.
39
+ - Per-turn provenance (this spec is per-run / per-PR granularity, matching the durable engine's per-phase checkpoint).
40
+ - Provenance for interactive `/work-on` runs (headless/orchestrated first, interactive later).
41
+
42
+ ---
43
+
44
+ ## 3. Locked Decisions
45
+
46
+ 1. **Attestation format: structured HTML comment (`FORGE:PROVENANCE`) on the PR.** Consistent with the existing annotation protocol. Readable by humans in the PR thread and queryable by the same text-contains filters used today.
47
+ 2. **Integrity mechanism: SHA-256 content hash over a canonical serialization of the annotation chain.** The hash is computed over the ordered sequence of `FORGE:*` annotation bodies (canonically serialized as JSON). Anyone with the run-log can recompute it.
48
+ 3. **Replayability: the durable engine run-log is the replay substrate.** The `FORGE:PROVENANCE` record carries a pointer to the run-log location (issue comment ID sequence). A conformant replayer reads those comments in order and reconstructs the pipeline state.
49
+ 4. **Chain of custody: each annotation carries a `seq` (sequence number) and `prev_hash` (hash of the prior annotation).** This forms a tamper-evident linked list. Adding, removing, or reordering annotations breaks the hash chain.
50
+ 5. **The attestation is written by the durable engine, not by individual phase agents.** Agents write their phase annotations as today; the engine writes the final `FORGE:PROVENANCE` after the merge gate passes.
51
+
52
+ ---
53
+
54
+ ## 4. Architecture
55
+
56
+ ### 4.1 Annotation Chain Extension
57
+
58
+ Existing FORGE annotations gain two new fields (backward-compatible — consumers that do not understand them ignore them):
59
+
60
+ ```
61
+ <!-- FORGE:INVESTIGATOR
62
+ seq: 1
63
+ prev_hash: "genesis"
64
+ ...existing fields...
65
+ body_hash: "sha256:a1b2c3..."
66
+ -->
67
+ ```
68
+
69
+ | New field | Type | Description |
70
+ |-----------|------|-------------|
71
+ | `seq` | integer | Position in the annotation chain for this run (1-indexed) |
72
+ | `prev_hash` | string | SHA-256 of the prior annotation's canonical body, or `"genesis"` for the first |
73
+ | `body_hash` | string | SHA-256 of this annotation's canonical body (self-hash, written last) |
74
+
75
+ **Canonical body**: the annotation content between the `<!-- FORGE:TAG` opening and the `-->` closing, with leading/trailing whitespace stripped and line endings normalized to `\n`, serialized as a UTF-8 JSON string.
76
+
77
+ ### 4.2 FORGE:PROVENANCE Annotation
78
+
79
+ Written to the PR by the durable engine after the merge gate passes, before the merge commit:
80
+
81
+ ```html
82
+ <!-- FORGE:PROVENANCE
83
+ run_id: "run-abc123"
84
+ issue: 1317
85
+ pr: 1460
86
+ pipeline_version: "1.0.21"
87
+ agent_model: "claude-sonnet-4-6"
88
+
89
+ chain:
90
+ - seq: 1 tag: INVESTIGATOR comment_id: 2345678901 body_hash: "sha256:a1b2..."
91
+ - seq: 2 tag: ARCHITECT comment_id: 2345678910 body_hash: "sha256:b2c3..."
92
+ - seq: 3 tag: BUILDER comment_id: 2345678920 body_hash: "sha256:c3d4..."
93
+ - seq: 4 tag: REVIEWER comment_id: 2345678930 body_hash: "sha256:d4e5..."
94
+ - seq: 5 tag: QUALITY_GATE comment_id: 2345678940 body_hash: "sha256:e5f6..."
95
+ - seq: 6 tag: ECONOMICS comment_id: 2345678950 body_hash: "sha256:f6a7..."
96
+
97
+ chain_hash: "sha256:0123456789abcdef..."
98
+ verification_passed: true
99
+ alternatives_considered:
100
+ - "Inline fix without issue — rejected: no traceability"
101
+ - "Defer to manual review — rejected: low-risk score 0.82"
102
+ merge_authorized_by: "economic-self-governance"
103
+ timestamp: 2026-07-04T18:00:00Z
104
+ forge_protocol_version: "1.0"
105
+ -->
106
+ <!-- FORGE:PROVENANCE:COMPLETE -->
107
+ ```
108
+
109
+ **`chain_hash`**: SHA-256 of the concatenated `body_hash` values in `seq` order, joined with `\n`. Recomputable from the listed comment IDs alone.
110
+
111
+ ### 4.3 Replayability Contract
112
+
113
+ A conformant replayer MUST be able to reconstruct the pipeline state for a given `run_id` by:
114
+
115
+ 1. Reading the `FORGE:PROVENANCE` annotation from the PR to get the `chain` (comment ID list).
116
+ 2. Fetching each comment in `seq` order from the GitHub API.
117
+ 3. Parsing each `FORGE:*` annotation body.
118
+ 4. Recomputing the `chain_hash` and asserting it matches the recorded value.
119
+ 5. Replaying the durable engine run-log (from `#1256`) for per-phase step details.
120
+
121
+ Step 4 is the integrity check. A mismatch means the annotation chain was tampered with after the run.
122
+
123
+ ### 4.4 Conformance Suite Integration (#1291)
124
+
125
+ The FORGE protocol conformance suite gains a new test category: **Provenance Conformance**.
126
+
127
+ | Test | Pass condition |
128
+ |------|---------------|
129
+ | `P-01` | PR has exactly one `FORGE:PROVENANCE` annotation followed by `FORGE:PROVENANCE:COMPLETE` |
130
+ | `P-02` | All `seq` values in the chain are contiguous starting from 1 |
131
+ | `P-03` | Each `prev_hash` matches the `body_hash` of the prior annotation (or `"genesis"` for seq=1) |
132
+ | `P-04` | `chain_hash` recomputes correctly from the listed `body_hash` values |
133
+ | `P-05` | All annotations referenced in the chain are fetchable and parse as valid FORGE annotations |
134
+ | `P-06` | `timestamp` is an ISO 8601 UTC datetime |
135
+ | `P-07` | `forge_protocol_version` is present and a known value |
136
+
137
+ ### 4.5 Integration Points
138
+
139
+ **Durable engine (`#1256`)**: After merge gate passes, the engine invokes `write_provenance()`:
140
+ - Collects all annotation comment IDs from the run-log.
141
+ - Fetches each annotation body and computes `body_hash` values.
142
+ - Computes `chain_hash`.
143
+ - Posts `FORGE:PROVENANCE` to the PR.
144
+
145
+ **Quality gate (`/quality-gate`)**: Gains a new check: `PROVENANCE` — verifies `P-01` through `P-07`. Fails the gate if any check fails on an autonomous run. Human-initiated runs emit a warning (not a hard failure) if provenance is absent.
146
+
147
+ **`/replay` command**: Uses the `chain` from `FORGE:PROVENANCE` as the replay index instead of scanning all comments for `FORGE:*` annotations. This is faster and guaranteed-ordered.
148
+
149
+ ---
150
+
151
+ ## 5. Implementation Plan
152
+
153
+ ### Increment 1: Chain fields on existing annotations (non-breaking)
154
+ - Modify durable engine to write `seq`, `prev_hash`, and `body_hash` on each annotation it posts.
155
+ - No consumer changes required — fields are additive.
156
+ - Validate that existing annotations without these fields are still parseable.
157
+
158
+ ### Increment 2: FORGE:PROVENANCE annotation
159
+ - Engine writes `FORGE:PROVENANCE` to the PR after merge gate passes.
160
+ - Includes `chain`, `chain_hash`, `verification_passed`, `timestamp`.
161
+ - `/replay` updated to use the chain index when present.
162
+
163
+ ### Increment 3: Conformance tests + quality gate check
164
+ - Add `P-01` through `P-07` tests to the conformance suite (#1291).
165
+ - Add `PROVENANCE` check to `/quality-gate` (warning on human runs, hard failure on autonomous runs).
166
+
167
+ ### Increment 4: Replayability validation
168
+ - Add a `verify_provenance(run_id)` script to `scripts/`.
169
+ - Script fetches the PR, reads `FORGE:PROVENANCE`, fetches all chained comments, recomputes `chain_hash`, and reports pass/fail.
170
+
171
+ ---
172
+
173
+ ## 6. Open Questions
174
+
175
+ - **Comment mutability**: GitHub allows editing comments. The hash chain detects tampering but does not prevent it. For v2, consider posting annotations to an immutable artifact (e.g., a GitHub Release asset or a signed commit note) as an optional hardened mode.
176
+ - **`body_hash` for legacy annotations**: If an annotation was written before this spec (no `body_hash` field), the chain is broken. Acceptable for v1: the `FORGE:PROVENANCE` chain only covers annotations written by the durable engine (which will be updated atomically). Legacy runs have no provenance claim.
177
+ - **`alternatives_considered` source**: In v1 this is written by the engine based on the economics decision (#1317) and the quality-gate outcome. A richer alternatives record (e.g., architect alternatives from `FORGE:ARCHITECT`) can be pulled in a later increment.
178
+
179
+ ---
180
+
181
+ ## 7. References
182
+
183
+ - #1318 — this issue
184
+ - #1291–1294 — FORGE protocol conformance suite (seed schema)
185
+ - #1256 — durable engine (run-log substrate; required for replayability)
186
+ - #1315 — outcome-based acceptance gate (supplies "what was verified" evidence)
187
+ - #1317 — economic self-governance (supplies `merge_authorized_by` and `alternatives_considered`)
188
+ - #1320 — five foundations epic (provenance layer)
189
+ - `docs/spec/forge-protocol-v1.md` — FORGE annotation protocol v1.0