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
@@ -11,9 +11,11 @@ argument-hint: [issue number] [--repo {owner}/{repo}] [--gh-flag "-R {owner}/{re
11
11
 
12
12
  Standalone investigation phase for the work-on pipeline. Validates whether an issue is real, determines root cause, posts a structured FORGE:INVESTIGATOR comment to GitHub, and updates workflow labels.
13
13
 
14
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
14
+ **Agent model policy**: `model: "sonnet"` (standard tier). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
15
15
  **NEVER use plan mode (EnterPlanMode).**
16
16
 
17
+ <!-- FORGE:SPEC_LOADED — work-on/investigate.md loaded and active. Agent is bound by this spec. -->
18
+
17
19
  ---
18
20
 
19
21
  ## Inputs
@@ -27,6 +29,67 @@ If called from `work-on`, these are passed through. If invoked standalone, `--re
27
29
 
28
30
  ---
29
31
 
32
+ ## Phase 0.5: Memory Retrieval — Prior Run Priors <!-- Added: forge#1316 -->
33
+
34
+ **Goal**: Before investigating, retrieve the top-k relevant prior pipeline runs from the per-repo memory index. Inject confirmed priors into the investigation context so the pipeline compounds intelligence across runs.
35
+
36
+ **This phase is non-blocking** — if the memory index is absent or retrieval fails, log the reason and proceed to Phase 1A. Never stall the pipeline for memory.
37
+
38
+ **Note on Gist visibility (forge#1587)**: The memory-index Gist is created **secret** (see `close.md` Phase C5.2 — no `--public` flag). `gh gist list` and `gh gist view` operate against the authenticated user's own Gists by description/id regardless of public/secret status, so the retrieval steps below work unchanged against a secret Gist. No code change is needed here — this note exists only so a future edit doesn't reintroduce a "must be public to be readable" assumption.
39
+
40
+ ### Step 1: Locate memory index Gist
41
+
42
+ The memory index is a GitHub Gist tagged `<!-- FORGE:MEMORY_INDEX: {GH_REPO} -->`. Find it:
43
+
44
+ ```bash
45
+ MEMORY_INDEX_URL=$(gh gist list --limit 100 \
46
+ --jq '.[] | select(.description | contains("FORGE:MEMORY_INDEX: {GH_REPO}")) | .url' 2>/dev/null | head -1)
47
+
48
+ MEMORY_INDEX_ID=$(gh gist list --limit 100 \
49
+ --jq '.[] | select(.description | contains("FORGE:MEMORY_INDEX: {GH_REPO}")) | .id' 2>/dev/null | head -1)
50
+ ```
51
+
52
+ If no memory index found: log `[MEMORY] No memory index for {GH_REPO} — starting fresh` and skip to Phase 1A.
53
+
54
+ ### Step 2: Retrieve relevant priors (top-k similarity)
55
+
56
+ Read the memory index content:
57
+
58
+ ```bash
59
+ MEMORY_CONTENT=$(gh gist view "$MEMORY_INDEX_ID" 2>/dev/null)
60
+ ```
61
+
62
+ The memory index is a newline-delimited list of prior run entries, each formatted as:
63
+
64
+ ```
65
+ MEMORY_ENTRY: issue={N} title="{TITLE}" domain="{DOMAIN_TAGS}" root_cause="{ROOT_CAUSE_SUMMARY}" outcome="{merged|invalid|blocked}" files="{AFFECTED_FILES}" lesson="{KEY_LESSON_ONE_LINE}" timestamp={ISO}
66
+ ```
67
+
68
+ **Retrieve top-3 relevant priors** by matching against the current issue title and body:
69
+
70
+ 1. Extract keywords from the current issue title: lowercase, remove stop words, keep noun/verb tokens
71
+ 2. Score each memory entry: +2 for a file path overlap, +1 per keyword match in title/root_cause/lesson
72
+ 3. Return the top-3 highest-scoring entries (minimum score ≥ 1 to filter noise)
73
+
74
+ If no entries score ≥ 1: log `[MEMORY] No relevant priors found` and skip to Phase 1A.
75
+
76
+ ### Step 3: Inject priors into investigation context
77
+
78
+ For each retrieved prior, emit a structured block that Phase 1B can reference:
79
+
80
+ ```
81
+ [MEMORY PRIOR #{RANK}]
82
+ Issue: #{issue} — {title}
83
+ Root cause: {root_cause}
84
+ Outcome: {outcome}
85
+ Key lesson: {lesson}
86
+ Affected files: {files}
87
+ ```
88
+
89
+ Print these blocks to stdout before Phase 1A begins. During Phase 1B (step 3 — blame analysis and step 5 — pickaxe pass), **explicitly check whether the current issue's suspected symbol or file appears in any prior root cause or affected files**. If a match is found, cite it in the FORGE:INVESTIGATOR comment's History Findings field as a `[MEMORY PRIOR]` hit.
90
+
91
+ ---
92
+
30
93
  ## Phase 1A: Load Issue & Check Resume State
31
94
 
32
95
  ```bash
@@ -67,10 +130,33 @@ The target repo is `{GH_REPO}` (resolved from `forge.yaml → project`). The wor
67
130
 
68
131
  If the issue specifies a **Code branch** (`**Code branch**: \`{branch}\``), check out that branch — the affected files may not be on the default branch.
69
132
 
133
+ ### Code Index Query (run BEFORE any grep exploration)
134
+
135
+ If `scripts/code-index.sh` exists under `{REPO_PATH}`, query the pre-built symbol/import index first. This yields deterministic answers in one tool call and avoids redundant grep exploration across agents.
136
+
137
+ ```bash
138
+ # Step 0A: Ensure index is current (cache-hit on unchanged HEAD — zero cost if already built)
139
+ bash {REPO_PATH}/scripts/code-index.sh --repo-path {REPO_PATH} 2>/dev/null || true
140
+
141
+ # Step 0B: Look up the symbol or file named in the issue (replace {SYMBOL} with the relevant name)
142
+ bash {REPO_PATH}/scripts/code-index.sh query --symbol {SYMBOL} --repo-path {REPO_PATH} 2>/dev/null || true
143
+
144
+ # Step 0C: Find all callers of that symbol
145
+ bash {REPO_PATH}/scripts/code-index.sh query --callers {SYMBOL} --repo-path {REPO_PATH} 2>/dev/null || true
146
+
147
+ # Step 0D: Find all importers of an affected file
148
+ bash {REPO_PATH}/scripts/code-index.sh query --importers {AFFECTED_FILE} --repo-path {REPO_PATH} 2>/dev/null || true
149
+
150
+ # Step 0E: Get all files in the affected domain (from issue labels/body)
151
+ bash {REPO_PATH}/scripts/code-index.sh query --domain {DOMAIN_LABEL} --repo-path {REPO_PATH} 2>/dev/null || true
152
+ ```
153
+
154
+ **Fallback**: If `scripts/code-index.sh` is absent or returns no results, proceed with standard grep exploration below. The index is an acceleration layer — its absence never blocks investigation.
155
+
70
156
  ### Investigation steps
71
157
 
72
158
  1. **Check the right branch** — read from the branch specified in the issue body (`**Code branch**: \`{branch}\``) if present
73
- 2. **Read domain files** — start with the key files for the affected domain
159
+ 2. **Read domain files** — start with the key files for the affected domain (use index query results from Step 0E as the file list; fall back to directory inspection if index is absent)
74
160
  3. **Verify claims** — does the code actually have the problem described?
75
161
  4. **Git blame** — trace when/why the relevant code was written. Run bounded, local commands (no network round-trip):
76
162
  ```bash
@@ -106,6 +192,19 @@ If the issue specifies a **Code branch** (`**Code branch**: \`{branch}\``), chec
106
192
 
107
193
  The comment MUST include `<!-- INVESTIGATION:COMPLETE -->` at the very end, AFTER all required sections are present. This marker signals the investigation finished successfully.
108
194
 
195
+ Before posting, resolve the attribution annotation link from `forge.yaml`:
196
+
197
+ ```bash
198
+ ATTRIBUTION_ANNOTATION_LINK=$(grep -A5 "^attribution:" forge.yaml 2>/dev/null | grep "annotation_link:" | awk '{print $2}' | tr -d '"' || echo "false")
199
+ ANNOTATION_LINK_FOOTER=""
200
+ if [ "$ATTRIBUTION_ANNOTATION_LINK" = "true" ]; then
201
+ ANNOTATION_LINK_FOOTER="
202
+
203
+ ---
204
+ *Pipeline powered by [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock)*"
205
+ fi
206
+ ```
207
+
109
208
  ```bash
110
209
  gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:INVESTIGATOR -->
111
210
  ## Investigation Report
@@ -146,6 +245,22 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:INVESTIGATOR -->
146
245
  **{YES|NO}** — {reason}
147
246
  {if YES: proposed sub-issues with titles and dependencies}
148
247
 
248
+ ### Acceptance Spec
249
+ {For each item in the issue's ## Acceptance Criteria section, emit one machine-checkable check line using the format below. If the issue has no Acceptance Criteria section, derive checks from the Recommendation above. Each check MUST be specific, observable, and testable — not vague prose. Checks are consumed by build/validate Phase B6.5 as the merge gate.}
250
+
251
+ ```
252
+ ACCEPTANCE_CHECK: id={ac-1} type={exists|contains|command|behavior} target={file_path|command|url} matcher={string|exit_0|regex} description={one-line human description}
253
+ ACCEPTANCE_CHECK: id={ac-2} type={exists|contains|command|behavior} target={file_path|command|url} matcher={string|exit_0|regex} description={one-line human description}
254
+ ```
255
+
256
+ **Check types**:
257
+ - `exists` — assert a file or directory exists (`target` = path, `matcher` = ignored)
258
+ - `contains` — assert a file contains a string or regex (`target` = file path, `matcher` = string/regex)
259
+ - `command` — run a shell command and assert exit 0 (`target` = shell command, `matcher` = `exit_0`)
260
+ - `behavior` — assert a runtime/observable behavior via shell command (`target` = shell command, `matcher` = expected output string or regex)
261
+
262
+ **Skipping**: if the issue has no verifiable acceptance criteria and none can be derived from the recommendation, emit a single sentinel: `ACCEPTANCE_CHECK: id=ac-skip type=skipped target=none matcher=none description=No machine-checkable criteria available — human review required`
263
+ ${ANNOTATION_LINK_FOOTER}
149
264
  <!-- INVESTIGATION:COMPLETE -->"
150
265
  ```
151
266
 
@@ -12,9 +12,11 @@ argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree P
12
12
  **Invoked by**: `work-on.md` Phase 4–5, after `build/validate.md` returns `GATE_PASSED: true`.
13
13
  **Output**: Push branch, create PR, invoke /review-pr --auto-merge, return result to caller.
14
14
 
15
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
15
+ **Agent model policy**: `model: "sonnet"` (standard tier). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
16
16
  **NEVER use plan mode (EnterPlanMode).**
17
17
 
18
+ <!-- FORGE:SPEC_LOADED — work-on/review.md loaded and active. Agent is bound by this spec. -->
19
+
18
20
  ---
19
21
 
20
22
  ## Inputs
@@ -146,7 +148,21 @@ Derive from issue title:
146
148
  - `docs(...):` → `Docs: {description}`
147
149
  - fallback: use issue title as-is
148
150
 
149
- ### R2B: Create PR
151
+ ### R2B: Resolve attribution footer (optional)
152
+
153
+ Before creating the PR, check `forge.yaml → attribution.pr_footer`:
154
+
155
+ ```bash
156
+ ATTRIBUTION_PR_FOOTER=$(grep -A5 "^attribution:" forge.yaml 2>/dev/null | grep "pr_footer:" | awk '{print $2}' | tr -d '"' || echo "false")
157
+ ```
158
+
159
+ If `ATTRIBUTION_PR_FOOTER` is `true`, append the following footer to the PR body (once — never duplicate on retries):
160
+
161
+ ```
162
+ > Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.
163
+ ```
164
+
165
+ ### R2C: Create PR
150
166
 
151
167
  ```bash
152
168
  gh pr create {GH_FLAG} \
@@ -170,18 +186,22 @@ gh pr create {GH_FLAG} \
170
186
  Closes #{NUMBER}
171
187
 
172
188
  **Implementation branch**: \`{BRANCH}\`
173
- **Base**: \`{PR_BASE}\`"
189
+ **Base**: \`{PR_BASE}\`
190
+ {IF_ATTRIBUTION_PR_FOOTER_TRUE:
191
+ > Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.}"
174
192
  ```
175
193
 
176
194
  **Note**: `Closes #{NUMBER}` documents intent but does NOT auto-close for non-default-branch PRs. The close subcommand handles explicit closure after merge.
177
195
 
196
+ **Attribution guard**: The footer line is appended once at PR creation. If the PR already exists (resume path), do NOT append the footer again — check the existing PR body first.
197
+
178
198
  If PR creation fails because a PR already exists for this branch:
179
199
  ```bash
180
200
  gh pr list {GH_FLAG} --head {BRANCH} --json number,url --jq '.[0]'
181
201
  ```
182
202
  Use the existing PR number and continue.
183
203
 
184
- ### R2C: Update labels
204
+ ### R2D: Update labels
185
205
 
186
206
  ```bash
187
207
  gh issue edit {NUMBER} {GH_FLAG} \
@@ -12,9 +12,14 @@ install: internal
12
12
 
13
13
  Orchestrator for the full issue lifecycle: investigate → build → review → merge → close. GitHub issues are the persistent context layer — read existing comments before starting, write structured reports back, use `workflow:*` labels to track state.
14
14
 
15
- **Agent model policy**: Default `model: "sonnet"`. Fallback: `model: "opus"` if Sonnet is rate-limited.
15
+ **Agent model policy**: `model: "sonnet"` (standard tier). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
16
16
  **NEVER use plan mode (EnterPlanMode).**
17
17
 
18
+ > **Relationship to `/work-on` (canonical path)**: This file is a `[BENCHMARK]` reference variant. It documents the same inline-execution model that `/work-on` Phase 3 and `work-on/build.md` use as their **default** for STANDARD/fast-lane issues — all build sub-phases (context → architect → implement → validate) run inline in the current context window with no `Skill()` sub-agent spawns. The difference is that this file omits the worktree lifecycle, `FORGE:CONTRACT` posting, and the Spawn-Decision exception path for large builds. Use `/work-on` for production runs; use this file for baseline benchmarking or when comparing single-prompt token cost against the modular path. See `work-on/build.md` (Canonical Build Path section) for the reconciled build topology. <!-- Added: forge#1276 -->
19
+ **NEVER use the Agent tool** — this spec executes all phases inline as a single monolithic prompt. The Agent tool would spawn a subprocess outside this context, breaking the single-prompt contract and losing all accumulated pipeline state.
20
+
21
+ <!-- FORGE:SPEC_LOADED — work-on-monolithic.md loaded and active. Agent is bound by this spec. -->
22
+
18
23
  ### Compaction Resilience
19
24
 
20
25
  1. Write state to GitHub after EVERY significant step
@@ -65,7 +70,7 @@ gh api repos/{GH_REPO}/issues/{NUMBER}/comments --jq '.[] | {id: .id, author: .u
65
70
 
66
71
  **Check**: state (closed → STOP), terminal labels (`workflow:merged`/`workflow:invalid` → STOP), existing agent comments (`FORGE:INVESTIGATOR`, `FORGE:CONTRACT`, `FORGE:BUILDER`, `FORGE:TRAJECTORY`), parent tracker status.
67
72
 
68
- **Determine resume point**: No comments → Phase 1. Investigation exists + ready-to-build → Phase 3. Builder + no PR → Phase 4. Builder + PR open → Phase 5. PR merged + issue open → close issue.
73
+ **Determine resume point**: No comments → Phase 1. Investigation exists + ready-to-build → Phase 3. Builder:COMPLETE + no PR → Phase 4. Builder without :COMPLETE (partial/interrupted build) + no PR → Phase 3 (partial-build cleanup). Builder + PR open → Phase 5. PR merged + issue open → close issue.
69
74
 
70
75
  **Classify lane**: Milestone → feature lane (`milestone/{slug}`). No milestone → fast lane (`staging`).
71
76
 
@@ -11,8 +11,21 @@ argument-hint: [issue number or "next" to pick highest priority]
11
11
 
12
12
  Orchestrator for the full issue lifecycle: investigate → decompose (if needed) → build → review → merge → close. GitHub issues are the persistent context layer — read existing comments before starting, write structured reports back, use `workflow:*` labels to track state.
13
13
 
14
- **Agent model policy**: Default `model: "sonnet"`. Fallback: `model: "opus"` if Sonnet is rate-limited.
14
+ **Agent model policy**: `model: "sonnet"` (standard tier). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
15
15
  **NEVER use plan mode (EnterPlanMode).**
16
+ **NEVER use the Agent tool** — this spec uses `Skill(...)` for sub-phase dispatch. The Agent tool spawns opaque subprocesses that bypass phase protocols, skip FORGE annotations, and cannot be constrained by allowed-tools. Always use `Skill(skill="...", args="...")` for sub-phase invocations.
17
+
18
+ <!-- FORGE:SPEC_LOADED — work-on.md loaded and active. Agent is bound by this spec. -->
19
+
20
+ ## HARD RULES — READ BEFORE ANYTHING ELSE
21
+
22
+ 1. **Every sub-phase MUST be invoked via `Skill(...)`.** You do NOT implement inline. You invoke `Skill(skill="work-on/investigate", ...)`, `Skill(skill="work-on/build", ...)`, etc. The Skill tool invocation is what triggers label updates, FORGE annotations, and structured output. Without it, the phase has no paper trail.
23
+
24
+ 2. **Write to GitHub after EVERY phase.** Every FORGE annotation (HEARTBEAT, INVESTIGATOR, CONTRACT, BUILDER, etc.) must be posted before the next phase starts. A phase that completes without a GitHub write is effectively invisible to the stall detector and future sessions.
25
+
26
+ 3. **Follow the Universal Phase Dispatcher.** The phase sequence table is the SINGLE source of truth for transitions. Do NOT skip phases, do NOT reorder phases, do NOT treat intermediate completions as terminal. Only the terminal states listed in the Dispatcher allow stopping.
27
+
28
+ 4. **PRs NEVER target `main`.** Target `staging` (fast lane) or `milestone/{slug}` (feature lane). A PR to main is a pipeline violation regardless of what the issue description says.
16
29
 
17
30
  ### Compaction Resilience
18
31
 
@@ -58,6 +71,44 @@ Orchestrator for the full issue lifecycle: investigate → decompose (if needed)
58
71
 
59
72
  ---
60
73
 
74
+ ## Spawn-Decision Policy
75
+
76
+ <!-- FORGE:SPAWN_POLICY — Canonical spawn-decision table. Sibling specs (orchestrate.md, review-pr.md) link to this section. Sub-issues #1276–#1279 reference this table. -->
77
+
78
+ **Default: run inline.** Every skill, phase, and sub-agent runs inline in the current context unless one of the three criteria below explicitly applies. A sub-agent buys exactly two things — parallelism and context isolation. If neither is needed, forking is waste.
79
+
80
+ ### Spawn-Decision Table
81
+
82
+ | Row | Criterion | Fork? | Example |
83
+ |-----|-----------|-------|---------|
84
+ | a | **Parallel fan-out** — two or more independent work units can execute concurrently and the total wall time saving justifies the fork overhead | YES — spawn one sub-agent per work unit | `/orchestrate` dispatching multiple `/work-on` agents; `review-pr` spawning domain-specific reviewers in parallel |
85
+ | b | **Fresh-context isolation** — the work unit is a structured review or audit whose value depends on seeing the artefact without the builder's accumulated context bias, AND the review result is load-bearing for the merge decision | YES — spawn a dedicated sub-agent | Phase 5C review-fork when build context is large (see Row c for the quantitative threshold) |
86
+ | c | **Parent context near overflow** — the parent agent has made ≥20 Skill invocations OR the build changed ≥10 files, meaning delegating review inline risks a mid-review token overflow | YES — spawn a fresh sub-agent for review | Phase 5C: `Skill(skill="work-on/review", …)` instead of direct `review-pr` invocation |
87
+
88
+ **If none of the three rows match: run inline.** Do not fork for convenience, narrative clarity, or to avoid reading a large file. Context cost of a fork (spawning, context reconstruction, result aggregation) is paid every time, even when parallelism or isolation adds no value.
89
+
90
+ ### Depth Budget
91
+
92
+ **Available depth**: 5 levels (since Claude Code v2.1.172).
93
+
94
+ **Target depth for a standard run**: ≤ 3.
95
+
96
+ | Depth | Agent | Notes |
97
+ |-------|-------|-------|
98
+ | 1 | `/orchestrate` | Top-level dispatcher — never implements directly |
99
+ | 2 | `/work-on` | Issue pipeline — runs build phases inline |
100
+ | 3 | Parallel reviewers (Row a/b/c fork) | Domain review agents spawned by Phase 5C |
101
+
102
+ **Build phases (3A–3M) run inline at depth 2** — they are sequential sub-phases of `/work-on`, not independent agents. Forking the build into a sub-agent (depth 3) is a violation of Row a/b/c unless the build itself fans out independently scoped work units.
103
+
104
+ **Depth 4–5 are reserved** for exceptional cases (e.g. an orchestrate agent that itself spawns an orchestrate agent for a sub-milestone). Agents that reach depth 4 MUST log a justification comment on the relevant issue.
105
+
106
+ ### Phase 5C Cross-Reference
107
+
108
+ The existing Phase 5C context-budget check (≥10 changed files OR ≥20 Skill invocations → spawn `work-on/review` sub-agent) is an instance of **Row (c)** above. The quantitative thresholds are not changed — only their framing: they are now a specific application of the spawn-decision table, not a standalone ad-hoc rule.
109
+
110
+ ---
111
+
61
112
  ## Pipeline Rules
62
113
 
63
114
  - **NEVER merge to main.** PRs target `staging` (fast lane) or `milestone/{slug}` (feature lane).
@@ -193,7 +244,7 @@ gh api repos/{GH_REPO}/issues/{NUMBER}/comments --jq '.[] | {id: .id, author: .u
193
244
 
194
245
  **Check**: state (closed → STOP), terminal labels (`workflow:merged`/`workflow:invalid` → STOP), existing agent comments (`FORGE:INVESTIGATOR`, `FORGE:DECOMPOSED`, `FORGE:CONTRACT`, `FORGE:BUILDER`, `FORGE:TRAJECTORY`, `FORGE:DECISION_RECORD`), parent tracker status, sub-issue status.
195
246
 
196
- **Determine resume point**: No comments → Phase 1. Investigation exists + ready-to-build → Phase 3. Builder + no PR → Phase 4. Builder + PR open → Phase 5. PR merged + issue open → Phase 6.
247
+ **Determine resume point**: No comments → Phase 1. Investigation exists + ready-to-build → Phase 3. Builder:COMPLETE + no PR → Phase 4. Builder without :COMPLETE (partial/interrupted build) + no PR → Phase 3 (partial-build cleanup). Builder + PR open → Phase 5. PR merged + issue open → Phase 6.
197
248
 
198
249
  ### 0B.5: Read Phase Checkpoint (MANDATORY — executes before any phase-skip decision)
199
250
 
@@ -225,6 +276,35 @@ fi
225
276
 
226
277
  **Classify lane**: Milestone → feature lane (`milestone/{slug}`). No milestone → fast lane (`staging`).
227
278
 
279
+ **Batch issue detection**: <!-- Added: forge#1333 --> If the issue body contains `<!-- FORGE:BATCH_MEMBERS -->`, this is a P3 batch issue. Set `IS_BATCH=true` and extract the member issue list:
280
+
281
+ ```bash
282
+ IS_BATCH=0
283
+ BATCH_MEMBERS=()
284
+
285
+ BATCH_MEMBERS_BLOCK=$(gh issue view {NUMBER} {GH_FLAG} --json body --jq '.body' \
286
+ | sed -n '/<!-- FORGE:BATCH_MEMBERS -->/,/<!-- \/FORGE:BATCH_MEMBERS -->/p' 2>/dev/null || true)
287
+
288
+ if [ -n "$BATCH_MEMBERS_BLOCK" ]; then
289
+ IS_BATCH=1
290
+ # Extract member issue numbers (- [ ] #NNN: title lines)
291
+ BATCH_MEMBERS=($(echo "$BATCH_MEMBERS_BLOCK" | grep -oP '(?<=- \[ \] #)\d+' || true))
292
+ echo "Batch issue detected — member issues: ${BATCH_MEMBERS[*]}"
293
+ fi
294
+ ```
295
+
296
+ **Batch issue pipeline rules** (when `IS_BATCH=true`):
297
+ - Build phases execute exactly as normal (the batch issue body IS the spec for what to fix)
298
+ - After successful merge, auto-close all member issues with a cross-reference:
299
+ ```bash
300
+ for MEMBER in "${BATCH_MEMBERS[@]}"; do
301
+ gh issue close "$MEMBER" {GH_FLAG} \
302
+ --comment "Resolved as part of batch PR #{PR_NUMBER} (#{ISSUE_NUMBER}). See batch issue for details."
303
+ gh issue edit "$MEMBER" {GH_FLAG} --add-label "workflow:merged" 2>/dev/null || true
304
+ done
305
+ ```
306
+ - Member issues are closed in Phase 6 (after PR merge) — NOT before
307
+
228
308
  **Source branch for review-findings**: Parse `**Code branch**: \`{branch}\`` from body. Branch from there, not main.
229
309
 
230
310
  **Script resolution** — Use the following `resolve_script()` function whenever calling a pipeline script. It enforces the 4-level precedence hierarchy (see `devdocs/project/architecture.md → Script Precedence`):
@@ -673,6 +753,31 @@ case "$TIER" in
673
753
  esac
674
754
  ```
675
755
 
756
+ **Marker gate — Phase 1 exit** (see Marker Gate table in Universal Phase Dispatcher): <!-- forge#1419, forge#1418 -->
757
+ ```bash
758
+ INV_MARKER=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
759
+ --jq '[.[] | select(.body | contains("INVESTIGATION:COMPLETE"))] | length')
760
+ if [ "${INV_MARKER:-0}" -eq 0 ]; then
761
+ echo "MARKER GATE FAIL: INVESTIGATION:COMPLETE absent — re-invoking work-on/investigate once"
762
+ Skill(skill="work-on/investigate", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG}")
763
+ INV_MARKER=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
764
+ --jq '[.[] | select(.body | contains("INVESTIGATION:COMPLETE"))] | length')
765
+ if [ "${INV_MARKER:-0}" -eq 0 ]; then
766
+ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:GATE_FAILURE -->
767
+ ## Marker Gate Failure — Phase 1 (Investigation)
768
+
769
+ **Expected marker**: \`INVESTIGATION:COMPLETE\` inside a \`FORGE:INVESTIGATOR\` comment
770
+ **Status**: Absent after subcommand re-invocation. Human review required.
771
+
772
+ The router re-invoked \`work-on/investigate\` once but the marker was still not posted.
773
+ Inspect the subcommand output above for errors. <!-- forge#1418 -->"
774
+ gh issue edit {NUMBER} {GH_FLAG} --add-label "needs-human" \
775
+ --remove-label "workflow:investigating" 2>/dev/null || true
776
+ exit 1
777
+ fi
778
+ fi
779
+ ```
780
+
676
781
  Write machine-readable phase checkpoint (MUST execute immediately after label transition, before continuing):
