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
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Create a revert PR to roll back a shipped feature or fix that caused a production incident
3
3
  argument-hint: [PR number to revert, or "last" for most recent deploy]
4
+ install: extras
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -15,7 +16,7 @@ argument-hint: [PR number to revert, or "last" for most recent deploy]
15
16
 
16
17
  You are the pipeline's emergency rollback system. When a shipped feature or fix causes production issues, this command creates a revert PR and fast-tracks it through the pipeline.
17
18
 
18
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`. User can override with `--model <name>`.
19
+ **Agent model policy**: `model: "sonnet"` (standard tier). Fallback: `model: "opus"` if rate-limited. User can override with `--model <name>`. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.
19
20
 
20
21
  **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
21
22
 
package/commands/scope.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Estimate issue complexity before running /work-on — affected files, blast radius, risk flags, and decomposition recommendation
3
3
  argument-hint: <issue number> [--repo {owner}/{repo}]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /scope — Pre-Flight Complexity Estimator
@@ -11,7 +12,7 @@ You are a read-only pre-flight analyst. Given a GitHub issue number, you estimat
11
12
 
12
13
  **This command is strictly READ-ONLY.** No labels are written, no comments are posted, no worktrees are created.
13
14
 
14
- **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.
15
16
  **NEVER use plan mode (EnterPlanMode).**
16
17
 
17
18
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Periodic security posture audit — runs a scripted 4-phase checklist against repo files (not diffs), creates GitHub issues for confirmed findings
3
3
  argument-hint: [--repo <prefix>] [--phase 1|2|3|4|all] [--dry-run]
4
+ install: extras
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -18,7 +19,7 @@ This command is designed to be run:
18
19
 
19
20
  This is NOT a PR review — it does not approve or block. It creates issues for each gap found.
20
21
 
21
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
22
+ **Agent model policy**: `model: "sonnet"`, `effort: xhigh` (deep tier — comprehensive security analysis). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` only on Claude Code >= 2.1.154.
22
23
  **NEVER use plan mode (EnterPlanMode).**
23
24
 
24
25
  ---
