forgedock 1.1.11 → 1.2.0

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 (73) hide show
  1. package/README.md +1 -1
  2. package/bin/cli-spawn-shared.mjs +25 -0
  3. package/bin/engine-cli.mjs +22 -1
  4. package/bin/engine.mjs +46 -4
  5. package/bin/forgedock.mjs +87 -16
  6. package/bin/hooks/pre-tool-use.mjs +331 -10
  7. package/bin/init-enrich-api.mjs +12 -4
  8. package/bin/init-enrich-cli.mjs +328 -0
  9. package/bin/init-enrich.mjs +137 -0
  10. package/bin/journey.mjs +13 -4
  11. package/bin/runner.mjs +653 -10
  12. package/commands/adopt.md +1 -1
  13. package/commands/analytics.md +10 -7
  14. package/commands/audit-agents.md +29 -6
  15. package/commands/audit.md +9 -20
  16. package/commands/autopilot.md +52 -78
  17. package/commands/changelog.md +1 -1
  18. package/commands/ci-audit.md +19 -10
  19. package/commands/cleanup.md +1 -1
  20. package/commands/compat-audit.md +1 -1
  21. package/commands/deploy-info.md +1 -1
  22. package/commands/deploy-pr.md +1 -1
  23. package/commands/design-bench.md +1 -1
  24. package/commands/design-render-critique-loop.md +1 -1
  25. package/commands/diagnose.md +1 -1
  26. package/commands/forge-stats.md +1 -1
  27. package/commands/forgedock-init.md +1 -1
  28. package/commands/geo-audit.md +9 -6
  29. package/commands/incident-response.md +15 -5
  30. package/commands/issue.md +298 -15
  31. package/commands/milestone.md +45 -18
  32. package/commands/optimize.md +1 -1
  33. package/commands/orchestrate/phase-1-resolve.md +20 -5
  34. package/commands/orchestrate/phase-4-execution.md +6 -1
  35. package/commands/orchestrate/phase-5-cleanup.md +43 -2
  36. package/commands/orchestrate/phase-6-report.md +1 -0
  37. package/commands/orchestrate.md +1 -1
  38. package/commands/pipeline-health/phase-4-proposals.md +40 -10
  39. package/commands/pipeline-health/phase-5-report.md +140 -13
  40. package/commands/pipeline-health.md +1 -1
  41. package/commands/pipeline-resume.md +1 -1
  42. package/commands/pipeline-status.md +1 -1
  43. package/commands/qa-sweep.md +10 -4
  44. package/commands/recover-orphans.md +1 -1
  45. package/commands/review-pr-agents/protocols.md +4 -0
  46. package/commands/review-pr-agents.md +7 -4
  47. package/commands/review-pr-staging.md +44 -15
  48. package/commands/review-pr.md +73 -28
  49. package/commands/rollback.md +15 -5
  50. package/commands/security-audit.md +14 -11
  51. package/commands/signal-planner.md +32 -12
  52. package/commands/spec-doctor.md +1 -1
  53. package/commands/sync-ecosystem.md +54 -11
  54. package/commands/test-gate.md +49 -11
  55. package/commands/validate.md +16 -5
  56. package/commands/work-on/build/architect.md +1 -1
  57. package/commands/work-on/build/context.md +1 -1
  58. package/commands/work-on/build/implement.md +2 -2
  59. package/commands/work-on/build/validate.md +3 -1
  60. package/commands/work-on/build.md +1 -1
  61. package/commands/work-on/close.md +1 -1
  62. package/commands/work-on/decompose.md +27 -24
  63. package/commands/work-on/investigate.md +2 -2
  64. package/commands/work-on/remediate.md +1 -1
  65. package/commands/work-on/review.md +5 -3
  66. package/commands/work-on-monolithic.md +1 -1
  67. package/commands/work-on.md +28 -7
  68. package/docs/CI.md +18 -0
  69. package/docs/CONFIG.md +5 -2
  70. package/docs/site/annotations-explained.md +2 -2
  71. package/docs/site/command-reference.md +21 -0
  72. package/docs/spec/review-protocol.md +6 -0
  73. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Independently verify if a reported issue is actually a problem before making code changes.
