forgedock 1.0.22 → 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 (184) hide show
  1. package/README.md +255 -211
  2. package/bin/batch-runner.mjs +339 -0
  3. package/bin/cinema.mjs +320 -0
  4. package/bin/demo.mjs +92 -7
  5. package/bin/engine/phases.mjs +168 -0
  6. package/bin/engine/projector.mjs +32 -0
  7. package/bin/engine/reconcile.mjs +11 -0
  8. package/bin/engine/runlog.mjs +79 -0
  9. package/bin/engine/state.mjs +32 -0
  10. package/bin/engine-cli.mjs +222 -0
  11. package/bin/engine.mjs +138 -0
  12. package/bin/forgedock.mjs +896 -1540
  13. package/bin/hooks/interactive-engine.mjs +509 -0
  14. package/bin/hooks/pre-tool-use.mjs +498 -0
  15. package/bin/hooks/subagent-stop-enforce.mjs +197 -0
  16. package/bin/journey.mjs +841 -0
  17. package/bin/registry.mjs +139 -0
  18. package/bin/report.mjs +447 -0
  19. package/bin/runner.mjs +136 -20
  20. package/bin/settings-hook.mjs +346 -0
  21. package/bin/tui.mjs +6 -3
  22. package/commands/adopt.md +4 -1
  23. package/commands/analytics.md +4 -1
  24. package/commands/audit-agents.md +110 -27
  25. package/commands/audit.md +20 -1
  26. package/commands/autopilot.md +84 -12
  27. package/commands/changelog.md +2 -1
  28. package/commands/ci-audit.md +2 -1
  29. package/commands/cleanup.md +161 -1
  30. package/commands/compat-audit.md +2 -1
  31. package/commands/deploy-info.md +63 -4
  32. package/commands/design-bench.md +6 -1
  33. package/commands/design-render-critique-loop.md +2 -1
  34. package/commands/design.md +1 -0
  35. package/commands/diagnose.md +2 -1
  36. package/commands/explain.md +2 -1
  37. package/commands/forge-stats.md +122 -2
  38. package/commands/forgedock-init.md +1 -1
  39. package/commands/geo-audit.md +3 -0
  40. package/commands/incident-response.md +2 -1
  41. package/commands/issue.md +24 -3
  42. package/commands/milestone.md +77 -12
  43. package/commands/optimize.md +2 -1
  44. package/commands/orchestrate/config.md +67 -0
  45. package/commands/orchestrate/phase-1-resolve.md +159 -0
  46. package/commands/orchestrate/phase-2-triage.md +126 -0
  47. package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
  48. package/commands/orchestrate/phase-3-dependency.md +591 -0
  49. package/commands/orchestrate/phase-4-execution.md +962 -0
  50. package/commands/orchestrate/phase-5-cleanup.md +47 -0
  51. package/commands/orchestrate/phase-6-report.md +198 -0
  52. package/commands/orchestrate/safety.md +62 -0
  53. package/commands/orchestrate.md +25 -2027
  54. package/commands/pipeline-health/config.md +34 -0
  55. package/commands/pipeline-health/phase-1-context.md +180 -0
  56. package/commands/pipeline-health/phase-2-metrics.md +1729 -0
  57. package/commands/pipeline-health/phase-3-analyze.md +204 -0
  58. package/commands/pipeline-health/phase-4-proposals.md +117 -0
  59. package/commands/pipeline-health/phase-5-report.md +284 -0
  60. package/commands/pipeline-health/phase-6-summary.md +52 -0
  61. package/commands/pipeline-health.md +25 -2401
  62. package/commands/pipeline-resume.md +24 -1
  63. package/commands/pipeline-status.md +65 -0
  64. package/commands/qa-sweep.md +4 -1
  65. package/commands/quality-gate.md +326 -42
  66. package/commands/replay.md +2 -1
  67. package/commands/review-pr-agents/api.md +135 -0
  68. package/commands/review-pr-agents/auth.md +137 -0
  69. package/commands/review-pr-agents/billing.md +101 -0
  70. package/commands/review-pr-agents/concurrency.md +145 -0
  71. package/commands/review-pr-agents/database.md +103 -0
  72. package/commands/review-pr-agents/frontend.md +89 -0
  73. package/commands/review-pr-agents/infra.md +385 -0
  74. package/commands/review-pr-agents/protocols.md +185 -0
  75. package/commands/review-pr-agents/scraper.md +185 -0
  76. package/commands/review-pr-agents/security.md +406 -0
  77. package/commands/review-pr-agents.md +45 -1722
  78. package/commands/review-pr-staging.md +196 -40
  79. package/commands/review-pr.md +612 -56
  80. package/commands/rollback.md +2 -1
  81. package/commands/scope.md +2 -1
  82. package/commands/security-audit.md +2 -1
  83. package/commands/signal-planner.md +623 -0
  84. package/commands/sync-ecosystem.md +1 -0
  85. package/commands/test-gate.md +17 -1
  86. package/commands/validate.md +2 -1
  87. package/commands/work-on/build/architect.md +28 -0
  88. package/commands/work-on/build/context.md +2 -0
  89. package/commands/work-on/build/implement.md +19 -5
  90. package/commands/work-on/build/validate.md +62 -6
  91. package/commands/work-on/build.md +187 -30
  92. package/commands/work-on/close.md +132 -5
  93. package/commands/work-on/decompose.md +19 -1
  94. package/commands/work-on/investigate.md +117 -2
  95. package/commands/work-on/review.md +48 -4
  96. package/commands/work-on-monolithic.md +8 -2
  97. package/commands/work-on.md +247 -7
  98. package/docs/BRAND.md +16 -5
  99. package/docs/CI.md +2 -2
  100. package/docs/CODEX.md +36 -1
  101. package/docs/CONFIG.md +44 -42
  102. package/docs/FORGE-PROTOCOL.md +15 -1064
  103. package/docs/anthropic-devrel-outreach.md +2 -2
  104. package/docs/articles/command-decomposition-token-savings.md +214 -0
  105. package/docs/articles/model-release-playbook.md +131 -0
  106. package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
  107. package/docs/claude-breakpoints.json +75 -5
  108. package/docs/design/abc-benchmark.md +1 -1
  109. package/docs/design/design-spec-schema.md +1 -1
  110. package/docs/design/divergent-generation.md +1 -1
  111. package/docs/design/eval-gate-runbook.md +178 -0
  112. package/docs/design/show-hn-draft.md +26 -1
  113. package/docs/design/token-cost-baseline-1298.md +59 -0
  114. package/docs/eval/README.md +117 -0
  115. package/docs/eval/corpus/seed-v1.json +6 -0
  116. package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
  117. package/docs/site/annotations-explained.md +24 -0
  118. package/docs/site/command-learning-path.md +51 -14
  119. package/docs/site/command-reference.md +339 -113
  120. package/docs/site/for-companies.md +95 -0
  121. package/docs/site/forge-annotation-protocol.md +12 -256
  122. package/docs/site/getting-started.md +58 -12
  123. package/docs/site/github-is-the-memory.md +113 -0
  124. package/docs/site/how-it-works.md +3 -13
  125. package/docs/site/index.md +10 -2
  126. package/docs/spec/eval-run-result.md +147 -0
  127. package/docs/spec/forge-protocol-v1.md +441 -18
  128. package/docs/spec/label-state-machine.md +55 -0
  129. package/docs/spec/review-protocol.md +158 -0
  130. package/docs/spec-graph-schema.md +28 -0
  131. package/docs/superpowers/plans/2026-07-03-cinematic-onboarding-tui.md +2339 -0
  132. package/docs/superpowers/plans/2026-07-03-durable-execution-engine.md +1223 -0
  133. package/docs/superpowers/specs/2026-07-03-cinematic-onboarding-tui-design.md +157 -0
  134. package/docs/superpowers/specs/2026-07-03-durable-execution-engine-design.md +194 -0
  135. package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
  136. package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
  137. package/examples/forgedock-demo/README.md +41 -22
  138. package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
  139. package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
  140. package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
  141. package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
  142. package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
  143. package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
  144. package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
  145. package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
  146. package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
  147. package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
  148. package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
  149. package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
  150. package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
  151. package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
  152. package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
  153. package/examples/forgedock-demo/scripts/smoke.js +18 -1
  154. package/examples/forgedock-demo/src/db.js +36 -11
  155. package/examples/forgedock-demo/src/routes/notes.js +106 -9
  156. package/examples/forgedock-demo/src/server.js +4 -1
  157. package/package.json +12 -4
  158. package/packages/protocol/LICENSE +21 -0
  159. package/packages/protocol/src/cli.js +135 -0
  160. package/packages/protocol/src/emit.js +146 -0
  161. package/packages/protocol/src/index.js +43 -0
  162. package/packages/protocol/src/parse.js +229 -0
  163. package/packages/protocol/src/types.js +171 -0
  164. package/packages/protocol/src/validate.js +122 -0
  165. package/scripts/bench-topology-cost.mjs +372 -0
  166. package/scripts/check-command-docs-drift.sh +198 -0
  167. package/scripts/check-protocol-restatements.sh +176 -0
  168. package/scripts/check-registry/README.md +72 -0
  169. package/scripts/check-registry/manifest.json +6 -0
  170. package/scripts/code-index.sh +454 -0
  171. package/scripts/conformance-check.mjs +168 -0
  172. package/scripts/doctor-pipeline-state.sh +484 -0
  173. package/scripts/eval-gate-baseline.json +17 -0
  174. package/scripts/eval-gate-scorecard.mjs +242 -0
  175. package/scripts/eval-scorecard-aggregator.mjs +252 -0
  176. package/scripts/flaky-quarantine.sh +241 -0
  177. package/scripts/forge-annotation.sh +567 -0
  178. package/scripts/issue-dedup.sh +236 -0
  179. package/scripts/validate-annotation-node.mjs +233 -0
  180. package/scripts/verify-env-vars.sh +18 -2
  181. package/scripts/verify-host-headers.sh +4 -4
  182. package/scripts/verify-route-registration.sh +2 -2
  183. package/scripts/worktree-lifecycle.sh +202 -0
  184. package/templates/devdocs/agent/using-forgedock.md +14 -0
