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.
- package/README.md +255 -211
- package/bin/batch-runner.mjs +339 -0
- package/bin/cinema.mjs +320 -0
- package/bin/demo.mjs +92 -7
- package/bin/engine/phases.mjs +168 -0
- package/bin/engine/projector.mjs +32 -0
- package/bin/engine/reconcile.mjs +11 -0
- package/bin/engine/runlog.mjs +79 -0
- package/bin/engine/state.mjs +32 -0
- package/bin/engine-cli.mjs +222 -0
- package/bin/engine.mjs +138 -0
- package/bin/forgedock.mjs +896 -1540
- package/bin/hooks/interactive-engine.mjs +509 -0
- package/bin/hooks/pre-tool-use.mjs +498 -0
- package/bin/hooks/subagent-stop-enforce.mjs +197 -0
- package/bin/journey.mjs +841 -0
- package/bin/registry.mjs +139 -0
- package/bin/report.mjs +447 -0
- package/bin/runner.mjs +136 -20
- package/bin/settings-hook.mjs +346 -0
- package/bin/tui.mjs +6 -3
- package/commands/adopt.md +4 -1
- package/commands/analytics.md +4 -1
- package/commands/audit-agents.md +110 -27
- package/commands/audit.md +20 -1
- package/commands/autopilot.md +84 -12
- package/commands/changelog.md +2 -1
- package/commands/ci-audit.md +2 -1
- package/commands/cleanup.md +161 -1
- package/commands/compat-audit.md +2 -1
- package/commands/deploy-info.md +63 -4
- package/commands/design-bench.md +6 -1
- package/commands/design-render-critique-loop.md +2 -1
- package/commands/design.md +1 -0
- package/commands/diagnose.md +2 -1
- package/commands/explain.md +2 -1
- package/commands/forge-stats.md +122 -2
- package/commands/forgedock-init.md +1 -1
- package/commands/geo-audit.md +3 -0
- package/commands/incident-response.md +2 -1
- package/commands/issue.md +24 -3
- package/commands/milestone.md +77 -12
- package/commands/optimize.md +2 -1
- package/commands/orchestrate/config.md +67 -0
- package/commands/orchestrate/phase-1-resolve.md +159 -0
- package/commands/orchestrate/phase-2-triage.md +126 -0
- package/commands/orchestrate/phase-2.5-synthesis.md +156 -0
- package/commands/orchestrate/phase-3-dependency.md +591 -0
- package/commands/orchestrate/phase-4-execution.md +962 -0
- package/commands/orchestrate/phase-5-cleanup.md +47 -0
- package/commands/orchestrate/phase-6-report.md +198 -0
- package/commands/orchestrate/safety.md +62 -0
- package/commands/orchestrate.md +25 -2027
- package/commands/pipeline-health/config.md +34 -0
- package/commands/pipeline-health/phase-1-context.md +180 -0
- package/commands/pipeline-health/phase-2-metrics.md +1729 -0
- package/commands/pipeline-health/phase-3-analyze.md +204 -0
- package/commands/pipeline-health/phase-4-proposals.md +117 -0
- package/commands/pipeline-health/phase-5-report.md +284 -0
- package/commands/pipeline-health/phase-6-summary.md +52 -0
- package/commands/pipeline-health.md +25 -2401
- package/commands/pipeline-resume.md +24 -1
- package/commands/pipeline-status.md +65 -0
- package/commands/qa-sweep.md +4 -1
- package/commands/quality-gate.md +326 -42
- package/commands/replay.md +2 -1
- package/commands/review-pr-agents/api.md +135 -0
- package/commands/review-pr-agents/auth.md +137 -0
- package/commands/review-pr-agents/billing.md +101 -0
- package/commands/review-pr-agents/concurrency.md +145 -0
- package/commands/review-pr-agents/database.md +103 -0
- package/commands/review-pr-agents/frontend.md +89 -0
- package/commands/review-pr-agents/infra.md +385 -0
- package/commands/review-pr-agents/protocols.md +185 -0
- package/commands/review-pr-agents/scraper.md +185 -0
- package/commands/review-pr-agents/security.md +406 -0
- package/commands/review-pr-agents.md +45 -1722
- package/commands/review-pr-staging.md +196 -40
- package/commands/review-pr.md +612 -56
- package/commands/rollback.md +2 -1
- package/commands/scope.md +2 -1
- package/commands/security-audit.md +2 -1
- package/commands/signal-planner.md +623 -0
- package/commands/sync-ecosystem.md +1 -0
- package/commands/test-gate.md +17 -1
- package/commands/validate.md +2 -1
- package/commands/work-on/build/architect.md +28 -0
- package/commands/work-on/build/context.md +2 -0
- package/commands/work-on/build/implement.md +19 -5
- package/commands/work-on/build/validate.md +62 -6
- package/commands/work-on/build.md +187 -30
- package/commands/work-on/close.md +132 -5
- package/commands/work-on/decompose.md +19 -1
- package/commands/work-on/investigate.md +117 -2
- package/commands/work-on/review.md +48 -4
- package/commands/work-on-monolithic.md +8 -2
- package/commands/work-on.md +247 -7
- package/docs/BRAND.md +16 -5
- package/docs/CI.md +2 -2
- package/docs/CODEX.md +36 -1
- package/docs/CONFIG.md +44 -42
- package/docs/FORGE-PROTOCOL.md +15 -1064
- package/docs/anthropic-devrel-outreach.md +2 -2
- package/docs/articles/command-decomposition-token-savings.md +214 -0
- package/docs/articles/model-release-playbook.md +131 -0
- package/docs/articles/per-repo-adaptive-scripts-token-savings.md +27 -25
- package/docs/claude-breakpoints.json +75 -5
- package/docs/design/abc-benchmark.md +1 -1
- package/docs/design/design-spec-schema.md +1 -1
- package/docs/design/divergent-generation.md +1 -1
- package/docs/design/eval-gate-runbook.md +178 -0
- package/docs/design/show-hn-draft.md +26 -1
- package/docs/design/token-cost-baseline-1298.md +59 -0
- package/docs/eval/README.md +117 -0
- package/docs/eval/corpus/seed-v1.json +6 -0
- package/docs/eval/published/claude-sonnet-4-6-2026-07-04.json +33 -0
- package/docs/site/annotations-explained.md +24 -0
- package/docs/site/command-learning-path.md +51 -14
- package/docs/site/command-reference.md +339 -113
- package/docs/site/for-companies.md +95 -0
- package/docs/site/forge-annotation-protocol.md +12 -256
- package/docs/site/getting-started.md +58 -12
- package/docs/site/github-is-the-memory.md +113 -0
- package/docs/site/how-it-works.md +3 -13
- package/docs/site/index.md +10 -2
- package/docs/spec/eval-run-result.md +147 -0
- package/docs/spec/forge-protocol-v1.md +441 -18
- package/docs/spec/label-state-machine.md +55 -0
- package/docs/spec/review-protocol.md +158 -0
- package/docs/spec-graph-schema.md +28 -0
- package/docs/superpowers/plans/2026-07-03-cinematic-onboarding-tui.md +2339 -0
- package/docs/superpowers/plans/2026-07-03-durable-execution-engine.md +1223 -0
- package/docs/superpowers/specs/2026-07-03-cinematic-onboarding-tui-design.md +157 -0
- package/docs/superpowers/specs/2026-07-03-durable-execution-engine-design.md +194 -0
- package/docs/superpowers/specs/2026-07-04-economic-self-governance-design.md +181 -0
- package/docs/superpowers/specs/2026-07-04-provenance-trail-design.md +189 -0
- package/examples/forgedock-demo/README.md +41 -22
- package/examples/forgedock-demo/issues/06-bug-tags-type-validation.md +43 -0
- package/examples/forgedock-demo/issues/07-bug-negative-offset-pagination.md +42 -0
- package/examples/forgedock-demo/issues/08-bug-patch-mass-assignment.md +49 -0
- package/examples/forgedock-demo/issues/09-bug-count-injection.md +47 -0
- package/examples/forgedock-demo/issues/10-feature-sort-param.md +39 -0
- package/examples/forgedock-demo/issues/11-feature-patch-tags.md +37 -0
- package/examples/forgedock-demo/issues/12-feature-bulk-create.md +42 -0
- package/examples/forgedock-demo/issues/13-feature-archive-notes.md +46 -0
- package/examples/forgedock-demo/issues/14-refactor-extract-title-validation.md +41 -0
- package/examples/forgedock-demo/issues/15-refactor-protected-route-flag.md +43 -0
- package/examples/forgedock-demo/issues/16-refactor-extract-store.md +45 -0
- package/examples/forgedock-demo/issues/17-perf-tags-dedup-set.md +35 -0
- package/examples/forgedock-demo/issues/18-perf-remove-redundant-sort.md +37 -0
- package/examples/forgedock-demo/issues/19-docs-api-reference-full.md +53 -0
- package/examples/forgedock-demo/issues/20-docs-intentional-flaw-convention.md +46 -0
- package/examples/forgedock-demo/scripts/smoke.js +18 -1
- package/examples/forgedock-demo/src/db.js +36 -11
- package/examples/forgedock-demo/src/routes/notes.js +106 -9
- package/examples/forgedock-demo/src/server.js +4 -1
- package/package.json +12 -4
- package/packages/protocol/LICENSE +21 -0
- package/packages/protocol/src/cli.js +135 -0
- package/packages/protocol/src/emit.js +146 -0
- package/packages/protocol/src/index.js +43 -0
- package/packages/protocol/src/parse.js +229 -0
- package/packages/protocol/src/types.js +171 -0
- package/packages/protocol/src/validate.js +122 -0
- package/scripts/bench-topology-cost.mjs +372 -0
- package/scripts/check-command-docs-drift.sh +198 -0
- package/scripts/check-protocol-restatements.sh +176 -0
- package/scripts/check-registry/README.md +72 -0
- package/scripts/check-registry/manifest.json +6 -0
- package/scripts/code-index.sh +454 -0
- package/scripts/conformance-check.mjs +168 -0
- package/scripts/doctor-pipeline-state.sh +484 -0
- package/scripts/eval-gate-baseline.json +17 -0
- package/scripts/eval-gate-scorecard.mjs +242 -0
- package/scripts/eval-scorecard-aggregator.mjs +252 -0
- package/scripts/flaky-quarantine.sh +241 -0
- package/scripts/forge-annotation.sh +567 -0
- package/scripts/issue-dedup.sh +236 -0
- package/scripts/validate-annotation-node.mjs +233 -0
- package/scripts/verify-env-vars.sh +18 -2
- package/scripts/verify-host-headers.sh +4 -4
- package/scripts/verify-route-registration.sh +2 -2
- package/scripts/worktree-lifecycle.sh +202 -0
- package/templates/devdocs/agent/using-forgedock.md +14 -0
package/commands/compat-audit.md
CHANGED
|
@@ -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**:
|
|
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
|
---
|
package/commands/deploy-info.md
CHANGED
|
@@ -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**:
|
|
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
|
|
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
|
|
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
|
|---------|---------------|-----------------|
|
package/commands/design-bench.md
CHANGED
|
@@ -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/
|
|
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
|
|
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
|
package/commands/design.md
CHANGED
|
@@ -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 -->
|
package/commands/diagnose.md
CHANGED
|
@@ -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**:
|
|
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
|
|
package/commands/explain.md
CHANGED
|
@@ -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**:
|
|
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
|
---
|
package/commands/forge-stats.md
CHANGED
|
@@ -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**:
|
|
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
|
---
|
package/commands/geo-audit.md
CHANGED
|
@@ -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**:
|
|
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**:
|
|
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
|
-
#
|
|
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:
|
|
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 |
|
package/commands/milestone.md
CHANGED
|
@@ -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
|
-
**
|
|
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
|
-
#
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
package/commands/optimize.md
CHANGED
|
@@ -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**:
|
|
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
|
---
|