3
- argument-hint: [issue description or #number]
3
+ argument-hint: "[issue description or #number]"
4
4
  install: extras
5
5
  ---
6
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
@@ -91,10 +91,17 @@ If CONFIRMED — recommended next step:
91
91
  Root cause: [one sentence]
92
92
  Fix approach: [one sentence]
93
93
  Create issue:
94
+ Route through the `/issue` create-hook's programmatic invocation contract (see `commands/issue.md` § "Programmatic Invocation Contract") instead of calling the raw issue-creation command directly — this gets dedup (Phase 2D) and body validation (Phase 3F) for free:
95
+
94
96
  ```bash
95
- gh issue create --title "fix: [concise description of the confirmed bug]" \
96
- --label "[priority],[bug|enhancement]" \
97
- --body "$(cat <<'BODY_EOF'
97
+ VALIDATE_ISSUE_TITLE="fix: [concise description of the confirmed bug]"
98
+ # Defense-in-depth: /issue's arg tokenizer (commands/issue.md, forge#2094) uses
99
+ # an xargs-based tokenizer that never expands backtick/$(...) substitution, so
100
+ # this is no longer required for safety — but strip it anyway so the raw title
101
+ # stays readable if it round-trips through any other eval-based consumer.
102
+ VALIDATE_ISSUE_TITLE=$(printf '%s' "$VALIDATE_ISSUE_TITLE" | tr '`' "'" | sed 's/\$(/$ (/g')
103
+ VALIDATE_ISSUE_BODY_FILE=$(mktemp)
104
+ cat <<'BODY_EOF' > "$VALIDATE_ISSUE_BODY_FILE"
98
105
  ## Problem
99
106
 
100
107
  [1-3 sentences: what the validation confirmed is wrong. Specific and concrete.]
@@ -123,7 +130,11 @@ Validated by \`/validate\` on [DATE]. Confidence: [High|Medium|Low].
123
130
  - [source]: [finding]
124
131
  - [source]: [finding]
125
132
  BODY_EOF
126
- )"
133
+
134
+ # [priority] and [bug|enhancement] are two separate labels — passed as repeated --label flags,
135
+ # never comma-joined (the /issue programmatic contract's --label is repeatable, not CSV).
136
+ Skill(skill="issue", args="--title \"$VALIDATE_ISSUE_TITLE\" --body-file \"$VALIDATE_ISSUE_BODY_FILE\" --label \"[priority]\" --label \"[bug|enhancement]\"")
137
+ rm -f "$VALIDATE_ISSUE_BODY_FILE"
127
138
  ```
128
139
 
129
140
  If NOT A PROBLEM — why the report was wrong:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Pre-implementation architecture planning — traces ALL affected code paths and produces an ordered implementation plan before any code is written
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--files AFFECTED_FILES]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--files AFFECTED_FILES]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Pre-implementation context gathering — surfaces historical findings, bug patterns, and related code paths before the builder writes any code
3
- argument-hint: [issue number] [affected_files...] [--functions function_names...]
3
+ argument-hint: "[issue number] [affected_files...] [--functions function_names...]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Implementation agent — writes code, makes commits, posts builder comment
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -102,7 +102,7 @@ Extract from contract:
102
102
  | Refactor / Maintenance | Implement directly following contract deliverables |
103
103
  | Investigation | Spawn research agents, create GitHub issues for findings, skip to I5 |
104
104
 