@@ -0,0 +1,623 @@
1
+ ---
2
+ description: Closed-loop autonomy — convert a production/analytics/incident signal into a dependency-ordered issue DAG, execute via /orchestrate, then verify the originating signal is resolved. Event-driven companion to /autopilot.
3
+ argument-hint: [--signal '<json>' | --metric '<name> <threshold>' | --incident <issue#> | --geo | --dry-run | --max-issues N]
4
+ install: extras
5
+ ---
6
+ <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
7
+ <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
8
+
9
+ # /signal-planner — Closed-Loop Production Signal to Verified Resolution
10
+
11
+ **Input**: $ARGUMENTS
12
+
13
+ **Config variables used by this command** (set in `forge.yaml`):
14
+ - `{CREDENTIALS_FILE}` ← `paths.credentials.file` (optional) — path to credentials YAML for analytics APIs
15
+ - `{BILLING_ENABLED}` ← `billing.enabled` (optional, default `false`) — enable Stripe data in signal hydration
16
+ - `{GOVERNOR_MAX_ISSUES}` ← `governor.max_issues_per_run` (optional, default `10`) — hard cap on issues spawned per run
17
+ - `{GOVERNOR_MAX_COST_USD}` ← `governor.max_cost_usd` (optional, default `5.00`) — hard cap on estimated LLM spend per run
18
+
19
+ **NEVER use plan mode (EnterPlanMode).**
20
+ **NEVER use the Agent tool** for implementation work — dispatch issues via `Skill(skill="work-on", ...)` or via `/orchestrate`.
21
+
22
+ <!-- FORGE:SPEC_LOADED — signal-planner.md loaded and active. Agent is bound by this spec. -->
23
+
24
+ You are the closed-loop autonomy engine. Your job is to accept a production signal (metric regression, incident event, GEO gap), plan a dependency-ordered issue DAG, execute it via `/orchestrate`, and then verify the originating signal is resolved. You close the loop from observation to verification — no human needs to author a single issue.
25
+
26
+ ---
27
+
28
+ ## Argument Parsing
29
+
30
+ Parse `$ARGUMENTS` and set:
31
+
32
+ ```
33
+ SIGNAL_JSON = raw JSON from --signal '...' (if provided)
34
+ SIGNAL_METRIC = metric name + threshold from --metric '<name> <threshold>' (if provided)
35
+ SIGNAL_INCIDENT = issue number from --incident <N> (if provided)
36
+ SIGNAL_GEO = true if --geo flag present
37
+ DRY_RUN = true if --dry-run present
38
+ MAX_ISSUES_OVERRIDE = N from --max-issues N (if provided)
39
+ ```
40
+
41
+ **Signal source priority** (first match wins):
42
+ 1. `--signal` — structured JSON signal (most precise)
43
+ 2. `--metric` — named metric with threshold breach
44
+ 3. `--incident` — P0/P1 incident issue number
45
+ 4. `--geo` — run geo-audit sensor for GEO gaps
46
+ 5. *(no flag)* — interactive: print usage and exit
47
+
48
+ If no recognized signal flag is present, print:
49
+
50
+ ```
51
+ /signal-planner requires a signal source. Examples:
52
+
53
+ /signal-planner --signal '{"type":"metric","name":"gsc_clicks","value":1200,"baseline":2000,"window":"7d"}'
54
+ /signal-planner --metric "checkout_latency_p99 >2000ms"
55
+ /signal-planner --incident 55
56
+ /signal-planner --geo
57
+ /signal-planner --dry-run --signal '...' # plan only, no issues created
58
+ ```
59
+
60
+ Then exit.
61
+
62
+ ---
63
+
64
+ ## Phase 0: Economic Governor (MANDATORY — run before ANY side effects)
65
+
66
+ **Goal**: Prevent runaway spend. Hard-fail if governor limits would be breached.
67
+
68
+ ### 0A: Resolve governor config
69
+
70
+ ```bash
71
+ FORGE_YAML="${FORGE_CONFIG:-$(git rev-parse --show-toplevel 2>/dev/null)/forge.yaml}"
72
+
73
+ GOVERNOR_MAX_ISSUES=$(python3 -c "
74
+ import yaml, sys
75
+ cfg = yaml.safe_load(open('$FORGE_YAML')) if __import__('os').path.exists('$FORGE_YAML') else {}
76
+ print(cfg.get('governor', {}).get('max_issues_per_run', 10))
77
+ " 2>/dev/null || echo "10")
78
+
79
+ GOVERNOR_MAX_COST=$(python3 -c "
80
+ import yaml, sys
81
+ cfg = yaml.safe_load(open('$FORGE_YAML')) if __import__('os').path.exists('$FORGE_YAML') else {}
82
+ print(cfg.get('governor', {}).get('max_cost_usd', 5.00))
83
+ " 2>/dev/null || echo "5.00")
84
+
85
+ # Apply per-run override
86
+ if [ -n "$MAX_ISSUES_OVERRIDE" ]; then
87
+ GOVERNOR_MAX_ISSUES=$(( MAX_ISSUES_OVERRIDE < GOVERNOR_MAX_ISSUES ? MAX_ISSUES_OVERRIDE : GOVERNOR_MAX_ISSUES ))
88
+ fi
89
+ ```
90
+
91
+ ### 0B: Record governor state
92
+
93
+ Store `GOVERNOR_MAX_ISSUES` and `GOVERNOR_MAX_COST` as the hard caps for this run. They are checked in Phase 3 before any issue is created. Exceeding them is a hard fail — not a warning.
94
+
95
+ Print:
96
+ ```
97
+ [signal-planner] Governor: max_issues={GOVERNOR_MAX_ISSUES}, max_cost_usd={GOVERNOR_MAX_COST}
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Phase 1: Signal Intake & Hydration
103
+
104
+ **Goal**: Normalize the raw input signal into a typed, structured `SIGNAL` object and hydrate it with enough context to plan work.
105
+
106
+ ### 1A: Normalize the signal
107
+
108
+ Build `SIGNAL` from the input:
109
+
110
+ ```
111
+ SIGNAL = {
112
+ type: "metric" | "incident" | "geo" | "raw",
113
+ name: <human-readable signal name>,
114
+ raw_input: <original input string or JSON>,
115
+ severity: "P0" | "P1" | "P2" | null,
116
+ context: {} # filled in 1B
117
+ }
118
+ ```
119
+
120
+ **For `--signal <json>`**: Parse JSON directly. Map `type` field; if absent, classify from content.
121
+
122
+ **For `--metric <name> <threshold>`**: Set `type="metric"`, `name=<name>`. Parse threshold string (e.g., `>2000ms`, `<80%`, `dropped 30%`). Set `severity` based on magnitude:
123
+ - >50% regression or latency >5x baseline → P0
124
+ - 20–50% regression → P1
125
+ - 10–20% regression → P2
126
+
127
+ **For `--incident <N>`**: Fetch the issue:
128
+
129
+ ```bash
130
+ gh issue view {N} -R {GH_REPO} --json number,title,body,labels,state \
131
+ --jq '{number: .number, title: .title, severity: (.labels | map(.name) | map(select(startswith("priority:"))) | .[0]), state: .state}'
132
+ ```
133
+
134
+ Set `type="incident"`, `name="incident #N: {title}"`, `severity` from label.
135
+
136
+ **For `--geo`**: Set `type="geo"`, `name="GEO compliance gap"`, `severity="P2"`. Hydration (1B) will call `/geo-audit`.
137
+
138
+ ### 1B: Hydrate context
139
+
140
+ Fetch live data to fill `SIGNAL.context` based on signal type:
141
+
142
+ **For `type="metric"`**:
143
+ - Read credentials from `{CREDENTIALS_FILE}` (from `forge.yaml`)
144
+ - Pull the named metric from its source (GSC/GA4/Umami/Cloudflare/Stripe) using the same MCP tools as `/analytics`
145
+ - Compute: current value, baseline (same window, prior period), delta, % change
146
+ - Store: `SIGNAL.context = { metric_name, current, baseline, delta_pct, window, source }`
147
+
148
+ **For `type="incident"`**:
149
+ - Read all comments on issue `{N}` — extract timeline, error messages, affected components
150
+ - Check recent CI runs for failures correlated with incident time
151
+ - Store: `SIGNAL.context = { issue_number, title, body, timeline, affected_components, ci_failures }`
152
+
153
+ **For `type="geo"`**:
154
+ - Call `/geo-audit` sensors: Umami AI referral traffic, Clarity heatmaps, page compliance checks
155
+ - Collect gaps: missing structured data, broken OG tags, missing llms.txt entries, stale pages
156
+ - Store: `SIGNAL.context = { gaps: [{page, type, severity}], ai_referral_trend, compliance_score }`
157
+
158
+ **For `type="raw"`**:
159
+ - Parse prose for affected areas: look for file paths, feature names, metric names, error strings
160
+ - Store: `SIGNAL.context = { parsed_areas, raw_text }`
161
+
162
+ **Hydration timeout**: If any data source is unreachable, note it in `SIGNAL.context.hydration_warnings` and proceed — don't fail the whole run on a single unavailable API.
163
+
164
+ Print a compact hydration summary:
165
+ ```
166
+ [signal-planner] Signal: {type} / {name} / {severity}
167
+ [signal-planner] Context: {key facts from hydration — 2-3 bullet points}
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Phase 2: Plan DAG
173
+
174
+ **Goal**: Analyse the hydrated signal, cluster it into work units, resolve cross-unit dependencies, and emit a reviewable dependency DAG.
175
+
176
+ ### 2A: Deduplication — check for existing open issues
177
+
178
+ Before planning ANY new issues, scan existing open issues:
179
+
180
+ ```bash
181
+ gh issue list -R {GH_REPO} --state open --limit 200 --json number,title,labels \
182
+ --jq '.[] | "\(.number) \(.title)"'
183
+ ```
184
+
185
+ For each candidate work unit, check if an open issue already covers it. If yes — record it as `EXISTING_ISSUE` and use it in the DAG instead of creating a new one.
186
+
187
+ ### 2B: Cluster signal into work units
188
+
189
+ Analyse `SIGNAL.context` and identify discrete, independently-deployable work units:
190
+
191
+ **Rules for clustering**:
192
+ - Each work unit must map to a single `commands/` area, module, or clearly scoped change
193
+ - A work unit must be completable in one `/work-on` run (not a multi-week epic)
194
+ - If a work unit depends on another's output (e.g., schema change before UI), record the dependency
195
+ - Maximum `GOVERNOR_MAX_ISSUES` work units total — if more are found, rank by impact and take the top N
196
+
197
+ **For each work unit, draft**:
198
+ ```
199
+ {
200
+ title: "fix|feat|refactor: <concise description>",
201
+ type: "bug" | "feature" | "refactor",
202
+ priority: "P0" | "P1" | "P2" | "P3",
203
+ scope: <affected file or module>,
204
+ rationale: <1 sentence: why this addresses the signal>,
205
+ depends_on: [<work_unit_indices>], # empty = no deps
206
+ existing: <issue number if already open, else null>
207
+ }
208
+ ```
209
+
210
+ ### 2C: Resolve dependency order (topological sort)
211
+
212
+ Sort work units so no unit appears before all its dependencies:
213
+
214
+ ```python
215
+ # Pseudocode — implement with standard topological sort
216
+ order = topological_sort(work_units, key=lambda u: u.depends_on)
217
+ # Result: ordered list where dependencies always precede dependents
218
+ ```
219
+
220
+ Detect cycles — if a cycle exists, break it by demoting the lower-priority unit to depend on the higher-priority one and log a `CYCLE_BROKEN` warning.
221
+
222
+ ### 2D: Emit FORGE:PLAN_DAG annotation
223
+
224
+ Post the DAG to a tracker issue on GitHub. First, create the tracker issue:
225
+
226
+ ```bash
227
+ TRACKER_ISSUE=$(gh issue create -R {GH_REPO} \
228
+ --title "signal-planner: DAG tracker for {SIGNAL.name}" \
229
+ --label "signal-planner,priority:{SIGNAL.severity}" \
230
+ --body "$(cat <<'TRACKER_EOF'
231
+ ## Signal
232
+
233
+ **Type**: {SIGNAL.type}
234
+ **Name**: {SIGNAL.name}
235
+ **Severity**: {SIGNAL.severity}
236
+
237
+ ## Signal Context
238
+
239
+ {SIGNAL.context summary — key metrics, affected areas, evidence}
240
+
241
+ ## Work Plan
242
+
243
+ This tracker was created by \`/signal-planner\`. The dependency DAG below represents the planned work to resolve the originating signal.
244
+
245
+ ## Acceptance
246
+
247
+ - [ ] All DAG issues merged
248
+ - [ ] Originating signal verified resolved (FORGE:SIGNAL_RESOLVED posted)
249
+ TRACKER_EOF
250
+ )" --json number --jq '.number')
251
+ ```
252
+
253
+ Then post the `FORGE:PLAN_DAG` comment:
254
+
255
+ ```bash
256
+ gh issue comment $TRACKER_ISSUE -R {GH_REPO} --body "$(cat <<'DAG_EOF'
257
+ <!-- FORGE:PLAN_DAG -->
258
+ ## Planned Dependency DAG
259
+
260
+ **Signal**: {SIGNAL.name}
261
+ **Generated**: $(date -u +%Y-%m-%dT%H:%M:%SZ)
262
+ **Governor**: max_issues={GOVERNOR_MAX_ISSUES}, max_cost_usd={GOVERNOR_MAX_COST}
263
+
264
+ ### Work Units (execution order)
265
+
266
+ | Order | Issue | Title | Priority | Depends On | Status |
267
+ |-------|-------|-------|----------|------------|--------|
268
+ {rows — one per work unit, existing issues link to their number, new ones show "pending"}
269
+
270
+ ### Dependency Graph
271
+
272
+ \`\`\`
273
+ {ASCII or text representation of the DAG edges}
274
+ \`\`\`
275
+
276
+ ### Rationale
277
+
278
+ {1-2 sentence explanation of how this plan addresses the originating signal}
279
+
280
+ <!-- FORGE:PLAN_DAG:COMPLETE -->
281
+ DAG_EOF
282
+ )"
283
+ ```
284
+
285
+ **DRY_RUN check**: If `DRY_RUN == true`:
286
+ - Print the planned DAG to stdout
287
+ - Do NOT create the tracker issue or any work issues
288
+ - Print `[dry-run] No issues created. Re-run without --dry-run to execute.`
289
+ - Stop here
290
+
291
+ ---
292
+
293
+ ## Phase 3: Issue Creation (Governor-Gated)
294
+
295
+ **Goal**: Create GitHub issues for all new work units in the DAG.
296
+
297
+ ### 3A: Governor pre-flight check
298
+
299
+ ```python
300
+ new_issues_needed = len([u for u in work_units if u.existing is None])
301
+ if new_issues_needed > GOVERNOR_MAX_ISSUES:
302
+ # Hard fail
303
+ print(f"GOVERNOR BREACH: {new_issues_needed} issues needed but governor cap is {GOVERNOR_MAX_ISSUES}")
304
+ print("Reduce scope or raise governor.max_issues_per_run in forge.yaml")
305
+ exit(1)
306
+ ```
307
+
308
+ If governor would be breached, **hard fail** — do not create any issues, do not proceed to Phase 4.
309
+
310
+ ### 3B: Create issues in dependency order
311
+
312
+ For each work unit with `existing == null`, create a GitHub issue:
313
+
314
+ ```bash
315
+ ISSUE_NUM=$(gh issue create -R {GH_REPO} \
316
+ --title "{work_unit.title}" \
317
+ --label "priority:{work_unit.priority},{work_unit.type}" \
318
+ --body "$(cat <<'ISSUE_EOF'
319
+ ## Problem
320
+
321
+ {work_unit.rationale — why this is needed to resolve the originating signal}
322
+
323
+ ## Signal Source
324
+
325
+ Generated by \`/signal-planner\` from signal: **{SIGNAL.name}** ({SIGNAL.type}, {SIGNAL.severity})
326
+ Tracker issue: #{TRACKER_ISSUE}
327
+
328
+ ## Affected Files
329
+
330
+ 1. `{work_unit.scope}` — address the signal-identified gap
331
+
332
+ ## Acceptance Criteria
333
+
334
+ - [ ] {specific criterion derived from the signal context}
335
+ - [ ] Signal metric/incident verified not regressing after this change
336
+
337
+ ## Context
338
+
339
+ Signal context: {relevant subset of SIGNAL.context for this work unit}
340
+
341
+ ---
342
+ *Created by \`/signal-planner\` on $(date -u +%Y-%m-%dT%H:%M:%SZ). Will be investigated before any fix is applied.*
343
+ ISSUE_EOF
344
+ )" --json number --jq '.number')
345
+ ```
346
+
347
+ Record each created issue number and update the DAG table in the tracker issue.
348
+
349
+ ### 3C: Compile final DAG issue list
350
+
351
+ Build `DAG_ISSUES` = ordered list of issue numbers (existing + newly created), in topological execution order.
352
+
353
+ Update the tracker issue `FORGE:PLAN_DAG` comment with the final resolved issue numbers.
354
+
355
+ ---
356
+
357
+ ## Phase 4: Execute DAG via /orchestrate
358
+
359
+ **Goal**: Dispatch the ordered DAG to `/orchestrate` for parallel execution.
360
+
361
+ ### 4A: Present execution plan to user
362
+
363
+ **MANDATORY CHECKPOINT** — do NOT proceed without confirmation.
364
+
365
+ ```markdown
366
+ ## Signal Planner — Execution Plan
367
+
368
+ **Signal**: {SIGNAL.name} ({SIGNAL.type} / {SIGNAL.severity})
369
+ **Tracker**: #{TRACKER_ISSUE}
370
+
371
+ I'll execute these {N} issues via /orchestrate (dependency order preserved):
372
+
373
+ | Order | Issue | Title | Priority |
374
+ |-------|-------|-------|----------|
375
+ | 1 | #{N} | ... | P1 |
376
+ | 2 | #{N} | ... | P2 |
377
+
378
+ Dependencies: {summary of any ordering constraints}
379
+
380
+ Each issue goes through: investigate → architect → build → review → merge to staging.
381
+ Nothing merges to `main` — you deploy when ready.
382
+
383
+ After all issues merge, I'll re-check the originating signal and post FORGE:SIGNAL_RESOLVED or FORGE:SIGNAL_UNRESOLVED.
384
+
385
+ **Proceed?** (yes / adjust / skip)
386
+ ```
387
+
388
+ Wait for user response. If they adjust (e.g., drop an issue, change priority), update `DAG_ISSUES` accordingly. If they skip, end here and leave the tracker issue open for manual execution.
389
+
390
+ ### 4B: Dispatch to /orchestrate
391
+
392
+ Pass `DAG_ISSUES` as an ordered issue set to `/orchestrate`:
393
+
394
+ ```
395
+ Skill(skill: "orchestrate", args: "{DAG_ISSUES joined by space — e.g. '42 43 45'}")
396
+ ```
397
+
398
+ `/orchestrate` handles parallel execution where dependencies allow — signal-planner does not re-implement execution logic.
399
+
400
+ ### 4C: Monitor completion
401
+
402
+ Poll until all DAG issues reach `workflow:merged`:
403
+
404
+ ```bash
405
+ # Check each issue in DAG_ISSUES
406
+ for issue in $DAG_ISSUES; do
407
+ gh issue view $issue -R {GH_REPO} --json labels \
408
+ --jq '.labels | map(.name) | any(. == "workflow:merged")'
409
+ done
410
+ ```
411
+
412
+ Repeat every 5 minutes (or when notified by orchestrate completion) until all issues are merged or a timeout is reached (default: 2 hours). If timeout is reached, post an interim `FORGE:PLAN_DAG_STALLED` comment and exit — do not block indefinitely.
413
+
414
+ ---
415
+
416
+ ## Phase 5: Signal Verification
417
+
418
+ **Goal**: Re-check the originating metric/incident after all DAG issues are merged. Post `FORGE:SIGNAL_RESOLVED` or `FORGE:SIGNAL_UNRESOLVED`.
419
+
420
+ ### 5A: Re-fetch signal data
421
+
422
+ Repeat the same data collection from Phase 1B using the same source and parameters. This produces `SIGNAL_AFTER`.
423
+
424
+ **For `type="metric"`**: Pull the same metric with the same window — compare `SIGNAL_AFTER.current` vs `SIGNAL.context.current` (the pre-fix value) and vs `SIGNAL.context.baseline`.
425
+
426
+ **For `type="incident"`**: Check if the incident issue is closed and has `workflow:merged` label. Check CI runs since the merge for clean builds.
427
+
428
+ **For `type="geo"`**: Re-run the same compliance checks from Phase 1B. Compute new compliance score.
429
+
430
+ **For `type="raw"`**: Re-examine the affected areas identified in Phase 1B for the described problem.
431
+
432
+ ### 5B: Evaluate resolution
433
+
434
+ ```python
435
+ RESOLVED = False
436
+
437
+ if SIGNAL.type == "metric":
438
+ # Resolved if current value is within 10% of baseline (or above baseline)
439
+ recovery_pct = (SIGNAL_AFTER.current - SIGNAL.context.current) / abs(SIGNAL.context.delta_pct)
440
+ RESOLVED = SIGNAL_AFTER.current >= SIGNAL.context.baseline * 0.90
441
+
442
+ elif SIGNAL.type == "incident":
443
+ RESOLVED = incident_issue.state == "closed" and ci_clean_since_merge
444
+
445
+ elif SIGNAL.type == "geo":
446
+ RESOLVED = SIGNAL_AFTER.compliance_score >= SIGNAL.context.compliance_score + 0.10
447
+
448
+ elif SIGNAL.type == "raw":
449
+ # Conservative: mark unresolved, require human confirmation
450
+ RESOLVED = False
451
+ ```
452
+
453
+ ### 5C: Post verification annotation
454
+
455
+ If `RESOLVED == True`, post `FORGE:SIGNAL_RESOLVED`:
456
+
457
+ ```bash
458
+ gh issue comment $TRACKER_ISSUE -R {GH_REPO} --body "$(cat <<'RESOLVED_EOF'
459
+ <!-- FORGE:SIGNAL_RESOLVED -->
460
+ ## Signal Resolution Verified
461
+
462
+ **Signal**: {SIGNAL.name}
463
+ **Resolved**: $(date -u +%Y-%m-%dT%H:%M:%SZ)
464
+
465
+ ### Before / After
466
+
467
+ | Metric | Before | After | Baseline |
468
+ |--------|--------|-------|----------|
469
+ | {name} | {SIGNAL.context.current} | {SIGNAL_AFTER.current} | {SIGNAL.context.baseline} |
470
+
471
+ ### Conclusion
472
+
473
+ The originating signal is resolved. All {N} DAG issues merged to staging. Baseline metric recovered within tolerance.
474
+
475
+ **Next step**: Merge staging → main when ready to deploy.
476
+
477
+ <!-- FORGE:SIGNAL_RESOLVED:COMPLETE -->
478
+ RESOLVED_EOF
479
+ )"
480
+ ```
481
+
482
+ If `RESOLVED == False`, post `FORGE:SIGNAL_UNRESOLVED`:
483
+
484
+ ```bash
485
+ gh issue comment $TRACKER_ISSUE -R {GH_REPO} --body "$(cat <<'UNRESOLVED_EOF'
486
+ <!-- FORGE:SIGNAL_UNRESOLVED -->
487
+ ## Signal Verification: UNRESOLVED
488
+
489
+ **Signal**: {SIGNAL.name}
490
+ **Checked**: $(date -u +%Y-%m-%dT%H:%M:%SZ)
491
+
492
+ ### Before / After
493
+
494
+ | Metric | Before | After | Baseline |
495
+ |--------|--------|-------|----------|
496
+ | {name} | {SIGNAL.context.current} | {SIGNAL_AFTER.current} | {SIGNAL.context.baseline} |
497
+
498
+ ### Conclusion
499
+
500
+ The signal is **not yet resolved** after DAG execution. Possible causes:
501
+ - The root cause spans more files than the DAG covered
502
+ - A dependency issue was excluded by the governor cap
503
+ - The signal is caused by an external factor outside this repo
504
+
505
+ ### Recommended Actions
506
+
507
+ 1. Review the DAG tracker issue: #{TRACKER_ISSUE}
508
+ 2. Check if any work units were skipped or failed
509
+ 3. Run \`/signal-planner\` again with a broader scope, or investigate manually with \`/work-on\`
510
+
511
+ <!-- FORGE:SIGNAL_UNRESOLVED:COMPLETE -->
512
+ UNRESOLVED_EOF
513
+ )"
514
+ ```
515
+
516
+ ### 5D: Close the tracker issue
517
+
518
+ If `RESOLVED == True`:
519
+ ```bash
520
+ gh issue close $TRACKER_ISSUE -R {GH_REPO} \
521
+ --comment "Closing tracker: originating signal verified resolved (FORGE:SIGNAL_RESOLVED posted)." \
522
+ --reason "completed"
523
+ gh issue edit $TRACKER_ISSUE -R {GH_REPO} --add-label "workflow:merged"
524
+ ```
525
+
526
+ If `RESOLVED == False`, leave the tracker open for human review.
527
+
528
+ ---
529
+
530
+ ## Phase 6: Final Report
531
+
532
+ Print a summary regardless of resolution outcome:
533
+
534
+ ```markdown
535
+ ## Signal Planner — Cycle Complete
536
+
537
+ **Signal**: {SIGNAL.name} ({SIGNAL.type} / {SIGNAL.severity})
538
+ **Tracker**: #{TRACKER_ISSUE}
539
+ **Started**: {START_TIME}
540
+ **Completed**: $(date -u +%Y-%m-%dT%H:%M:%SZ)
541
+
542
+ ### DAG Summary
543
+
544
+ | Issue | Title | Outcome |
545
+ |-------|-------|---------|
546
+ | #{N} | ... | merged |
547
+
548
+ **Issues created**: {new_count}
549
+ **Issues reused**: {existing_count}
550
+ **Governor headroom**: {GOVERNOR_MAX_ISSUES - total_issues} issues remaining
551
+
552
+ ### Signal Resolution
553
+
554
+ **Status**: {RESOLVED / UNRESOLVED}
555
+ {resolution detail — 1-2 sentences}
556
+
557
+ ### Next Steps
558
+
559
+ {If resolved}: Merge staging → main to deploy the fix.
560
+ {If unresolved}: Review tracker #{TRACKER_ISSUE} — consider /signal-planner with broader scope or /work-on for manual investigation.
561
+ ```
562
+
563
+ ---
564
+
565
+ ## FORGE Annotations Introduced by This Command
566
+
567
+ | Annotation | Writer | Consumer | Purpose |
568
+ |------------|--------|----------|---------|
569
+ | `FORGE:PLAN_DAG` | signal-planner (Phase 2D) | signal-planner (Phase 4), humans | Reviewable dependency DAG before execution |
570
+ | `FORGE:PLAN_DAG_STALLED` | signal-planner (Phase 4C) | humans | Execution timed out — DAG not fully merged |
571
+ | `FORGE:SIGNAL_RESOLVED` | signal-planner (Phase 5C) | humans, future autopilot cycles | Originating signal verified resolved |
572
+ | `FORGE:SIGNAL_UNRESOLVED` | signal-planner (Phase 5C) | humans | Post-execution signal check failed |
573
+
574
+ ---
575
+
576
+ ## Safety Rules
577
+
578
+ 1. **NEVER merge to `main`** — all work goes to `staging`. User deploys manually.
579
+ 2. **Governor is a hard fail** — if `new_issues > GOVERNOR_MAX_ISSUES`, abort Phase 3. Do not warn and continue.
580
+ 3. **MANDATORY checkpoint before execution** — Phase 4A user gate is non-negotiable. Never auto-execute without confirmation.
581
+ 4. **Dedup before creating** — always check existing open issues before creating any new one (Phase 2A).
582
+ 5. **DRY_RUN means NO side effects** — no issues created, no comments, no label changes. Plan output only.
583
+ 6. **Hydration failure is non-fatal** — if a sensor is unreachable, log a warning and continue with partial context.
584
+ 7. **Resolution verdict is conservative** — when in doubt (type="raw", ambiguous metrics), post FORGE:SIGNAL_UNRESOLVED and let the human decide.
585
+ 8. **Tracker issue is always created first** — even if all DAG issues are existing ones, the tracker provides the audit trail for this signal-planner run.
586
+ 9. **NEVER fix `needs-human` issues** — issues with this label are excluded from the DAG automatically.
587
+
588
+ ---
589
+
590
+ ## Relationship to Other Commands
591
+
592
+ | Command | Relationship |
593
+ |---------|-------------|
594
+ | `/autopilot` | Periodic improvement cycle. `/signal-planner` is its event-driven complement — triggered by a specific signal, not a timer. Use `/autopilot` for routine health checks; use `/signal-planner` when a specific signal fires. |
595
+ | `/analytics` | Signal sensor. `/signal-planner --metric` calls the same MCP tools as `/analytics` to hydrate metric signals. |
596
+ | `/geo-audit` | Signal sensor. `/signal-planner --geo` delegates GEO compliance checks to the `/geo-audit` sensor layer. |
597
+ | `/incident-response` | Signal sensor. `/signal-planner --incident` reads the incident issue and CI data as signal context. |
598
+ | `/orchestrate` | Execution engine. `/signal-planner` hands the ordered DAG issue list to `/orchestrate` for parallel dispatch. |
599
+ | `/work-on` | Per-issue pipeline. Called by `/orchestrate` for each DAG node. `/signal-planner` never calls `/work-on` directly. |
600
+
601
+ ---
602
+
603
+ ## Examples
604
+
605
+ ```bash
606
+ # Metric regression: GSC clicks dropped 40% week-over-week
607
+ /signal-planner --signal '{"type":"metric","name":"gsc_clicks","value":1200,"baseline":2000,"window":"7d"}'
608
+
609
+ # Latency alert from monitoring
610
+ /signal-planner --metric "checkout_latency_p99 >2000ms"
611
+
612
+ # Active P0 incident — plan fix DAG from the open incident issue
613
+ /signal-planner --incident 55
614
+
615
+ # GEO gap audit — plan issues for all compliance failures
616
+ /signal-planner --geo
617
+
618
+ # Dry run — see the plan without creating anything
619
+ /signal-planner --dry-run --signal '{"type":"metric","name":"conversion_rate","value":0.018,"baseline":0.031,"window":"7d"}'
620
+
621
+ # Conservative run — cap at 3 issues regardless of forge.yaml setting
622
+ /signal-planner --metric "error_rate >5%" --max-issues 3
623
+ ```
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Detect API changes, sync satellite repos, and publish releases
3
3
  argument-hint: [check | auto | status | publish | PR-number]
4
+ install: extras
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->