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: On-demand Claude Code compatibility and feature parity report — compares installed version against the breakpoints registry and lists affected ForgeDock features
3
3
  argument-hint: [--refresh]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /compat-audit — Claude Code Compatibility Report
@@ -9,7 +10,7 @@ argument-hint: [--refresh]
9
10
 
10
11
  You are the ForgeDock compatibility auditor. Produce a point-in-time advisory report that shows whether the user's installed Claude Code version is current and which ForgeDock features may behave differently on their runtime. This command is **non-blocking** — it never aborts the session. All output is advisory.
11
12
 
12
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
13
+ **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.
13
14
  **NEVER use plan mode (EnterPlanMode).**
14
15
 
15
16
  ---
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Show what will deploy next — diff staging vs main with issue/PR summary, risk assessment, and deploy checklist
3
3
  argument-hint: [staging | milestone/{slug} | compare {branch}]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /deploy-info — Pre-Deploy Summary
@@ -15,10 +16,12 @@ argument-hint: [staging | milestone/{slug} | compare {branch}]
15
16
 
16
17
  You are the pipeline's deploy awareness layer. Before the user merges staging → main (triggering CI/CD deployment), this command shows exactly what's going out: which PRs, which issues, what changed, and what risks exist.
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
 
23
+ <!-- FORGE:SPEC_LOADED — deploy-info.md loaded and active. Agent is bound by this spec. -->
24
+
22
25
  ---
23
26
 
24
27
  ## Phase 0: Review-Finding Readiness Check
@@ -156,7 +159,7 @@ done
156
159
  # Full file diff summary
157
160
  git diff --stat origin/$TARGET..origin/$SOURCE
158
161
 
159
- # Read layout paths from forge.yaml, fall back to AlterLab defaults
162
+ # Read layout paths from forge.yaml, fall back to forge.yaml defaults
160
163
  LAYOUT_API=$(yq '.review.layout.api // "services/api"' forge.yaml 2>/dev/null || echo "services/api")
161
164
  LAYOUT_WORKER=$(yq '.review.layout.worker // "services/worker"' forge.yaml 2>/dev/null || echo "services/worker")
162
165
  LAYOUT_PAGES=$(yq '.review.layout.pages // "web/src/app"' forge.yaml 2>/dev/null || echo "web/src/app")
@@ -231,8 +234,10 @@ if [ -n "$NEW_ENV" ]; then
231
234
  # If your project uses a different backend, skip this block and verify manually.
232
235
  if [ "{DEPLOY_SECRETS_BACKEND}" = "sops" ]; then
233
236
  for var in $(echo "$NEW_ENV" | grep -oE '^\+[A-Z_]+' | sed 's/^\+//'); do
234
- if ! grep -q "$var" scripts/decrypt-secrets.sh 2>/dev/null; then
235
- echo " ❌ $var NOT in decrypt-secrets.sh ENV_MAPPING"
237
+ if [ -f "{REPO_PATH}/scripts/decrypt-secrets.sh" ]; then
238
+ grep -q "$var" "{REPO_PATH}/scripts/decrypt-secrets.sh" 2>/dev/null || echo " ❌ $var NOT in decrypt-secrets.sh ENV_MAPPING"
239
+ else
240
+ echo " ℹ️ scripts/decrypt-secrets.sh not found — skipping ENV_MAPPING cross-check for $var. Verify manually in your SOPS chain."
236
241
  fi
237
242
  done
238
243
  else