105
- **Investigation task special case**: Research deeply, create GitHub issues for each finding using the Pipeline Issue Template (see `commands/issue.md` § "Pipeline Issue Template"). Each issue MUST include `## Problem`, `## Affected Files`, and `## Acceptance Criteria`. Use `gh issue create {GH_FLAG}` with a fully-structured body. Post a deliverables comment listing the created issues, close the original issue, return `IMPLEMENT_RESULT: status: INVESTIGATION_COMPLETE`.
105
+ **Investigation task special case**: Research deeply, create GitHub issues for each finding using the Pipeline Issue Template (see `commands/issue.md` § "Pipeline Issue Template"). Each issue MUST include `## Problem`, `## Affected Files`, and `## Acceptance Criteria`. Create each issue via the `/issue` create-hook's programmatic invocation contract (see `commands/issue.md` § "Programmatic Invocation Contract") — `Skill(skill="issue", args="--title \"...\" --body-file <path> --label ...")` — instead of calling the raw issue-creation command directly; this gets dedup and body validation for free. Post a deliverables comment listing the created issues, close the original issue, return `IMPLEMENT_RESULT: status: INVESTIGATION_COMPLETE`.
106
106
 
107
107
  ---
108
108
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Validation agent — quality gate loop, format/verify, proxy check, deploy check
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--files FILE1 FILE2...]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--files FILE1 FILE2...]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -304,6 +304,8 @@ Where `{SCOPE}` is the command or module scope from the contract (e.g. `work-on`
304
304
 
305
305
  This is the **only** commit for this build cycle. It replaces the old `git commit` that was previously in `implement.md` Phase I4. Do NOT create a separate commit for validation fixes — they are absorbed into this single commit.
306
306
 
307
+ **Attribution**: The commit message is exactly the conventional-commit line above — nothing more. Do NOT append a `Co-Authored-By: Claude` trailer, a `🤖 Generated with Claude Code` line, or any assistant-tool attribution. Pipeline output is ForgeDock-branded; the assistant signature must never enter the repo's commit history. (A PreToolUse guard hard-blocks it as a backstop — see `bin/hooks/pre-tool-use.mjs` Rule 5.)
308
+
307
309
  ### V5 Post-Commit Ancestry Audit (MANDATORY)
308
310
 
309
311
  After committing, run the ancestry audit to detect merge commits from unrelated branches before the branch is pushed:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Build subcommand — create worktree, post contract, sequence context/architect/implement/validate
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BASE]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BASE]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Close subcommand — update project board, final issue body, parent tracker, summary report, trajectory log
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--pr PR_NUMBER] [--base PR_BASE] [--branch BRANCH] [--worktree WORKTREE_PATH]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--pr PR_NUMBER] [--base PR_BASE] [--branch BRANCH] [--worktree WORKTREE_PATH]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Decompose subcommand — break a complex issue into ordered sub-issues, post FORGE:DECOMPOSED, stop
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -106,30 +106,14 @@ For each sub-issue, prepare:
106
106
 
107
107
  ## Phase D3: Create Sub-Issues
108
108
 
109
- For each sub-issue (in dependency order):
109
+ For each sub-issue (in dependency order), route creation through the `/issue` create-hook's programmatic invocation contract (`commands/issue.md` Programmatic Invocation Contract, added in #2085) instead of calling `gh issue create` directly. `/issue`'s Phase 2D runs the same `scripts/issue-dedup.sh` check this file used to run manually — the standalone pre-check below is removed; dedup is now enforced inside the create-hook on every call, with no bypass path. <!-- Changed: forge#2086 — route through /issue create-hook -->
110
110
 
111
- **Before creating each sub-issue, run the deterministic dedup check:** <!-- Added: forge#1335 -->
111
+ **Compose the sub-issue body to a temp file** (avoids quoting issues when passed as `--body-file`):
112
112
 