@@ -0,0 +1,67 @@
1
+ ---
2
+ install: internal
3
+ ---
4
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
+
7
+ # /orchestrate — Configuration, Hard Rules & Multi-Repo Support
8
+
9
+ Read this file at the start of every `/orchestrate` invocation.
10
+
11
+ ## HARD RULES — READ BEFORE ANYTHING ELSE
12
+
13
+ 1. **Every agent MUST invoke `/work-on` via the Skill tool.** You do NOT write implementation prompts. You copy the Phase 4A template verbatim and fill in the `{VARIABLES}`. Nothing else. No custom prompts. No "just read and edit" shortcuts. The Skill tool invocation is what triggers labels, investigation comments, structured review, and trajectory tracking. Without it, the agent's work has no paper trail and is worthless.
14
+
15
+ 2. **You are a dispatcher, not a builder.** You resolve issues, build the dependency DAG, spawn agents, and report results. You NEVER read code, edit files, or implement fixes yourself.
16
+
17
+ 3. **After each agent completes, verify it used `/work-on`.** Check that completed issues have `workflow:*` labels and structured comments. If an agent bypassed the pipeline, report it as a failure.
18
+
19
+ ---
20
+
21
+ You are the top-level orchestrator. Your job is to take a batch of issues, plan the execution order, spawn parallel sub-agents (each running the full `/work-on` pipeline), and report consolidated results.
22
+
23
+ **You have access to ALL tools** — Agent tool (critical), Task tool, Skill tool, Bash, everything. Use the Agent tool aggressively to parallelize work.
24
+
25
+ **Agent model policy**: `model: "haiku"`, `effort: low` (mechanical — dispatch bookkeeping, lane routing, classification). Fallback: `model: "sonnet"` if rate-limited. User can override with `--model <name>`. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
26
+ **NEVER use plan mode (EnterPlanMode).**
27
+
28
+ <!-- FORGE:SPEC_LOADED — orchestrate.md loaded and active. Agent is bound by HARD RULES above. -->
29
+
30
+ ---
31
+
32
+ ## Config Resolution
33
+
34
+ Read `forge.yaml` at the project root to resolve all project-specific variables before running any commands:
35
+
36
+ ```bash
37
+ # Parse forge.yaml for project context
38
+ CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
39
+ GH_REPO=$(yq '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
40
+ GH_FLAG="-R $GH_REPO"
41
+ REPO_PATH=$(yq '.paths.root' "$CONFIG_FILE")
42
+ PROJECT_NAME=$(yq '.project.name' "$CONFIG_FILE")
43
+ STAGING_BRANCH=$(yq '.branches.staging' "$CONFIG_FILE")
44
+ DEFAULT_BRANCH=$(yq '.branches.default' "$CONFIG_FILE")
45
+ # Build satellite repo map from repos.satellites list
46
+ # Each satellite: { prefix, repo, staging_branch }
47
+ ```
48
+
49
+ All `{GH_REPO}`, `{GH_FLAG}`, `{REPO_PATH}`, `{PROJECT_NAME}`, `{STAGING_BRANCH}`, and `{DEFAULT_BRANCH}` references below are populated from `forge.yaml`.
50
+
51
+ ---
52
+
53
+ ## Multi-Repo Support
54
+
55
+ This orchestrator supports issues across multiple repositories. See `/work-on` → "Multi-Repo Support" and `forge.yaml → repos` for the full project registry and context variables.
56
+
57
+ ### Cross-Repo Issue References
58
+
59
+ Issues can be prefixed with a project shorthand derived from `forge.yaml → repos.satellites`:
60
+ - `#123` or `123` → default repo (`{GH_REPO}`)
61
+ - `{satellite_prefix}:5` → satellite repo (e.g., `mcp:5`, `n8n:12`) — prefixes and repos come from `forge.yaml → repos.satellites`
62
+ - `all-repos` → Scan all configured repos for open issues (combine and prioritize)
63
+
64
+ When spawning sub-agents, pass the project prefix so `/work-on` resolves to the correct repo.
65
+
66
+ ---
67
+
@@ -0,0 +1,159 @@
1
+ ---
2
+ install: internal
3
+ ---
4
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
+
7
+ # /orchestrate — Phase 1: Resolve the Issue Set
8
+
9
+ ## Phase 1: Resolve the Issue Set
10
+
11
+ Parse `$ARGUMENTS` to determine which issues to work on:
12
+
13
+ ### Input Patterns
14
+
15
+ | Input | Resolution |
16
+ |-------|------------|
17
+ | `milestone <slug>` | All open issues assigned to that GitHub milestone (default repo) |
18
+ | `#1 #2 #3` or `1 2 3` | Specific issue numbers, optionally repo-prefixed (e.g., `#123 mcp:5 n8n:12`) |
19
+ | `next <N>` | Top N priority open issues (priority:P0 first, then priority:P1, etc.) |
20
+ | `next <N> all-repos` | Top N across ALL ecosystem repos |
21
+ | `fast-lane` or `fast` | All open fast-lane issues (no milestone, bugs/fixes) |
22
+ | `priority:P0` or `priority:P1` | All open issues with that priority label |
23
+ | `mcp:fast` or `n8n:next 3` | Repo-scoped queries |
24
+ | `<slug>` (no keyword) | Try milestone first, then fall back to label search |
25
+
26
+ ### Fetch the issues
27
+
28
+ For each resolved repo, use the appropriate `-R` flag:
29
+
30
+ ```bash
31
+ # Default repo (no flag needed if using GH_FLAG="" for the default):
32
+ gh issue list {GH_FLAG} --milestone "{TITLE}" --state open --limit 500 --json number,title,labels,milestone --jq '.[] | {number, title, labels: [.labels[].name], milestone: .milestone.title}'
33
+
34
+ # Satellite repos — always include -R flag with the satellite repo from forge.yaml:
35
+ # For each satellite in forge.yaml → repos.satellites:
36
+ gh issue list -R {SATELLITE_REPO} --milestone "{TITLE}" --state open --limit 500 --json number,title,labels,milestone
37
+
38
+ # For specific numbers with repo prefix:
39
+ gh issue view {NUMBER} -R {SATELLITE_REPO} --json number,title,labels,state,milestone,body
40
+
41
+ # For "all-repos" — fetch from all configured repos and combine:
42
+ gh issue list {GH_FLAG} --state open --limit {N} --json number,title,labels,milestone
43
+ # For each satellite in forge.yaml → repos.satellites:
44
+ gh issue list -R {SATELLITE_REPO} --state open --limit 500 --json number,title,labels,milestone
45
+ # Combine, sort by priority, take top N
46
+ ```
47
+
48
+ **Count validation**: After fetching issues, log the count returned. If a milestone query returns exactly 30 issues, warn the user: "WARNING: Exactly 30 issues returned — gh CLI default may have truncated results. Re-running with --limit 500 is recommended." (The --limit 500 above prevents this for standard runs, but verify if the count seems suspiciously low relative to milestone expectations.)
49
+
50
+ **Tag each issue with its project prefix** in your internal tracking so sub-agents receive the correct repo context.
51
+
52
+ ### Filter out ineligible issues
53
+
54
+ Remove issues that should NOT be worked on:
55
+ - Already closed or has `workflow:merged` label
56
+ - Has `workflow:invalid` label
57
+ - Has `needs-human` label (requires manual action)
58
+ - Has `workflow:decomposed` label (parent tracker — its sub-issues should be picked up instead)
59
+ - Has `workflow:building` or `workflow:in-review` label (already in progress)
60
+ - Is an epic (`epic` label) — these are planning containers, not buildable
61
+
62
+ If a `workflow:decomposed` issue is found, automatically expand it to its open sub-issues instead.
63
+
64
+ ### P3 Review-Finding Batching (deterministic grouping rule)
65
+
66
+ <!-- Added: forge#1333 -->
67
+
68
+ Before finalizing the issue set, apply the P3 batching rule to reduce full-pipeline overhead on low-severity review findings.
69
+
70
+ **Trigger conditions** (BOTH must be true to batch):
71
+ 1. The issue has labels `review-finding` + `priority:P3`
72
+ 2. The issue has `<!-- FORGE:BATCHABLE -->` in its body
73
+
74
+ **Safety exclusions — NEVER batch** (override all trigger conditions):
75
+ - Issue body contains the word "security" or "billing" anywhere in the title or `## Problem` section
76
+ - Issue has a `security` label
77
+ - Issue has a `billing` label
78
+
79
+ **Grouping algorithm:**
80
+ ```bash
81
+ # Fetch all open batchable P3 issues
82
+ BATCHABLE_P3=$(gh issue list {GH_FLAG} \
83
+ --state open \
84
+ --label "review-finding,priority:P3" \
85
+ --limit 500 \
86
+ --json number,title,body,labels \
87
+ --jq '.[] | select(.body | test("<!-- FORGE:BATCHABLE -->"))
88
+ | select((.title | test("security|billing"; "i")) | not)
89
+ | select(.body | test("## Problem[\\s\\S]{0,500}(security|billing)"; "i") | not)
90
+ | select(([.labels[].name] | any(. == "security" or . == "billing")) | not)')
91
+
92
+ # Group by domain (file-cluster derived from the affected file path in each issue body)
93
+ # Domain is the top-level directory of the first affected file listed under "## Affected Files"
94
+ # e.g., "services/api/auth/login.py" → domain "services/api/auth"
95
+ # "web/src/app/billing/" → EXCLUDED (billing path)
96
+ # "commands/review-pr.md" → domain "commands"
97
+ ```
98
+
99
+ **Batch creation rule**: When 5+ batchable P3 issues share the same domain, OR when the oldest batchable P3 in a domain exceeds 72 hours, create a single batch issue grouping those issues:
100
+
101
+ ```bash
102
+ BATCH_ISSUE_NUM=$(gh issue create {GH_FLAG} \
103
+ --title "fix(batch): P3 review findings — {DOMAIN} domain (batch #{BATCH_N})" \
104
+ --label "review-finding,priority:P3,batch" \
105
+ --body "$(cat <<'BATCH_EOF'
106
+ ## Problem
107
+
108
+ Batch of P3 review findings in the **{DOMAIN}** domain, grouped to reduce per-finding pipeline overhead.
109
+
110
+ ## Member Findings
111
+
112
+ <!-- FORGE:BATCH_MEMBERS -->
113
+ {for each member issue: "- [ ] #{NUM}: {TITLE}"}
114
+ <!-- /FORGE:BATCH_MEMBERS -->
115
+
116
+ ## Acceptance Criteria
117
+
118
+ - [ ] All member findings addressed or closed as false-positive
119
+ - [ ] Member issues auto-closed with reference to this batch PR on merge
120
+ - [ ] No security or billing paths touched (validated before batching)
121
+
122
+ ## Context
123
+
124
+ **Batch policy**: 5+ open P3 findings in the same domain, or oldest > 72h.
125
+ **Member issues**: #{N1}, #{N2}, #{N3}, ...
126
+
127
+ <!-- FORGE:BATCHABLE -->
128
+ BATCH_EOF
129
+ )")
130
+ ```
131
+
132
+ **Replace member issues with the batch issue** in the resolved issue set. Member issues are NOT individually dispatched to `/work-on` — the batch issue is the single pipeline unit.
133
+
134
+ **Important limits**:
135
+ - Max 10 members per batch issue — if more than 10 batchable P3s exist in a domain, create multiple batch issues of ≤ 10 each
136
+ - P1 and P2 issues are NEVER batched — they keep the standard one-issue-one-PR path
137
+ - Batch issues themselves are never nested inside other batch issues
138
+
139
+ If fewer than 5 batchable P3 findings exist in any domain AND none exceed 72h, skip batch creation entirely — individual P3s run through the standard pipeline.
140
+
141
+ ### CRITICAL: No duplicate detection at orchestrator level
142
+
143
+ **The orchestrator NEVER closes, merges, or deduplicates issues.** Even if two issues look like duplicates (similar titles, same error message, same symptoms), they may target different code paths, different ORM objects, or different failure modes. Only a `/work-on` investigation agent — after reading the actual code — can determine whether an issue is truly a duplicate.
144
+
145
+ **What the orchestrator must NOT do:**
146
+ - Close an issue as "duplicate" based on title/symptom similarity
147
+ - Skip an issue because another issue "covers it"
148
+ - Merge two issues into one agent
149
+ - Make ANY judgment about issue validity
150
+
151
+ **What the orchestrator SHOULD do:**
152
+ - If two issues look related, add a note in the agent prompt: "Note: #{OTHER} has similar symptoms — investigate whether this is the same root cause or a different code path"
153
+ - Let both agents run independently — if one finds it's truly a duplicate, `/work-on`'s investigation phase will close it as invalid with evidence
154
+ - Flag potential overlap in the DAG plan for the user's awareness, but NEVER act on it
155
+
156
+ **Why**: Surface-level similarity hides critical differences. #3842 (api_key.id lazy load) and #4039 (user.id lazy load) had identical error messages but targeted completely different ORM objects. Closing #4039 as a "duplicate" would have left a customer-impacting P0 bug unfixed.
157
+
158
+ ---
159
+
@@ -0,0 +1,126 @@
1
+ ---
2
+ install: internal
3
+ ---
4
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
+
7
+ # /orchestrate — Phase 2: Investigation-First Triage
8
+
9
+ ## Phase 2: Investigation-First Triage
10
+
11
+ **Purpose**: Investigation issues produce NEW GitHub issues as their output. If the batch contains investigations, they must run FIRST so their output can be folded into the execution plan.
12
+
13
+ **If no investigations are found in Step 2A, skip this entire phase and proceed directly to Phase 3.**
14
+
15
+ ### Step 2A: Classify each issue
16
+
17
+ For each issue in the resolved set, read its title and body to classify it:
18
+
19
+ ```bash
20
+ for NUM in {issue_numbers}; do
21
+ gh issue view $NUM --json title,body,labels --jq '{title: .title, labels: [.labels[].name], body_preview: (.body[:500])}'
22
+ done
23
+ ```
24
+
25
+ **Classification rules:**
26
+
27
+ | Signal | Classification |
28
+ |--------|---------------|
29
+ | Title contains "Investigate", "Audit", "Research", "Evaluate", "Assess", "Deep dive" | **Investigation** |
30
+ | Issue body is primarily questions (`- [ ]` checklist) with no concrete code changes | **Investigation** |
31
+ | Issue body says "Deliverable: execution plan" or "create issues" | **Investigation** |
32
+ | Issue has `enhancement` label + title starts with "Enable" + body describes toggling a feature flag | **Implementation** |
33
+ | Issue has `bug`, `refactor`, `dead-code`, or `feature` label | **Implementation** |
34
+
35
+ Tag each issue internally as `INVESTIGATION` or `IMPLEMENTATION`.
36
+
37
+ ### Step 2B: Run investigations first (Wave 0)
38
+
39
+ If ANY issues are classified as `INVESTIGATION`:
40
+
41
+ 1. **Move them to Wave 0** — they run BEFORE all implementation issues
42
+ 2. **Spawn Wave 0 agents** using the same agent template as Phase 4A, but emphasize that `/work-on` will detect the investigation task type and produce issues (not code)
43
+ 3. **Wait for ALL Wave 0 agents to complete** before proceeding to Phase 3
44
+
45
+ ### Step 2C: Collect newly created issues
46
+
47
+ After Wave 0 completes, each investigation agent will have created new GitHub issues. Collect them:
48
+
49
+ ```bash
50
+ # For each investigation issue that completed successfully:
51
+ # Read the FORGE:BUILDER comment to find created issue numbers
52
+ for INV_NUM in {investigation_numbers}; do
53
+ gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
54
+ --jq '.[] | select(.body | contains("<!-- FORGE:BUILDER -->")) | .body' \
55
+ | grep -oP '#\K\d+' | sort -u
56
+ done
57
+
58
+ # Also check: if the investigation issue had a milestone, the new issues should too
59
+ # Verify milestone assignment:
60
+ for NEW_NUM in {newly_created_numbers}; do
61
+ gh issue view $NEW_NUM --json milestone --jq '.milestone.title // "NO MILESTONE"'
62
+ done
63
+ ```
64
+
65
+ ### Step 2C.5: Collect Knowledge Gist URLs from investigations
66
+
67
+ For each completed investigation issue, query its comments for `FORGE:KNOWLEDGE_GIST` annotations. Store the mapping of investigation issue number → Gist URL(s) so the agent template in Step 4A can include prior investigation context.
68
+
69
+ ```bash
70
+ # Build a map: investigation_number → gist_url(s)
71
+ declare -A INVESTIGATION_GISTS
72
+ for INV_NUM in {investigation_numbers}; do
73
+ GIST_URLS=$(gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
74
+ --jq '[.[] | select(.body | test("<!-- FORGE:KNOWLEDGE_GIST: https://")) | .body | capture("<!-- FORGE:KNOWLEDGE_GIST: (?<url>https://[^ ]+) -->").url] | unique | .[]')
75
+ if [ -n "$GIST_URLS" ]; then
76
+ INVESTIGATION_GISTS[$INV_NUM]="$GIST_URLS"
77
+ echo "Investigation #${INV_NUM}: found Gist URL(s)"
78
+ fi
79
+ done
80
+ ```
81
+
82
+ When spawning agents for implementation issues in Step 4A, include any Gist URLs from parent/sibling investigations in the agent prompt's context block. See the `{GIST_CONTEXT}` variable in the agent template.
83
+
84
+ **Milestone index Gist**: If the milestone has a `<!-- FORGE:MILESTONE_INDEX: {url} -->` annotation in its description, read the index URL and store it for inclusion in agent context. The milestone index aggregates all investigation Gist URLs for the milestone into a single reference.
85
+
86
+ ```bash
87
+ # Read milestone index URL from milestone description (if milestone exists)
88
+ MILESTONE_INDEX_URL=""
89
+ if [ -n "$MILESTONE_NUM" ]; then
90
+ MILESTONE_DESC=$(gh api repos/{GH_REPO}/milestones/${MILESTONE_NUM} --jq '.description // ""' 2>/dev/null)
91
+ MILESTONE_INDEX_URL=$(echo "$MILESTONE_DESC" | grep -oP '(?<=<!-- FORGE:MILESTONE_INDEX: )https://[^ ]+(?= -->)' | head -1)
92
+ if [ -n "$MILESTONE_INDEX_URL" ]; then
93
+ echo "Milestone index Gist found: ${MILESTONE_INDEX_URL}"
94
+ fi
95
+ fi
96
+ ```
97
+
98
+ ### Step 2D: Merge new issues into the batch
99
+
100
+ Add the newly created issues to the issue set. Re-check each one:
101
+ - Filter out any that are already ineligible (same rules as Phase 1)
102
+ - Tag them as `IMPLEMENTATION` (investigations don't spawn more investigations)
103
+ - They inherit the milestone from their parent investigation if applicable
104
+
105
+ **Issue body standard**: Any new issues created by investigation agents MUST use the **Pipeline Issue Template** from `issue.md` Phase 3D as their body structure. Investigation agents that produce issues as output should be prompted to use that template — not ad-hoc body formats — so every spawned issue enters the pipeline with the correct structure (Problem, Root Cause, Affected Files, Acceptance Criteria). Verify spawned issues have all mandatory sections before adding them to the batch; if sections are missing, the `/issue` body-validation step (Phase 4C.5) will repair them. <!-- Added: forge#293 -->
106
+
107
+ **Updated issue set** = original `IMPLEMENTATION` issues + newly spawned issues from investigations.
108
+
109
+ ### Step 2E: Report Wave 0 results to user
110
+
111
+ ```
112
+ ## Wave 0: Investigations Complete
113
+
114
+ | # | Investigation | Result | Issues Created |
115
+ |---|--------------|--------|---------------|
116
+ | #{INV1} | {title} | ✓ Closed | #{N1}, #{N2}, #{N3} |
117
+ | #{INV2} | {title} | ✓ Closed | #{N4}, #{N5} |
118
+
119
+ **New issues added to batch**: {count}
120
+ **Updated total**: {original_count} → {new_total} issues
121
+
122
+ Proceeding to dependency analysis with the expanded issue set...
123
+ ```
124
+
125
+ ---
126
+
@@ -0,0 +1,156 @@
1
+ ---
2
+ install: internal
3
+ ---
4
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
6
+
7
+ # /orchestrate — Phase 2.5: Investigation Synthesis
8
+
9
+ ## Phase 2.5: Investigation Synthesis
10
+
11
+ <!-- Added: forge#1192 -->
12
+
13
+ **Purpose**: Reconcile *competing recommendations* across investigation outputs BEFORE they fan out to implementation agents. Phase 3's conflict detection (Step 3C) deconflicts issues at the **file** layer only — it prevents git merge conflicts. It performs **zero semantic deconfliction**: two issues can touch entirely different files while proposing **contradictory approaches to the same problem**, and the file-overlap detector passes both straight to parallel dispatch. This phase closes that gap by clustering investigations semantically (by target subsystem, not by file) and arbitrating incompatible plans into a single decision — or serializing them so the second agent inherits the first's decision.
14
+
15
+ **This phase operates ONLY on FORGE annotations and issue bodies. It NEVER reads code, and it NEVER closes, skips, or merges issues.** Reconciling plans/annotations is distinct from adjudicating *duplicate validity* (Safety Rule 9, the #3842/#4039 scar): the anti-dedup rule forbids the orchestrator from deciding two issues are the same bug and closing one — that call belongs to `/work-on` investigation agents examining actual code. Plan reconciliation touches neither code nor issue state; it only writes a synthesis brief annotation and adds `Depends on #X` serialization edges. It therefore does not violate Hard Rule 2 (dispatcher, not builder) or Safety Rule 9.
16
+
17
+ **No-op guard**: This entire phase is skipped when the batch contains **0 or 1 investigations** — there is nothing to reconcile against. Proceed directly to Phase 3.
18
+
19
+ ### Step 2.5A: No-op guard
20
+
21
+ ```bash
22
+ # Count investigations that completed in Wave 0 (Phase 2), regardless of whether each
23
+ # emitted a Knowledge Gist. Use the full completed-investigation set (the same
24
+ # {investigation_numbers} that Steps 2C.5, 2.5B and 2.5C iterate) — NOT the
25
+ # INVESTIGATION_GISTS map, which only holds gist-producing investigations and would
26
+ # undercount when a genuine investigation reached a recommendation without a gist.
27
+ # If < 2, skip synthesis entirely.
28
+ INVESTIGATION_NUMS=( {investigation_numbers} )
29
+ INVESTIGATION_COUNT=${#INVESTIGATION_NUMS[@]}
30
+ if [ "$INVESTIGATION_COUNT" -lt 2 ]; then
31
+ echo "Phase 2.5 skipped: ${INVESTIGATION_COUNT} investigation(s) in batch — nothing to reconcile. Proceeding to Phase 3."
32
+ SYNTHESIS_RAN=false
33
+ RECONCILED_COUNT=0
34
+ # Skip to Phase 3.
35
+ else
36
+ SYNTHESIS_RAN=true
37
+ fi
38
+ ```
39
+
40
+ If `SYNTHESIS_RAN` is false, do NOT execute Steps 2.5B–2.5D — proceed directly to Phase 3. Step 4A's `{GIST_CONTEXT}` generation will fall back to the existing raw-gist behavior (no synthesis brief exists).
41
+
42
+ ### Step 2.5B: Cluster investigations by target subsystem
43
+
44
+ For each investigation that completed in Wave 0, read its `FORGE:INVESTIGATOR` comment (and the newly spawned implementation issue bodies from Step 2D) and extract its **Recommendation** and **Affected Files / target subsystem** — NOT to compare files for merge conflicts, but to group investigations that operate on the **same conceptual surface** (e.g. "auth session lifecycle", "credit metering", "orchestrate DAG construction").
45
+
46
+ ```bash
47
+ # For each investigation, pull its recommendation + affected-files block (annotations only — no code reads)
48
+ declare -A INV_RECOMMENDATION
49
+ declare -A INV_SUBSYSTEM
50
+ for INV_NUM in {investigation_numbers}; do
51
+ INV_BODY=$(gh api repos/{GH_REPO}/issues/${INV_NUM}/comments \
52
+ --jq '.[] | select(.body | contains("FORGE:INVESTIGATOR")) | .body' 2>/dev/null | head -1)
53
+ # Extract the Recommendation section (annotation prose only)
54
+ INV_RECOMMENDATION[$INV_NUM]=$(echo "$INV_BODY" | awk '/^### Recommendation/{p=1;next}/^### /{p=0}p')
55
+ # Derive a coarse subsystem tag from Affected Files directories + title keywords
56
+ INV_SUBSYSTEM[$INV_NUM]=$(echo "$INV_BODY" \
57
+ | grep -oP '`[^`]+/[^`]+`' | xargs -r -n1 dirname 2>/dev/null | sort | uniq -c | sort -rn | head -1)
58
+ done
59
+ ```
60
+
61
+ **Cluster rule**: Two investigations are in the same cluster when they share a target subsystem (overlapping affected-file directories OR the same domain tag from Step 3B applied to their recommendations). Clustering is by **conceptual surface**, deliberately coarser than Step 3C's file-level analysis — the goal is to surface plan-level contradictions the file layer cannot see.
62
+
63
+ **Forward reference — related future signal** <!-- Added: forge#1196 -->: This clustering step (Step 2.5B) runs before Phase 3, so no Layer 5 data exists yet at this point — do not treat it as an input here. For readers extending this clustering rule in the future: Step 3C Layer 5 (historical co-change coupling, computed later in Phase 3) is a related signal worth reusing — two investigations whose affected files have historically co-changed would be good candidates for the same subsystem cluster. This is purely a forward reference, not a functional dependency or phase-reordering.
64
+
65
+ ### Step 2.5C: Detect and resolve competing recommendations
66
+
67
+ Within each cluster (2+ investigations on the same subsystem), compare the **Recommendation** sections for incompatibility — e.g. one recommends adding a cache layer while another recommends removing caching from the same path; one proposes a new abstraction another proposes to delete. This is a semantic comparison of *proposed approaches*, read purely from the annotation prose.
68
+
69
+ For each detected conflict, resolve it in exactly ONE of two ways:
70
+
71
+ 1. **Arbitration decision** — When the two recommendations are directly incompatible and one is clearly correct given the combined evidence, record a single deconflicted decision for BOTH issues. State which approach wins and why. This decision is written into each affected issue's `FORGE:SYNTHESIS_BRIEF` (Step 2.5D) — it does NOT close either issue; both still run, but against a reconciled plan.
72
+ 2. **Serialization edge** — When the approaches are interdependent (the second issue's correct approach depends on what the first decides) or arbitration cannot pick a winner from annotations alone, add a `Depends on #{FIRST}` marker to the SECOND issue's body so the two serialize. The second agent then inherits the first's merged result during its own investigation/context phase.
73
+
74
+ ```bash
75
+ # Serialization is expressed as a standard "Depends on #X" edge so Step 3A consumes it
76
+ # with no new plumbing (see Step 3A dependency-marker parsing).
77
+ RECONCILED_COUNT=0
78
+ N_ARBITRATED=0
79
+ N_SERIALIZED=0
80
+ for CONFLICT in "${DETECTED_CONFLICTS[@]}"; do
81
+ # CONFLICT = "FIRST SECOND RESOLUTION" where RESOLUTION is "arbitrate" or "serialize"
82
+ set -- $CONFLICT; FIRST=$1; SECOND=$2; RESOLUTION=$3
83
+ if [ "$RESOLUTION" = "serialize" ]; then
84
+ # Reverse-direction cycle guard: before adding "#SECOND depends on #FIRST", check
85
+ # whether #FIRST already declares "Depends on #SECOND". If it does, the requested
86
+ # edge would close a 2-node cycle (#FIRST -> #SECOND -> #FIRST) that Step 3D.5's
87
+ # cycle detector would later have to exclude from dispatch entirely (both issues
88
+ # stuck behind needs-human). Skip the edge and fall back to arbitration-in-place
89
+ # instead, so both issues still run.
90
+ FIRST_BODY=$(gh issue view $FIRST -R {GH_REPO} --json body --jq '.body')
91
+ if echo "$FIRST_BODY" | grep -qiE "depends on #${SECOND}\b"; then
92
+ echo "Phase 2.5: skipping serialization edge #${FIRST} -> #${SECOND}: reverse edge #${SECOND} -> #${FIRST} already exists (would create a cycle). Falling back to arbitration-in-place."
93
+ RESOLUTION="arbitrate"
94
+ else
95
+ SECOND_BODY=$(gh issue view $SECOND -R {GH_REPO} --json body --jq '.body')
96
+ if ! echo "$SECOND_BODY" | grep -qiE "depends on #${FIRST}\b"; then
97
+ gh issue edit $SECOND -R {GH_REPO} \
98
+ --body "${SECOND_BODY}
99
+
100
+ Depends on #${FIRST}
101
+ <!-- Serialized by orchestrate Phase 2.5: competing recommendation reconciled via dependency edge. -->"
102
+ fi
103
+ fi
104
+ fi
105
+ # Re-check RESOLUTION (may have been downgraded from "serialize" to "arbitrate" above)
106
+ # so the breakdown counters and the Step 2.5D per-issue decision recording both reflect
107
+ # the resolution that was actually applied, not the one originally proposed.
108
+ if [ "$RESOLUTION" = "serialize" ]; then
109
+ N_SERIALIZED=$((N_SERIALIZED + 1))
110
+ else
111
+ N_ARBITRATED=$((N_ARBITRATED + 1))
112
+ fi
113
+ RECONCILED_COUNT=$((RECONCILED_COUNT + 1))
114
+ done
115
+ echo "Phase 2.5 reconciled ${RECONCILED_COUNT} competing recommendation(s) (${N_ARBITRATED} arbitrated, ${N_SERIALIZED} serialized)."
116
+ ```
117
+
118
+ **MUST NOT**: close, skip, or merge any issue on the basis of a detected conflict. Two issues with competing recommendations are BOTH valid work items — Phase 2.5 makes their plans coherent, it does not eliminate either. (This is the Safety Rule 9 boundary — see the Purpose note above.)
119
+
120
+ ### Step 2.5D: Emit one deconflicted brief per issue
121
+
122
+ For each implementation issue about to be dispatched, write a single `FORGE:SYNTHESIS_BRIEF` annotation containing ONLY the reconciled context relevant to *that* issue — the arbitration decisions affecting it and pointers to the specific sibling investigation Gists it actually needs. This replaces injecting the entire aggregated milestone-index gist (which forces each agent to independently re-arbitrate the same contradictions, wasting tokens and producing nondeterministic cross-PR incoherence).
123
+
124
+ ```bash
125
+ for ISSUE_NUM in {implementation_issue_numbers}; do
126
+ # Assemble the per-issue brief: arbitration decisions touching this issue's subsystem +
127
+ # only the relevant sibling gist URLs (not the full milestone-index dump)
128
+ BRIEF_BODY="Reconciled context for this issue (see orchestrate Phase 2.5):
129
+ ${PER_ISSUE_DECISIONS[$ISSUE_NUM]}"
130
+ gh issue comment $ISSUE_NUM -R {GH_REPO} --body "<!-- FORGE:SYNTHESIS_BRIEF -->
131
+ ## Synthesis Brief
132
+
133
+ ${BRIEF_BODY}
134
+
135
+ <!-- FORGE:SYNTHESIS_BRIEF:COMPLETE -->"
136
+ done
137
+ ```
138
+
139
+ The `FORGE:SYNTHESIS_BRIEF` annotation is consumed by Step 4A's `{GIST_CONTEXT}` generation (which prefers it over the raw milestone-index gist when present) and its reconciled count (`RECONCILED_COUNT`) feeds the Step 6B `Competing recommendations reconciled (Phase 2.5)` metric.
140
+
141
+ **Report**: Post a brief Phase 2.5 summary to the user before proceeding to Phase 3:
142
+
143
+ ```
144
+ ## Phase 2.5: Investigation Synthesis
145
+
146
+ **Investigations reconciled**: {INVESTIGATION_COUNT}
147
+ **Competing recommendations detected**: {RECONCILED_COUNT}
148
+ - Arbitrated in place: {N_ARBITRATED} (includes any serialization edges downgraded by the reverse-cycle guard)
149
+ - Serialized via dependency edge: {N_SERIALIZED}
150
+ **Per-issue synthesis briefs emitted**: {N_briefs}
151
+
152
+ Proceeding to dependency analysis with a deconflicted plan set...
153
+ ```
154
+
155
+ ---
156
+