677
782
  ```bash
678
783
  CHECKPOINT_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
@@ -835,6 +940,8 @@ esac
835
940
 
836
941
  <!-- FORGE:PHASE_COMPLETE — Entering Phase 3 (Build). See Universal Phase Dispatcher: sub-phases 3A–3M execute in sequence. No sub-phase completion is terminal. -->
837
942
 
943
+ **Canonical path**: Sub-phases 3A–3M run **inline** in the current context window for STANDARD and fast-lane issues. This is the single authoritative build topology. `work-on/build.md` and `work-on-monolithic.md` ([BENCHMARK]) describe the same inline model with different levels of detail; they are not separate competing paths. `Skill()` sub-agent spawns for build sub-phases are only permitted under the Spawn-Decision Table Row (c) exception (≥20 Skill invocations or ≥10 files changed before the build). <!-- Added: forge#1276 -->
944
+
838
945
  **Skip if**: `<!-- FORGE:BUILDER:COMPLETE -->` is present in a BUILDER comment. <!-- Added: forge#1305 — require completion marker, not mere presence of BUILDER annotation -->
839
946
 
840
947
  **Partial build detection**: If `<!-- FORGE:BUILDER -->` exists BUT `<!-- FORGE:BUILDER:COMPLETE -->` is ABSENT → the build was interrupted after implement.md Phase I6 (comment posted) but before validate.md Phase V5 (commit). Delete the partial comment and restart Phase 3 from the top: <!-- Added: forge#1305 -->
@@ -1508,6 +1615,7 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:BUILDER -->
1508
1615
  **Commits**: {COMMIT_SHA(S)}
1509
1616
  **Files changed**: {COUNT}
1510
1617
  **Verification Status**: ${VERIFICATION_STATUS}
1618
+ **Cost (build phase)**: ${PHASE_COST_USD:-unavailable} (best-effort — session telemetry; omit if unavailable)
1511
1619
 
1512
1620
  ### Approach
1513
1621
  {what was built, key decisions}
@@ -1536,6 +1644,31 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:CHECKPOINT -->
1536
1644
  \`\`\`"
1537
1645
  ```