113
113
  ```bash
114
114
  SUB_TITLE="{fix|feat|refactor}: {SUB_ISSUE_TITLE}"
115
- DEDUP_RESULT=$(scripts/issue-dedup.sh "$SUB_TITLE" {GH_FLAG} 2>&1)
116
- DEDUP_EXIT=$?
117
- if [ "$DEDUP_EXIT" -eq 1 ]; then
118
- echo "DEDUP: Sub-issue near-duplicate detected — $DEDUP_RESULT"
119
- echo "Skipping creation. Comment on the existing issue instead."
120
- # Do NOT call gh issue create for this sub-issue
121
- elif [ "$DEDUP_EXIT" -eq 2 ]; then
122
- echo "DEDUP: Usage error — $DEDUP_RESULT"
123
- # Do NOT call gh issue create for this sub-issue — fix the invocation and retry
124
- fi
125
- ```
126
-
127
- Only call `gh issue create` when the dedup script exits 0 (no match):
128
-
129
- ```bash
130
- gh issue create {GH_FLAG} \
131
- --title "{fix|feat|refactor}: {SUB_ISSUE_TITLE}" \
132
- --body "$(cat <<'SUB_BODY_EOF'
115
+ SUB_BODY_FILE="$(mktemp)"
116
+ cat > "$SUB_BODY_FILE" <<'SUB_BODY_EOF'
133
117
  ## Problem
134
118
 
135
119
  {1-3 sentences: what this sub-issue specifically addresses. What's wrong or what needs to be built for this sub-task.}
@@ -155,11 +139,30 @@ Files that need changes:
155
139
  **Parent**: #{NUMBER}
156
140
  {If depends on another sub-issue: "**Depends on**: #{SUB_ISSUE_N} — {reason}"}
157
141
  SUB_BODY_EOF
158
- )" \
159
- --label "{PRIORITY_LABEL}" \
160
- --milestone "{MILESTONE_TITLE}"
161
142
  ```
162
143
 
144
+ **Invoke `/issue` in programmatic mode**:
145
+
146
+ ```
147
+ ISSUE_SKILL_OUTPUT=$(Skill(skill="issue", args="--title \"${SUB_TITLE}\" --body-file \"${SUB_BODY_FILE}\" --label \"{PRIORITY_LABEL}\" --milestone \"{MILESTONE_TITLE}\""))
148
+ ```
149
+
150
+ `/issue` runs Phase 2D dedup, Phase 3F body validation, then creates the issue (Phase 4) — no separate pre-check needed on this side.
151
+
152
+ **Extract the created sub-issue number from the Skill output** (see `commands/issue.md` Phase 4C/4E — it echoes `Created: {url}` and reports `**#{NUMBER}**: {title}`):
153
+
154
+ ```bash
155
+ # Match either the "Created: {url}" line (extract trailing /issues/N) or the "**#{NUMBER}**" bold report line.
156
+ SUB_NUMBER=$(echo "$ISSUE_SKILL_OUTPUT" | grep -oE 'issues/[0-9]+' | head -1 | grep -oE '[0-9]+')
157
+ [ -z "$SUB_NUMBER" ] && SUB_NUMBER=$(echo "$ISSUE_SKILL_OUTPUT" | grep -oE '\*\*#[0-9]+\*\*' | head -1 | grep -oE '[0-9]+')
158
+
159
+ if [ -z "$SUB_NUMBER" ]; then
160
+ echo "WARNING: /issue did not report a created issue number for sub-issue '${SUB_TITLE}' — likely a Phase 2D dedup STOP (near-duplicate found) or a usage error. Skipping this sub-issue: do not reference it in the parent tracker or in dependent sub-issue bodies. Review the Skill output above and, if a near-duplicate exists, comment on the existing issue instead."
161
+ fi
162
+ ```
163
+
164
+ If `SUB_NUMBER` is empty, treat this sub-issue as not created — do not add it to the parent tracker checklist (Phase D4) and do not reference it as a dependency in later sub-issues.
165
+
163
166
  **Append Prior Investigation section** (conditional — only if `GIST_URLS` from Phase D1.5 is non-empty):
164
167
 
165
168
  After creating each sub-issue, append the `## Prior Investigation` section containing all parent Gist URLs. This keeps the Gist references machine-readable for downstream agents.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Investigate a GitHub issue — validate it's real, determine root cause, post findings
3
- argument-hint: [issue number] [--repo {owner}/{repo}] [--gh-flag "-R {owner}/{repo}"]
3
+ argument-hint: "[issue number] [--repo {owner}/{repo}] [--gh-flag \"-R {owner}/{repo}\"]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -380,7 +380,7 @@ if [ "$ATTRIBUTION_ANNOTATION_LINK" = "true" ]; then
380
380
  ANNOTATION_LINK_FOOTER="