@@ -276,6 +281,52 @@ gh workflow run {deploy.workflow} --ref main -f {deploy.workflow_inputs.services
276
281
 
277
282
  ---
278
283
 
284
+ ## Phase 4B: Deploy Train State <!-- Added: forge#1332 -->
285
+
286
+ **Purpose**: Report the current state of the rolling staging→main deploy candidate (the "merge train"). One deploy PR should stay open per deploy cycle — this phase shows whether a candidate exists, what is holding it, and what is queued behind it.
287
+
288
+ ```bash
289
+ git fetch origin {STAGING_BRANCH} {DEFAULT_BRANCH} 2>/dev/null
290
+
291
+ # Step 1: Find the current open staging→main deploy PR (the "train")
292
+ TRAIN_PR=$(gh pr list {GH_FLAG} \
293
+ --head "{STAGING_BRANCH}" \
294
+ --base "{DEFAULT_BRANCH}" \
295
+ --state open \
296
+ --json number,title,headRefOid,createdAt,reviewRequests \
297
+ --jq '.[0] // empty' 2>/dev/null)
298
+
299
+ TRAIN_PR_NUMBER=$(echo "$TRAIN_PR" | jq -r '.number // empty')
300
+ TRAIN_PR_SHA=$(echo "$TRAIN_PR" | jq -r '.headRefOid // empty' | cut -c1-7)
301
+ TRAIN_PR_CREATED=$(echo "$TRAIN_PR" | jq -r '.createdAt // empty')
302
+
303
+ if [ -z "$TRAIN_PR_NUMBER" ]; then
304
+ TRAIN_STATUS="NO_TRAIN — no open staging→main PR. Run /review-pr-staging to open one."
305
+ else
306
+ # Step 2: Check whether the train is held (has blocking findings)
307
+ HELD_BY=$(gh issue list {GH_FLAG} \
308
+ --label "review-finding" \
309
+ --state open \
310
+ --search "PR #${TRAIN_PR_NUMBER}" \
311
+ --limit 20 \
312
+ --json number,title \
313
+ --jq '[.[] | "#\(.number): \(.title)"] | join("\n")' 2>/dev/null || true)
314
+
315
+ if [ -n "$HELD_BY" ]; then
316
+ TRAIN_STATUS="HELD"
317
+ else
318
+ TRAIN_STATUS="CLEAR — ready to merge"
319
+ fi
320
+
321
+ # Step 3: Count commits queued (commits in staging not yet in main)
322
+ QUEUED_COMMITS=$(git rev-list --count origin/{DEFAULT_BRANCH}..origin/{STAGING_BRANCH} 2>/dev/null || echo "?")
323
+ fi
324
+ ```
325
+
326
+ Train state is included in the Phase 5 output summary.
327
+
328
+ ---
329
+
279
330
  ## Phase 5: Output Summary
280
331
 
281
332
  ```
@@ -283,6 +334,14 @@ gh workflow run {deploy.workflow} --ref main -f {deploy.workflow_inputs.services
283
334
 
284
335
  **Commits**: {N} | **PRs**: {N} | **Issues closed**: {N} | **Files changed**: {N}
285
336
 
337
+ ### Deploy Train State
338
+ **Train PR**: #{TRAIN_PR_NUMBER} (SHA: {TRAIN_PR_SHA}, opened: {TRAIN_PR_CREATED})
339
+ **Status**: {TRAIN_STATUS}
340
+ {If HELD: "**Held by**: {count} open finding(s) — fix and push to unblock:\n{HELD_BY}"}
341
+ {If CLEAR: "**Ready to merge**: no open findings on the train PR"}
342
+ {If NO_TRAIN: "No open staging→main PR — run /review-pr-staging to open one"}
343
+ **Queued commits**: {QUEUED_COMMITS} (commits in staging not yet in main)
344
+
286
345
  ### Services Affected
287
346
  | Service | Files Changed | Rebuild Required |
288
347
  |---------|---------------|-----------------|
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Run the ABC benchmark — reference URL → design-blind brief → render arms A/B/C → blind judge → scorecard with win-rates over n runs
3
3
  argument-hint: [<brief-name>|all] [--n <runs>] [--corpus-version <ver>]
4
+ install: internal
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -21,6 +22,10 @@ live there — this command is the executable workflow over that methodology.
21
22
  **No application runtime.** ForgeDock is a set of command specs. This command is a step-by-step procedure an
22
23
  agent executes; the only executable helper is the deterministic aggregator `scripts/bench-scorecard.mjs`.
23
24
 
25
+ **NEVER use plan mode (EnterPlanMode).**
26
+
27
+ <!-- FORGE:SPEC_LOADED — design-bench.md loaded and active. Agent is bound by this spec. -->
28
+
24
29
  ---
25
30
 
26
31
  ## The three arms (one variable)
@@ -127,7 +132,7 @@ The aggregator (see `scripts/bench-scorecard.mjs`):
127
132
  generated arm is a judge defect, not a harness win — treat those runs as suspect.
128
133
 
129
134
  Post the result as a `FORGE:BENCH_SCORECARD` annotation (registered in
130
- [`docs/FORGE-PROTOCOL.md`](../docs/FORGE-PROTOCOL.md)) on the tracking issue:
135
+ [`docs/spec/forge-protocol-v1.md`](../docs/spec/forge-protocol-v1.md)) on the tracking issue:
131
136
 
132
137
  ```bash
133
138
  gh issue comment <ISSUE> --body "<!-- FORGE:BENCH_SCORECARD -->
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Render a design from its FORGE:DESIGN_SPEC, critique the rendered pixels against the perceptual negatives, and iterate until it passes or the budget is spent — the missing reward signal.
3
3
  argument-hint: [<issue-number>|<spec-path>] [--max-iters <n>] [--viewports desktop,mobile]
4
+ install: internal
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -81,7 +82,7 @@ real reference*. They must never be the same judge. This is also distinct from t
81
82
 
82
83
  ## `FORGE:CRITIQUE` annotation
83
84
 
84
- Registered in [FORGE-PROTOCOL](../docs/FORGE-PROTOCOL.md). One per iteration, so the improvement trajectory is an
85
+ Registered in [FORGE Annotation Protocol](../docs/spec/forge-protocol-v1.md). One per iteration, so the improvement trajectory is an
85
86
  auditable artifact:
86
87
 
87
88
  ```markdown
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Route a design GitHub issue through the UI Taste Harness — investigate → architect → implement → critique loop → user-feedback loop → close — accumulating FORGE:DESIGN_* annotations and driving the design:* label state machine to design:shipped.
3
3
  argument-hint: <issue-number> | <brief-name>
4
+ install: internal
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Trace a failed or stalled pipeline run — identify which FORGE annotation is missing or malformed, diagnose the failure point, and suggest specific remediation steps
3
3
  argument-hint: [issue number] [--repo prefix]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /diagnose — Pipeline Failure Tracer
@@ -9,7 +10,7 @@ argument-hint: [issue number] [--repo prefix]
9
10
 
10
11
  **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
11
12
 
12
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
13
+ **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.
13
14
 
14
15
  You are the pipeline's diagnostic layer. Given a single GitHub issue number, you reconstruct the full FORGE annotation chain for that pipeline run, identify the exact failure point, and suggest specific remediation steps. This command is **read-only** — it never mutates GitHub state.
15
16
 
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Plain-English breakdown of what happened on a GitHub issue — translates FORGE pipeline annotations into a human-readable narrative for teammates and PMs
3
3
  argument-hint: <issue number or PR#N> [--repo prefix]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /explain — FORGE Annotation Translator
@@ -9,7 +10,7 @@ argument-hint: <issue number or PR#N> [--repo prefix]
9
10
 
10
11
  You translate the FORGE pipeline's machine-readable annotations on a GitHub issue or PR into a clear, plain-English narrative that anyone can understand — no pipeline knowledge required. This is a read-only command: it never writes to GitHub, never changes labels, and never modifies any state.
11
12
 
12
- **Agent model policy**: Default `model: "sonnet"`. If Sonnet is rate-limited, fall back to `model: "opus"`.
13
+ **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.
13
14
  **NEVER use plan mode (EnterPlanMode).**
14
15
 
15
16
  ---
@@ -1,13 +1,14 @@
1
1
  ---
2
2
  description: Track command sizes, detect bloat, compare against baselines and thresholds
3
- argument-hint: [diff | baseline | full]
3
+ argument-hint: [diff | baseline | full | cost]
4
+ install: internal
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
7
8
 
8
9
  # /forge-stats — Prompt Bloat Tracker
9
10
 
10
- **Input**: $ARGUMENTS (default: `diff`)
11
+ **Input**: $ARGUMENTS (default: `diff`; modes: `diff`, `baseline`, `full`, `cost`)
11
12
 
12
13
  Tracks the size of every Forge command file over time. Detects bloat by comparing current sizes against the git-tracked baseline and per-command thresholds.
13
14
 
@@ -193,3 +194,122 @@ If 3+ commands repeat the same instruction block (e.g., "how to create a worktre
193
194
 
194
195
  ### 4. Remove motivational padding
195
196
  Emojis, ALL CAPS warnings, "YOU MUST", "CRITICAL", "NO EXCEPTIONS" — these are noise. Sonnet follows clear instructions, not emphasis. Replace 5 lines of warnings with 1 line of instruction.
197
+
198
+ ---
199
+
200
+ ## Mode: `cost`
201
+
202
+ Report raw cost-per-issue, cost-per-stage, and cost-per-agent-tier by reading `FORGE:DECISION_RECORD` annotations from merged PRs. **Raw numbers only** — no trend dashboards, no automated regression-flagging, no visualization. Respects the open-core boundary defined in `devdocs/project/architecture.md` (trend analytics are a Platform value-add).
203
+
204
+ ```bash
205
+ cd "$FORGE_HOME"
206
+
207
+ CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
208
+ GH_REPO=$(yq e '.project.owner + "/" + .project.repo' "$CONFIG_FILE")
209
+
210
+ echo "=== Forge Cost Report — $(date +%Y-%m-%d) ==="
211
+ echo "Repo: $GH_REPO"
212
+ echo ""
213
+
214
+ # Fetch all merged PRs (last 50) and extract their FORGE:DECISION_RECORD JSON blocks
215
+ RECORDS=$(gh pr list -R "$GH_REPO" --state merged --limit 50 --json number \
216
+ --jq '.[].number' 2>/dev/null | while read pr; do
217
+ gh api "repos/$GH_REPO/issues/$pr/comments" \
218
+ --jq '.[] | select(.body | contains("FORGE:DECISION_RECORD")) | .body' 2>/dev/null
219
+ done)
220
+
221
+ if [ -z "$RECORDS" ]; then
222
+ echo "No FORGE:DECISION_RECORD annotations found in the last 50 merged PRs."
223
+ echo "(Older issues predate the cost block — no data to report.)"
224
+ exit 0
225
+ fi
226
+
227
+ # Extract cost blocks via Python (handles missing cost block gracefully)
228
+ echo "$RECORDS" | python3 - <<'PYEOF'
229
+ import sys, re, json
230
+
231
+ records = []
232
+ for block in sys.stdin.read().split("<!-- FORGE:DECISION_RECORD -->"):
233
+ m = re.search(r'```json\s*(\{.*?\})\s*```', block, re.DOTALL)
234
+ if not m:
235
+ continue
236
+ try:
237
+ data = json.loads(m.group(1))
238
+ except json.JSONDecodeError:
239
+ continue
240
+ records.append(data)
241
+
242
+ if not records:
243
+ print("No parseable FORGE:DECISION_RECORD JSON found.")
244
+ sys.exit(0)
245
+
246
+ print(f"Parsed {len(records)} FORGE:DECISION_RECORD annotation(s).\n")
247
+
248
+ has_cost = [r for r in records if r.get("cost")]
249
+ no_cost = [r for r in records if not r.get("cost")]
250
+
251
+ print(f" With cost block : {len(has_cost)}")
252
+ print(f" Without cost block: {len(no_cost)} (older annotations — no data)")
253
+ print()
254
+
255
+ if not has_cost:
256
+ print("No cost data available. Cost blocks are written starting with #1296.")
257
+ sys.exit(0)
258
+
259
+ # Per-issue raw cost
260
+ print("--- Cost Per Issue ---")
261
+ print(f"{'Issue':<10} {'PR':<8} {'Total ($)':<12} {'Stages'}")
262
+ print(f"{'-----':<10} {'--':<8} {'---------':<12} {'------'}")
263
+ for r in sorted(has_cost, key=lambda x: x.get("issue", 0)):
264
+ cost = r.get("cost", {})
265
+ total = cost.get("total_usd", "n/a")
266
+ stages = cost.get("stages", {})
267
+ stage_str = ", ".join(f"{k}: ${v}" for k, v in stages.items()) if stages else "n/a"
268
+ print(f" #{r.get('issue','?'):<8} #{r.get('pr','?'):<6} {str(total):<12} {stage_str}")
269
+
270
+ print()
271
+
272
+ # Per-stage aggregate
273
+ stage_totals = {}
274
+ for r in has_cost:
275
+ for stage, val in (r.get("cost", {}).get("stages") or {}).items():
276
+ try:
277
+ stage_totals[stage] = stage_totals.get(stage, 0.0) + float(val)
278
+ except (TypeError, ValueError):
279
+ pass
280
+
281
+ if stage_totals:
282
+ print("--- Cost Per Stage (aggregate) ---")
283
+ for stage, total in sorted(stage_totals.items()):
284
+ print(f" {stage:<20}: ${total:.4f}")
285
+ print()
286
+
287
+ # Per-agent-tier aggregate
288
+ tier_totals = {}
289
+ for r in has_cost:
290
+ for tier, val in (r.get("cost", {}).get("agent_tiers") or {}).items():
291
+ try:
292
+ tier_totals[tier] = tier_totals.get(tier, 0.0) + float(val)
293
+ except (TypeError, ValueError):
294
+ pass
295
+
296
+ if tier_totals:
297
+ print("--- Cost Per Agent Tier (aggregate) ---")
298
+ for tier, total in sorted(tier_totals.items()):
299
+ print(f" {tier:<20}: ${total:.4f}")
300
+ print()
301
+
302
+ # Summary
303
+ if has_cost:
304
+ totals = [float(r["cost"]["total_usd"]) for r in has_cost if r.get("cost", {}).get("total_usd") not in (None, "unavailable")]
305
+ if totals:
306
+ print(f"Issues with cost data: {len(totals)}")
307
+ print(f" Total cost (window) : ${sum(totals):.4f}")
308
+ print(f" Average per issue : ${sum(totals)/len(totals):.4f}")
309
+ print(f" Min / Max : ${min(totals):.4f} / ${max(totals):.4f}")
310
+ PYEOF
311
+ ```
312
+
313
+ **Scope constraint**: This mode reports raw numbers sourced from `FORGE:DECISION_RECORD` annotations only. No new data source is invented. Trend visualization, regression-flagging, and alerting logic are Platform features — do not add them here. If a cost block is absent (older annotations predating #1296), report "no data" rather than erroring.
314
+
315
+ <!-- Added: forge#1297 -->
@@ -11,7 +11,7 @@ argument-hint: [--preserve | --interactive | --section <name>]
11
11
 
12
12
  You complete the `forge.yaml` configuration that `npx forgedock init` started. The CLI generates required sections (project, paths, branches) from auto-detection. Your job is to scan the codebase, query GitHub APIs, and produce a complete `forge.yaml` with every applicable optional section filled — using detected values directly, without asking for confirmation.
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
16
 
17
17
  ---
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  description: "Run a GEO audit — check AI referral traffic, page compliance, and auto-create improvement issues"
3
+ install: extras
3
4
  ---
4
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
5
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -12,6 +13,8 @@ You are the GEO (Generative Engine Optimization) auditor. Pull AI referral data
12
13
 
13
14
  **NEVER use plan mode (EnterPlanMode)** — it breaks execution context.
14
15
 
16
+ <!-- FORGE:SPEC_LOADED — geo-audit.md loaded and active. Agent is bound by this spec. -->
17
+
15
18
  ---
16
19
 
17
20
  ## Phase 0: Load Config
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Coordinate P0 incident response — hotfix validation, timeline reconstruction, and post-incident analysis
3
3
  argument-hint: [issue number | "active" | "postmortem {issue}"]
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: [issue number | "active" | "postmortem {issue}"]
15
16
 
16
17
  You are the pipeline's incident response coordinator. When production goes down or a critical bug surfaces, this command orchestrates the response: validates the hotfix before deploy, reconstructs the incident timeline, and produces a post-incident analysis.
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/issue.md CHANGED
@@ -11,7 +11,7 @@ argument-hint: [description of the problem or feature]
11
11
 
12
12
  You create GitHub issues with the exact structure the `/work-on` pipeline expects. Every issue you create must give the investigation agent enough context to find the right files on the first pass — no vague descriptions, no missing domains, no ambiguous scope.
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
16
 
17
17
  ---
@@ -133,8 +133,28 @@ List every file that the fix/feature will need to touch. Be thorough:
133
133
 
134
134
  ### 2D: Check for duplicates
135
135
 
136
+ Run the deterministic dedup script first (authoritative check), then fall back to an LLM pass if the script produces no result:
137
+
138
+ ```bash
139
+ # Authoritative deterministic check — uses token overlap algorithm (see scripts/issue-dedup.sh)
140
+ DEDUP_RESULT=$(scripts/issue-dedup.sh "{PROPOSED_TITLE}" {GH_FLAG} 2>&1)
141
+ DEDUP_EXIT=$?
142
+
143
+ if [ "$DEDUP_EXIT" -eq 1 ]; then
144
+ echo "Near-duplicate detected: $DEDUP_RESULT"
145
+ echo "Existing issue found — do NOT create a new one."
146
+ # STOP here and report to user (see handling rules below)
147
+ elif [ "$DEDUP_EXIT" -eq 2 ]; then
148
+ echo "Dedup check usage error: $DEDUP_RESULT"
149
+ echo "Do NOT proceed to issue creation — fix the invocation and retry."
150
+ # STOP here — do not fall through to gh issue create
151
+ fi
152
+ ```
153
+
154
+ If the script exits 0 (no match found), also run an LLM-side search as a fallback:
155
+
136
156
  ```bash
137
- # Search for existing issues with similar scope
157
+ # LLM fallback — broader semantic search for issues the token algorithm may miss
138
158
  gh issue list {GH_FLAG} --state open --limit 20 --search "{key_terms}" --json number,title,labels --jq '.[] | "#\(.number) [\(.labels | map(.name) | join(","))] \(.title)"'
139
159
 
140
160
  # Also check recently closed issues (might be a regression)
@@ -144,6 +164,7 @@ gh issue list {GH_FLAG} --state closed --limit 10 --search "{key_terms}" --json
144
164
  If a duplicate exists:
145
165
  - **Open duplicate found**: Tell the user. Do NOT create the issue. Show the existing issue number.
146
166
  - **Closed duplicate found (regression)**: Create the issue but reference the prior issue in the body: "Regression of #{N}."
167
+ - **User wants to override**: Pass `--force` to the dedup script — this is an explicit human override path. Agents MUST NOT pass `--force` without user authorization. <!-- Added: forge#1335 -->
147
168
 
148
169
  ### 2E: Check for milestone context
149
170
 
@@ -495,7 +516,7 @@ Create all {N} issues? (yes / adjust #N / cancel)
495
516
 
496
517
  | Bad Issue | Why It Fails | Good Version |
497
518
  |-----------|-------------|-------------|
498
- | "Fix docker mount" | Which compose file? Which mount? | "fix: `.gemini` volume mount in docker-compose.prod.yml missing rw flag" |
519
+ | "Fix docker mount" | Which compose file? Which mount? | "fix: `logs` volume in docker-compose.yml missing `rw` flag — container writes fail at runtime" |
499
520
  | "Update billing" | What about billing? What's broken? | "fix: payment_processor.charge() raises ZeroDivisionError when amount == 0" |
500
521
  | "Investigate performance" | Investigate what? Where? | "investigate: API p95 latency doubled since last deploy — trace hot paths in job processing routers" |
501
522
  | No affected files listed | Investigator guesses wrong files | List every file with what needs to change |
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Create, manage, and ship milestones — the top-level planning layer for feature development
3
3
  argument-hint: [create <name> | status | ship <slug> | sync <slug>]
4
+ install: extras
4
5
  ---
5
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
7
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -13,7 +14,12 @@ Milestones are the top-level planning unit. They group related issues into a shi
13
14
 
14
15
  **Hierarchy**: Milestone → Issues → Sub-issues (optional decomposition)
15
16
 
16
- **You have access to ALL tools** — Task tool, Skill tool, sub-agents, everything.
17
+ **NEVER use plan mode (EnterPlanMode).**
18
+ **NEVER use the Agent tool for issue work** — milestone dispatches issue work via `Skill(skill="work-on", ...)` only. The Agent tool bypasses the Skill pipeline's label state machine, FORGE annotations, and structured review. The Agent tool may be used only for coordination tasks within milestone planning itself (e.g., parallel issue list queries) — never for /work-on sub-dispatch.
19
+
20
+ <!-- FORGE:SPEC_LOADED — milestone.md loaded and active. Agent is bound by this spec. -->
21
+
22
+ **You have access to Task, Skill, and Bash tools** for milestone coordination.
17
23
 
18
24
  ## Config Resolution
19
25
 
@@ -498,18 +504,29 @@ ISSUE_EOF
498
504
  fi
499
505
  ```
500
506
 
501
- ### Step 3: Create shipping PR
507
+ ### Step 3: Create or update shipping PR (merge-train mechanics)
508
+
509
+ <!-- Added: forge#1327 (update-in-place), extended: forge#1332 (merge-train) -->
510
+
511
+ **Merge-train policy**: One staging→main PR stays open per deploy cycle. When a milestone ships to staging, it joins the deploy train as a candidate. The train PR is updated in place when fixes are pushed — it is NEVER closed and recreated. Dead-PR chains are eliminated: fix → push → re-request review on the same PR.
512
+
513
+ **Update-in-place policy**: Before creating a new PR, check whether an open shipping PR already exists for this milestone. If one does, push the updated milestone branch and re-request review on the existing PR — do NOT close and recreate. Closing-and-recreating is pure churn: it burns a new PR number, loses review history, and contributes to a low staging→main pass rate. The correct flow is: fix → push → re-request review on the same PR.
502
514
 
503
515
  ```bash
504
- # Get the full diff summary (computed after Step 2.5 rebase, so it reflects the final state)
505
- DIFF_STATS=$(git diff origin/{STAGING_BRANCH}...origin/milestone/{slug} --stat)
506
- COMMIT_LOG=$(git log origin/{STAGING_BRANCH}..origin/milestone/{slug} --oneline)
507
-
508
- gh pr create {GH_FLAG} \
509
- --base {STAGING_BRANCH} \
510
- --head milestone/{slug} \
511
- --title "Ship: {MILESTONE_TITLE}" \
512
- --body "$(cat <<'PR_EOF'
516
+ # Check for an existing open shipping PR for this milestone
517
+ EXISTING_PR=$(gh pr list {GH_FLAG} --head "milestone/{slug}" --base "{STAGING_BRANCH}" --state open \
518
+ --json number,url --jq '.[0] | "\(.number)|\(.url)"' 2>/dev/null)
519
+
520
+ if [ -n "$EXISTING_PR" ]; then
521
+ PR_NUMBER=$(echo "$EXISTING_PR" | cut -d'|' -f1)
522
+ PR_URL=$(echo "$EXISTING_PR" | cut -d'|' -f2)
523
+ echo "Existing open shipping PR #$PR_NUMBER found — updating in place (not recreating)."
524
+
525
+ # Update PR body to reflect latest diff state after fixes were pushed
526
+ DIFF_STATS=$(git diff origin/{STAGING_BRANCH}...origin/milestone/{slug} --stat)
527
+ COMMIT_LOG=$(git log origin/{STAGING_BRANCH}..origin/milestone/{slug} --oneline)
528
+ gh pr edit "$PR_NUMBER" {GH_FLAG} --body "$(cat <<'PR_EOF'
529
+ <!-- FORGE:TRAIN_CANDIDATE milestone={slug} -->
513
530
  ## Milestone: {MILESTONE_TITLE}
514
531
 
515
532
  {MILESTONE_DESCRIPTION}
@@ -529,7 +546,43 @@ gh pr create {GH_FLAG} \
529
546
  ## Commits
530
547
  {COMMIT_LOG}
531
548
  PR_EOF
532
- )"
549
+ )"
550
+
551
+ # Re-request review so reviewers are notified of the updated push
552
+ gh pr review "$PR_NUMBER" {GH_FLAG} --request-review 2>/dev/null || true
553
+ echo "PR #$PR_NUMBER updated and review re-requested."
554
+ else
555
+ # No open PR exists — create a new one
556
+ DIFF_STATS=$(git diff origin/{STAGING_BRANCH}...origin/milestone/{slug} --stat)
557
+ COMMIT_LOG=$(git log origin/{STAGING_BRANCH}..origin/milestone/{slug} --oneline)
558
+
559
+ gh pr create {GH_FLAG} \
560
+ --base {STAGING_BRANCH} \
561
+ --head milestone/{slug} \
562
+ --title "Ship: {MILESTONE_TITLE}" \
563
+ --body "$(cat <<'PR_EOF'
564
+ <!-- FORGE:TRAIN_CANDIDATE milestone={slug} -->
565
+ ## Milestone: {MILESTONE_TITLE}
566
+
567
+ {MILESTONE_DESCRIPTION}
568
+
569
+ ## Issues Included
570
+ {list of all closed issues in this milestone with PR references}
571
+
572
+ ## Hunk-Loss Audit
573
+ {If Step 2.5 rebase ran: "✓ Rebase completed — {AT_RISK_COUNT} at-risk staging-branch hunks absorbed into milestone branch before this PR was created. All staging content is preserved."}
574
+ {If Step 2.5 found no at-risk hunks: "✓ Clean — no at-risk staging-branch hunks detected. Safe to merge."}
575
+
576
+ > ⚠ **IMPORTANT: Merge this PR using a MERGE COMMIT, not squash.** Squash-merging a milestone PR can silently drop staging-only hunks in files the milestone touches. Use the "Create a merge commit" option in the GitHub UI, or `gh pr merge {PR_NUMBER} --merge`.
577
+
578
+ ## Diff Summary
579
+ {DIFF_STATS}
580
+
581
+ ## Commits
582
+ {COMMIT_LOG}
583
+ PR_EOF
584
+ )"
585
+ fi
533
586
  ```
534
587
 
535
588
  ### Step 4: Run staging review
@@ -540,6 +593,16 @@ Use the `/review-pr` skill to review the shipping PR. This is a comprehensive re
540
593
  Skill(skill="review-pr", args="{PR_NUMBER}")
541
594
  ```