1538
1646
 
1647
+ **Marker gate — Phase 3 exit** (see Marker Gate table in Universal Phase Dispatcher): <!-- forge#1419, forge#1418 -->
1648
+ ```bash
1649
+ BUILD_MARKER=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
1650
+ --jq '[.[] | select(.body | contains("FORGE:BUILDER:COMPLETE"))] | length')
1651
+ if [ "${BUILD_MARKER:-0}" -eq 0 ]; then
1652
+ echo "MARKER GATE FAIL: FORGE:BUILDER:COMPLETE absent — re-invoking work-on/build once"
1653
+ Skill(skill="work-on/build", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --worktree {WORKTREE_PATH} --branch {BRANCH} --base {PR_BASE}")
1654
+ BUILD_MARKER=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
1655
+ --jq '[.[] | select(.body | contains("FORGE:BUILDER:COMPLETE"))] | length')
1656
+ if [ "${BUILD_MARKER:-0}" -eq 0 ]; then
1657
+ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:GATE_FAILURE -->
1658
+ ## Marker Gate Failure — Phase 3 (Build)
1659
+
1660
+ **Expected marker**: \`FORGE:BUILDER:COMPLETE\` inside a \`FORGE:BUILDER\` comment
1661
+ **Status**: Absent after subcommand re-invocation. Human review required.
1662
+
1663
+ The router re-invoked \`work-on/build\` once but the marker was still not posted.
1664
+ Inspect the subcommand output above for errors. <!-- forge#1418 -->"
1665
+ gh issue edit {NUMBER} {GH_FLAG} --add-label "needs-human" \
1666
+ --remove-label "workflow:building" 2>/dev/null || true
1667
+ exit 1
1668
+ fi
1669
+ fi
1670
+ ```
1671
+
1539
1672
  ---