381
381
 
382
382
  ---
383
- *Pipeline powered by [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock)*"
383
+ *⚒️ Pipeline powered by [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock)*"
384
384
  fi
385
385
  ```
386
386
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Remediate subcommand — checkout a needs-human PR, fix review findings, re-review, and re-gate with a FORGE:REMEDIATION paper trail
3
- argument-hint: [PR number] [--issue N] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BASE]
3
+ argument-hint: "[PR number] [--issue N] [--repo GH_REPO] [--gh-flag GH_FLAG] [--base PR_BASE]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Review subcommand — push branch, create PR, invoke /review-pr with --auto-merge
3
- argument-hint: [issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH] [--base PR_BASE]
3
+ argument-hint: "[issue number] [--repo GH_REPO] [--gh-flag GH_FLAG] [--worktree PATH] [--branch BRANCH] [--base PR_BASE]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -159,7 +159,7 @@ ATTRIBUTION_PR_FOOTER=$(grep -A5 "^attribution:" forge.yaml 2>/dev/null | grep "
159
159
  If `ATTRIBUTION_PR_FOOTER` is `true`, append the following footer to the PR body (once — never duplicate on retries):
160
160
 
161
161
  ```
162
- > Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.
162
+ > ⚒️ Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.
163
163
  ```
164
164
 
165
165
  ### R2C: Create PR
@@ -188,13 +188,15 @@ Closes #{NUMBER}
188
188
  **Implementation branch**: \`{BRANCH}\`
189
189
  **Base**: \`{PR_BASE}\`
190
190
  {IF_ATTRIBUTION_PR_FOOTER_TRUE:
191
- > Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.}"
191
+ > ⚒️ Orchestrated with [ForgeDock](https://github.com/RapierCraftStudios/ForgeDock) — state, scheduling, review, and memory on GitHub.}"
192
192
  ```
193
193
 
194
194
  **Note**: `Closes #{NUMBER}` documents intent but does NOT auto-close for non-default-branch PRs. The close subcommand handles explicit closure after merge.
195
195
 
196
196
  **Attribution guard**: The footer line is appended once at PR creation. If the PR already exists (resume path), do NOT append the footer again — check the existing PR body first.
197
197
 
198
+ **No assistant attribution**: The PR body is exactly the sections above (plus the optional ForgeDock footer). Do NOT add a `🤖 Generated with Claude Code` line, a `Co-Authored-By: Claude` trailer, or any assistant-tool attribution — the pipeline is ForgeDock-branded. A PreToolUse guard hard-blocks it as a backstop (`bin/hooks/pre-tool-use.mjs` Rule 5).
199
+
198
200
  If PR creation fails because a PR already exists for this branch:
199
201
  ```bash
200
202
  gh pr list {GH_FLAG} --head {BRANCH} --json number,url --jq '.[0]'
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: "[BENCHMARK] Monolithic work-on — single-prompt pipeline with no Skill sub-phase boundaries"
3
- argument-hint: [issue number]
3
+ argument-hint: "[issue number]"
4
4
  install: internal
5
5
  ---
6
6
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Pick up a GitHub issue and run the full investigate-build-review-merge pipeline
3
- argument-hint: [issue number or "next" to pick highest priority]
3
+ argument-hint: "[issue number or \"next\" to pick highest priority]"
4
4
  ---
5
5
  <!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
6
6
  <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
@@ -926,10 +926,18 @@ For each sub-issue:
926
926
  - **Milestone**: same as parent
927
927
 
928
928
  ### 2C: Create sub-issues
929
+
930
+ Route through the `/issue` create-hook's programmatic invocation contract (see `commands/issue.md` § "Programmatic Invocation Contract") instead of calling the raw issue-creation command directly — this gets dedup (Phase 2D) and body validation (Phase 3F) for free on every decomposition-spawned sub-issue.
931
+
929
932
  ```bash