542
595
 
596
+ **If the review returns blocking findings (FINDINGS, not PASSED)**:
597
+ - Do NOT close the PR.
598
+ - Do NOT restart from Step 1.
599
+ - Fix the blockers on `milestone/{slug}`, push the commits, then re-invoke review on the same PR:
600
+ ```
601
+ Skill(skill="review-pr", args="{PR_NUMBER}")
602
+ ```
603
+ - Step 3 will detect the open PR on the next `/milestone ship {slug}` call and update it in place — the same PR number is preserved, review history is retained, and the reviewer is re-notified.
604
+ - This eliminates the close-and-recreate churn that inflates the failed-PR count and lowers the staging→main pass rate. <!-- Added: forge#1328 -->
605
+
543
606
  ### Step 5: Report — PR is ready for user to merge
544
607
 
545
608
  ```
@@ -572,6 +635,8 @@ Milestone stays open. Issues remain assigned. Branch milestone/{slug} preserved.
572
635
  Run /milestone ship {slug} again when the milestone is ready for another shipping attempt.
573
636
  ```
574
637
 
638
+ **When the staging review returns blockers (FINDINGS, not PASSED)**: do NOT close the PR. Fix the blockers on `milestone/{slug}`, push the fixes, then re-run `/milestone ship {slug}`. Step 3 will detect the open PR and update it in place — the same PR number is preserved, review history is retained, and the reviewer is re-notified. This eliminates the close-and-recreate churn that inflates the failed-PR count and lowers the staging→main pass rate. <!-- Added: forge#1327 -->
639
+
575
640
  **If the PR merged successfully**, run the following:
576
641
 
577
642
  ```bash
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: Analyze this repo and generate per-repo adaptive scripts from learned patterns, git history, and existing configuration
3
3
  argument-hint: [--dry-run | --force | --no-registry]
4
+ install: extras
4
5
  ---
5
6
 
6
7
  # /optimize — Per-Repo Adaptive Script Generation
@@ -9,7 +10,7 @@ argument-hint: [--dry-run | --force | --no-registry]
9
10
 
10
11
  Proactively analyze the current repository and generate `.forgedock/scripts/` entries from `forge.yaml → learned:`, git commit history, and pipeline annotations — without waiting for a correction event. This is the proactive half of the learning loop; reactive capture happens in `/work-on` Phase 1D.
11
12
 
12
- **Agent model policy**: Default `model: "sonnet"`. Fallback: `model: "opus"` if Sonnet is rate-limited.
13
+ **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.
13
14
  **NEVER use plan mode (EnterPlanMode).**
14
15
 
15
16
  ---