1540
1673
 
1541
1674
  ## Phase 4: PR Creation
@@ -1673,7 +1806,7 @@ PR #${PR_NUMBER} created targeting \`{PR_BASE}\`. Invoking /review-pr with --aut
1673
1806
 
1674
1807
  **Context budget check** (run before invoking review-pr): <!-- Added: forge#93 -->
1675
1808
 
1676
- Large-context sessions that accumulated significant build history cause review-pr to hit the token limit mid-review. Check the accumulated context before delegating:
1809
+ Large-context sessions that accumulated significant build history cause review-pr to hit the token limit mid-review. This check is an instance of **Spawn-Decision Policy Row (c)** (parent context near overflow) — see the [Spawn-Decision Table](#spawn-decision-table) for the general policy. Check the accumulated context before delegating:
1677
1810
 
1678
1811
  - If the build changed **≥10 files** OR this agent has made **≥20 Skill invocations** since it started: invoke `work-on/review` as a fresh sub-agent (via `Skill(skill="work-on/review", args="...")`) rather than calling review-pr directly. The sub-agent starts with a clean context window.
1679
1812
  - Otherwise (small build, few skill calls): invoke review-pr directly as below.
@@ -1685,10 +1818,40 @@ Skill(skill="review-pr", args="{PR_NUMBER} --auto-merge --issue {NUMBER} --base
1685
1818
  ```
1686
1819
 
1687
1820
  **Sub-agent invocation** (large builds — ≥10 changed files OR ≥20 Skill invocations):
1821
+
1822
+ Before spawning, build a distilled hot-copy of the key annotations the review sub-agent would otherwise re-fetch from GitHub. This reduces gh round-trips in the child without replacing the durable FORGE annotation record. <!-- Added: forge#1277 -->
1823
+
1824
+ ```bash
1825
+ # Hot-copy: extract CONTRACT and ARCHITECT annotation bodies for inline injection
1826
+ HOT_CONTRACT=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
1827
+ --jq '[.[] | select(.body | contains("<!-- FORGE:CONTRACT -->"))] | last | .body // ""' 2>/dev/null \
1828
+ | head -60) # Scope: first 60 lines — captures Proposed Approach + Deliverables table
1829
+
1830
+ HOT_ARCHITECT=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
1831
+ --jq '[.[] | select(.body | contains("<!-- FORGE:ARCHITECT -->"))] | last | .body // ""' 2>/dev/null \
1832
+ | head -40) # Scope: first 40 lines — captures Affected Paths + Implementation Order
1833
+
1834
+ # Build inline context block (omit sections where annotation was not found)
1835
+ HOT_COPY_BLOCK=""
1836
+ if [ -n "$HOT_CONTRACT" ]; then
1837
+ HOT_COPY_BLOCK="${HOT_COPY_BLOCK}
1838
+ **HOT COPY — FORGE:CONTRACT** (do not re-fetch; durable record is on the issue):
1839
+ ${HOT_CONTRACT}"
1840
+ fi
1841
+ if [ -n "$HOT_ARCHITECT" ]; then
1842
+ HOT_COPY_BLOCK="${HOT_COPY_BLOCK}
1843
+
1844
+ **HOT COPY — FORGE:ARCHITECT** (do not re-fetch; durable record is on the issue):
1845
+ ${HOT_ARCHITECT}"
1846
+ fi
1688
1847
  ```
1689
- Skill(skill="work-on/review", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --worktree {WORKTREE_PATH} --branch {BRANCH} --base {PR_BASE}")
1848
+
1849
+ ```
1850
+ Skill(skill="work-on/review", args="{NUMBER} --repo {GH_REPO} --gh-flag {GH_FLAG} --worktree {WORKTREE_PATH} --branch {BRANCH} --base {PR_BASE}", context="{HOT_COPY_BLOCK}")
1690
1851
  ```
1691
1852
 
1853
+ The `{HOT_COPY_BLOCK}` is an optimization that avoids the child re-discovering context already held by the parent. The FORGE annotations on GitHub remain the durable, compaction-safe record. If the hot-copy block is empty (annotations not yet posted), the sub-agent falls back to reading them from GitHub as before.
1854
+
1692
1855
  Review-pr handles: full domain-agent review → post findings as separate issues → merge PR. It does NOT close the issue or clean up the worktree — those run in Phase 6.
1693
1856
 
1694
1857
  ### 5D: Verify merge and close (recovery)
@@ -1989,6 +2152,40 @@ AGENTS_RUN=$(echo "$REVIEW_SUMMARY" | grep -oE '[0-9]+ agents' | grep -oE '[0-9]
1989
2152
  AGENTS_RUN="${AGENTS_RUN:-0}"
1990
2153
  ```