930
- gh issue create {GH_FLAG} \
931
- --title "{fix|feat|refactor}: {SUB_ISSUE_TITLE}" \
932
- --body "$(cat <<'SUB_BODY_EOF'
933
+ SUB_ISSUE_TITLE_FULL="{fix|feat|refactor}: {SUB_ISSUE_TITLE}"
934
+ # Defense-in-depth: /issue's arg tokenizer (commands/issue.md, forge#2094) uses
935
+ # an xargs-based tokenizer that never expands backtick/$(...) substitution, so
936
+ # this is no longer required for safety — but strip it anyway so the raw title
937
+ # stays readable if it round-trips through any other eval-based consumer.
938
+ SUB_ISSUE_TITLE_FULL=$(printf '%s' "$SUB_ISSUE_TITLE_FULL" | tr '`' "'" | sed 's/\$(/$ (/g')
939
+ SUB_ISSUE_BODY_FILE=$(mktemp)
940
+ cat <<'SUB_BODY_EOF' > "$SUB_ISSUE_BODY_FILE"
933
941
  ## Problem
934
942
 
935
943
  {1-3 sentences: what this sub-issue specifically addresses. What's wrong or what needs to be built.}
@@ -955,9 +963,22 @@ Files that need changes:
955
963
  **Parent**: #{NUMBER}
956
964
  {If depends on another sub-issue: "**Depends on**: #{SUB_ISSUE_N} — {reason}"}
957
965
  SUB_BODY_EOF
958
- )" \
959
- --label "{PRIORITY_LABEL}" \
960
- --milestone "{MILESTONE_TITLE}"
966
+
967
+ # --milestone is only passed when the parent has one (see Phase 2B — "Milestone: same as parent").
968
+ MILESTONE_ARG=""
969
+ [ -n "{MILESTONE_TITLE}" ] && MILESTONE_ARG="--milestone \"{MILESTONE_TITLE}\""
970
+ Skill(skill="issue", args="--title \"$SUB_ISSUE_TITLE_FULL\" --body-file \"$SUB_ISSUE_BODY_FILE\" --label \"{PRIORITY_LABEL}\" ${MILESTONE_ARG}")
971
+ rm -f "$SUB_ISSUE_BODY_FILE"
972
+
973
+ # /issue has no machine-readable return contract — resolve the created issue's number by
974
+ # exact-title search immediately after the call (used by Phase 2D's tracker checklist).
975
+ # Retry to absorb GitHub Search API indexing lag.
976
+ SUB_ISSUE_NUM=""
977
+ for _resolve_attempt in 1 2 3; do
978
+ SUB_ISSUE_NUM=$(gh issue list {GH_FLAG} --search "in:title \"${SUB_ISSUE_TITLE_FULL}\"" --state open --limit 1 --json number --jq '.[0].number // empty')
979
+ [ -n "$SUB_ISSUE_NUM" ] && break
980
+ sleep 2
981
+ done
961
982
  ```
962
983
 
963
984
  ### 2D: Update parent issue body
package/docs/CI.md CHANGED
@@ -128,6 +128,24 @@ This is not recommended without understanding the security implications.
128
128
 
129
129
  ---
130
130
 
131
+ ## `forgedock run` Execution Backend
132
+
133
+ This guide's `forgedock-review.yml` workflow invokes `/review-pr` directly via the `claude --print` CLI, so it always needs `ANTHROPIC_API_KEY` as shown above — the CLI itself authenticates against your Anthropic account.
134
+
135
+ Separately, `npx forgedock run <command>` (the standalone, non-Claude-Code command runner in `bin/runner.mjs`) has its own **backend selection**, independent of this CI workflow:
136
+
137
+ | Backend | When used | Credential needed |
138
+ |---------|-----------|--------------------|
139
+ | `cli` (via `--backend cli` or `FORGEDOCK_BACKEND=cli`) | Explicit, or auto-selected when a working `claude` CLI is detected on PATH | None — reuses the CLI's own authentication (Pro/Max OAuth or a CLI-managed key) |
140
+ | `api` (via `--backend api` or `FORGEDOCK_BACKEND=api`) | Explicit, or auto-selected fallback when `claude` is not detected | `ANTHROPIC_API_KEY` |
141
+ | `auto` (default) | No `--backend` / `FORGEDOCK_BACKEND` given | Prefers `cli`, falls back to `api` |
142
+
143
+ **When CI still needs `ANTHROPIC_API_KEY` for `forgedock run`**: CI runners generally do not have an interactively-authenticated `claude` CLI (no browser/OAuth flow available in a headless job), so `auto` detection will typically fall back to `api` there anyway. If your CI runner does install and log in the `claude` CLI (e.g. via a headless API-key-based login), you can force `--backend cli` to skip the SDK/API path entirely. Otherwise, keep `ANTHROPIC_API_KEY` configured as a repository secret (see Setup above) and either let `auto` fall back naturally or set `--backend api` / `FORGEDOCK_BACKEND=api` explicitly for a deterministic CI backend regardless of what happens to be on the runner's PATH.
144
+
145
+ `npx forgedock run <command> --dry-run` always reports which backend it resolved to, without making any network call or requiring a key either way.
146
+
147
+ ---
148
+
131
149
  ## Customization
132
150
 
133
151
  ### Skip review for certain PRs
package/docs/CONFIG.md CHANGED
@@ -29,9 +29,12 @@ echo "forge.yaml" >> .gitignore # if your credentials path is sensitive
29
29
  |----------|----------|
30
30
  | `FORGE_NO_MOTION=1` | Same effect as `--fast` — disables animation frames. Color is unaffected. |
31
31
  | `NO_COLOR=1` | Disables ANSI color output only. Motion is unaffected (monochrome choreography). |
32
+ | `FORGEDOCK_INIT_BACKEND=cli\|api\|none\|auto` | Overrides AI-enrichment backend selection for `init` (see below). Default `auto` (or unset) preserves the CLI-first ladder. |
32
33
  | Non-TTY / piped output (or `CI=1`) | Plain sequential log: no color **and** no animation. |
33
34
 
34
- The default (no flags) is the annotated review screen: detection runs, AI enrichment fills in what it can (when an API key is available), and you review the result on a single screen — Enter accepts everything, low-confidence fields are flagged with a `# TODO(forgedock:<field>)` comment if left unedited.
35
+ The default (no flags) is the annotated review screen: detection runs, AI enrichment fills in what it can — using a local, authenticated `claude` CLI when available, otherwise falling back to the Anthropic API when `ANTHROPIC_API_KEY` is set, otherwise skipped — and you review the result on a single screen — Enter accepts everything, low-confidence fields are flagged with a `# TODO(forgedock:<field>)` comment if left unedited.
36
+
37
+ If you have both a local `claude` CLI and `ANTHROPIC_API_KEY` set and want to pin one explicitly instead of letting `init` prefer the CLI, set `FORGEDOCK_INIT_BACKEND=api` (or `=cli`, or `=none` to skip enrichment entirely). This is independent of `FORGEDOCK_BACKEND`, which controls the separate `forgedock run` engine backend.
35
38
 