1991
2154
 
2155
+ **Capture best-effort cost signal** from session telemetry before posting GDR. This is best-effort — if the signal is unavailable, the cost block is omitted rather than blocking the pipeline or fabricating a number. Field names align with `bin/runner.mjs` usage accounting from #1295 so downstream tooling shares one schema:
2156
+ ```bash
2157
+ # Best-effort: read per-stage usage from FORGE:BUILDER/FORGE:CONTEXT/FORGE:ARCHITECT phase annotations
2158
+ # Source: session telemetry when available (e.g. OTEL_LOG_TOOL_DETAILS, Claude Code usage reporting).
2159
+ # If unavailable, set COST_BLOCK to null — the field is omitted from the GDR rather than fabricated.
2160
+ COST_INVESTIGATION=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
2161
+ --jq '[.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body] | last // ""' 2>/dev/null \
2162
+ | grep -oP '(?<=cost_usd: )\S+' | head -1 || echo "")
2163
+ COST_BUILD=$(gh api repos/{GH_REPO}/issues/{NUMBER}/comments \
2164
+ --jq '[.[] | select(.body | contains("FORGE:BUILDER")) | .body] | last // ""' 2>/dev/null \
2165
+ | grep -oP '(?<=cost_usd: )\S+' | head -1 || echo "")
2166
+ COST_REVIEW=$(gh api repos/{GH_REPO}/issues/{PR_NUMBER}/comments \
2167
+ --jq '[.[] | select(.body | contains("FORGE:REVIEWER")) | .body] | last // ""' 2>/dev/null \
2168
+ | grep -oP '(?<=cost_usd: )\S+' | head -1 || echo "")
2169
+
2170
+ # Build cost block JSON only if at least one stage value is present; otherwise null
2171
+ if [ -n "$COST_INVESTIGATION" ] || [ -n "$COST_BUILD" ] || [ -n "$COST_REVIEW" ]; then
2172
+ COST_INV_JSON="${COST_INVESTIGATION:-null}"
2173
+ COST_BUILD_JSON="${COST_BUILD:-null}"
2174
+ COST_REVIEW_JSON="${COST_REVIEW:-null}"
2175
+ COST_BLOCK="\"cost\": {
2176
+ \"stages\": {
2177
+ \"investigation\": $COST_INV_JSON,
2178
+ \"build\": $COST_BUILD_JSON,
2179
+ \"review\": $COST_REVIEW_JSON
2180
+ },
2181
+ \"total_usd\": null,
2182
+ \"source\": \"session-telemetry\"
2183
+ },"
2184
+ else
2185
+ COST_BLOCK=""
2186
+ fi
2187
+ ```
2188
+
1992
2189
  **Post GDR to PR** (not to issue — PR comment survives as permanent artifact on the merged diff):