36
39
  ---
37
40
 
@@ -741,7 +744,7 @@ const draft = await detectConfig(process.cwd());
741
744
 
742
745
  Downstream consumers read `field.value` for the raw value and `field.confidence` to decide how to handle it:
743
746
 
744
- - **`init-enrich`** (AI enrichment): passes `low`- and `medium`-confidence fields to the AI backend to raise their confidence; leaves `high`-confidence fields untouched.
747
+ - **`init-enrich`** (AI enrichment): passes `low`- and `medium`-confidence fields to the selected AI backend (a local `claude` CLI when available, otherwise the Anthropic API with `ANTHROPIC_API_KEY`) to raise their confidence; leaves `high`-confidence fields untouched.
745
748
  - **`review-render`** (TUI review screen): shows each field with its source and why; highlights `low`-confidence fields with a `# TODO(forgedock:<field>)` annotation in the generated YAML.
746
749
 
747
750
  ---
@@ -57,10 +57,10 @@ ForgeDock can optionally append a small attribution line to pipeline-created PRs
57
57
  **`attribution.pr_footer: true`** — every pipeline-created PR ends with one muted footer:
58
58
 
59
59
  ```
60
- > Orchestrated with ForgeDock — state, scheduling, review, and memory on GitHub.
60
+ > ⚒️ Orchestrated with ForgeDock — state, scheduling, review, and memory on GitHub.
61
61
  ```