1993
2190
  ```bash
1994
2191
  if [ "$GDR_EXISTS" != "true" ] && [ -n "{PR_NUMBER}" ]; then
@@ -2015,6 +2212,7 @@ if [ "$GDR_EXISTS" != "true" ] && [ -n "{PR_NUMBER}" ]; then
2015
2212
  \"confidence\": \"{CONFIDENCE}\",
2016
2213
  \"task_type\": \"{TASK_TYPE}\"
2017
2214
  },
2215
+ ${COST_BLOCK}
2018
2216
  \"context\": {
2019
2217
  \"historical_edges_referenced\": ${REVIEW_FINDING_COUNT},
2020
2218
  \"forge_annotations_read\": [\"FORGE:INVESTIGATOR\", \"FORGE:CONTRACT\", \"FORGE:CONTEXT\", \"FORGE:ARCHITECT\", \"FORGE:BUILDER\"]
package/docs/BRAND.md CHANGED
@@ -6,8 +6,8 @@ Status of reserved and blocked brand handles across platforms.
6
6
 
7
7
  | Domain | Status |
8
8
  |--------|--------|
9
- | `forgedock.dev` | **Unverified** — live content (2026-07-04) is a third-party product unrelated to ForgeDock; registrar verification pending. Do not use as a public-facing link until resolved. |
10
- | `forgedock.io` | **Parked** — Porkbun parked page, HTTP-only (HTTPS does not connect). Not controlled by RapierCraft Studios. Do not use as a public-facing link. |
9
+ | `forgedock.dev` | **Not owned** — owner-confirmed 2026-07-05 as NOT controlled by RapierCraft Studios; live content is an unrelated third-party product. Retired from ForgeDock branding — do not use anywhere. |
10
+ | `forgedock.io` | **Owned** — owner-confirmed 2026-07-05 as registered to RapierCraft Studios. Canonical ForgeDock domain. Currently a Porkbun parked page; a site/holding page is pending deploy — do not link publicly until the site is live. |
11
11
 
12
12
  > **Rule**: No public ForgeDock surface (npm homepage, repo description, plugin manifests, docs) may point at a domain until its live content is verified as controlled by RapierCraft Studios.
13
13
 
@@ -28,9 +28,16 @@ No action needed. The package name was claimed on first publish.
28
28
  The bare `forgedock` org slug cannot be used for the ForgeDock GitHub App name — GitHub
29
29
  slugifies App display names and rejects collisions with existing user/org accounts.
30
30
 
31
- **Recommended App slug**: `forgedock-ai` (or `forgedock-app`). The App ID in use during
32
- development is **3978349** (registered under RapierCraftStudios with `public: false`).
33
- Update the display name and slug when the L2 central public App launches.
31
+ **Canonical public App**: **App ID 4051319** (Client ID `Iv23ligZAftI2QDt5CUa`), owner-confirmed
32
+ 2026-07-05. Currently owned by the personal `@RapierCraft` account — **to be transferred to the
33
+ `RapierCraftStudios` org** (a public/commercial App should not live on a personal account). Its
34
+ public listing still needs a real description and a homepage that resolves publicly.
35
+
36
+ Superseded / legacy Apps — do **not** present as the public identity:
37
+ - **3978349** — earlier dev App (registered under RapierCraftStudios, `public: false`); superseded by 4051319.
38
+ - **3731547** (`rapiercraft-forge`) — placeholder description "test"; authored the early public merged PRs but is legacy, its listing being wound down.
39
+
40
+ Recommended slug when finalizing the org-owned App: `forgedock-ai` (the bare `forgedock` slug is blocked, per above).
34
41
 
35
42
  ## Social Handles
36
43
 
@@ -48,8 +55,8 @@ Social handle registration is an operational task. Reserve handles before public
48
55
 
49
56
  | Platform | Action |
50
57
  |----------|--------|
51
- | Domain (forgedock.dev) | Unverified — registrar check pending; do not use as live surface |
52
- | Domain (forgedock.io) | Parked — not controlled by RapierCraft Studios; do not use as live surface |
58
+ | Domain (forgedock.dev) | Not owned (owner-confirmed 2026-07-05) — retired from branding |
59
+ | Domain (forgedock.io) | Owned — canonical; site deploy pending before public linking |
53
60
  | npm | Done |
54
61
  | GitHub org slug | Blocked — use variant for App slug |
55
62
  | Social handles | Reserve before L1 public launch |
package/docs/CI.md CHANGED
@@ -20,7 +20,7 @@ The `forgedock-review.yml` workflow template triggers on every pull request (ope
20
20
  ## Prerequisites
21
21
 
22
22
  1. **Anthropic API key** — Claude Code runs against the Anthropic API. Get one at [console.anthropic.com](https://console.anthropic.com).
23
- 2. **ForgeDock installed** — The workflow installs ForgeDock automatically via `npx forgedock install`.
23
+ 2. **ForgeDock installed** — The workflow installs ForgeDock automatically via `npx forgedock install --global` (CI uses global install so commands are available system-wide in the runner).
24
24
  3. **GitHub Actions enabled** — Standard for all public repos; enabled by default for private repos.
25
25
 
26
26
  ---
@@ -37,6 +37,20 @@ In your repository: **Settings → Secrets and variables → Actions → New rep
37
37
 
38
38
  Never commit the API key to your repository. GitHub Actions masks secrets in logs, but only secrets stored via Settings are protected.
39
39
 
40
+ ### 1a. Set the deploy-gate repository variable
41
+
42
+ If you use the `gate-marker-check` workflow (which enforces that every staging→main PR was reviewed by `/review-pr-staging` before merge), you must also set a **repository variable** that tells the gate which GitHub logins are authorized to post gate markers.
43
+
44
+ In your repository: **Settings → Secrets and variables → Actions → Variables → New repository variable**
45
+
46
+ | Name | Value |
47
+ |------|-------|
48
+ | `FORGE_TRUSTED_MARKER_AUTHORS` | Comma-separated list of GitHub logins authorized to run `/review-pr-staging` (e.g. `your-bot-login,your-personal-login`) |
49
+
50
+ **Why this is required**: The gate-marker-check workflow verifies that gate markers (`FORGE:GATE_PASS` / `FORGE:GATE_FAILURE`) were posted by a trusted author — not hand-typed by an external contributor. If this variable is unset or empty, the gate rejects every marker and blocks all staging→main PRs. The gate will fail immediately with setup instructions rather than waiting 30 minutes and producing a cryptic timeout error.
51
+
52
+ **What logins to include**: Add the GitHub login of the bot or user account that runs Claude Code sessions (the account that posts `/review-pr-staging` output). For automated CI setups this is typically the bot account; for manual runs it is your personal GitHub login.
53
+
40
54
  ### 2. Copy the workflow template
41
55
 
42
56
  Copy `templates/workflows/forgedock-review.yml` from your ForgeDock installation to your repository:
@@ -47,7 +61,7 @@ mkdir -p .github/workflows
47
61
  cp "$(npx forgedock which-dir)/templates/workflows/forgedock-review.yml" .github/workflows/forgedock-review.yml
48
62
  ```
49
63
 
50
- Or copy it manually — the file is in `~/.claude/commands/../templates/workflows/forgedock-review.yml` after running `npx forgedock install`.
64
+ Or copy it manually — the file is in `~/.claude/commands/../templates/workflows/forgedock-review.yml` after running `npx forgedock install --global`.
51
65
 
52
66
  ### 3. Commit and push
53
67