62
62
 
63
- **`attribution.annotation_link: true`** — visible (human-readable) annotation comments in the GitHub UI carry a small "Pipeline powered by ForgeDock" link at the end. Machine-readable `<!-- FORGE:... -->` HTML comments are never modified, regardless of this setting.
63
+ **`attribution.annotation_link: true`** — visible (human-readable) annotation comments in the GitHub UI carry a small "⚒️ Pipeline powered by ForgeDock" link at the end. Machine-readable `<!-- FORGE:... -->` HTML comments are never modified, regardless of this setting.
64
64
 
65
65
  Both keys default to disabled. The recommended configuration for public repos is to enable both; for private repos, leave both off.
66
66
 
@@ -91,6 +91,27 @@ Analyzes what a PR touches and spawns domain-specific review agents.
91
91
 
92
92
  ---
93
93
 
94
+ ### `/review-pr-staging`
95
+
96
+ **Staging review mode — deep review of a `staging → main` bundle before deploy.**
97
+
98
+ Purpose-built for the large, heterogeneous diffs a deploy bundle produces (1,000–10,000+ lines). Invoked by the orchestrator via `Skill("review-pr-staging", …)` or directly.
99
+
100
+ ```bash
101
+ /review-pr-staging staging # Review the staging → main bundle
102
+ /review-pr-staging 123 # Review a PR targeting main
103
+ /review-pr-staging staging:feature # Review a feature bundle into staging
104
+ ```
105
+
106
+ **What it does**:
107
+ - Handles large, diverse diffs with deep per-domain analysis and business-impact assessment
108
+ - Deep-diffs workflow siblings (e.g. `ci.yml` vs. `deploy-production.yml`) to catch shared-job drift that only surfaces at deploy time
109
+ - Produces a comprehensive verdict gating the deploy to `main`
110
+
111
+ *Companion to `/review-pr`, tuned for the deploy gate rather than a single feature PR.*
112
+
113
+ ---
114
+
94
115
  ### `/quality-gate`
95
116
 
96
117
  **Pre-commit quality checker.**
@@ -14,6 +14,12 @@ Do not duplicate these protocols in any other file. When updating either protoco
14
14
 
15
15
  ---
16
16
 
17
+ ## File Resolution Discipline
18
+
19
+ Pipeline agents MUST NOT use `find` (unbounded or filesystem-wide) to locate protocol files, persona templates, or verification scripts under any circumstances. If a `Read` or `bash` invocation of an expected pipeline file fails (e.g. because `$FORGE_HOME` is unset and the path degraded to a root-anchored form), that is never a reason to search the filesystem — it means the deterministic fallback chain the orchestrator already computed (`$FORGE_HOME` → `$REPO_PATH` → documented last-resort) was exhausted. Stop and report the failure (or fall through to the orchestrator's documented FATAL/hard-stop behavior — see `commands/review-pr.md` Phase 3C `TEMPLATE_BASE` guard) instead of improvising a `find /`-style search. A filesystem-wide `find` on an unset variable is the exact failure mode that produced runaway orphaned processes in production (see forge#1984, forge#2035). <!-- Added: forge#2035 -->
20
+
21
+ ---
22
+
17
23
  ## Evidence-Based Review Protocol (ALL Agents Follow)
18
24
 
19
25
  Every agent MUST follow this protocol:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgedock",
3
- "version": "1.1.11",
3
+ "version": "1.2.0",
4
4
  "description": "Autonomous dev pipeline for Claude Code. GitHub as institutional memory — every issue, PR, and annotation survives context resets and makes the next agent smarter.",
5
5
  "bin": {
6
6
  "forgedock": "bin/forgedock.mjs"