forgedock 1.1.7 → 1.1.9
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 +10 -33
- package/bin/cinema.mjs +23 -5
- package/bin/engine/invariants.mjs +361 -0
- package/bin/engine-cli.mjs +137 -11
- package/bin/env-detect.mjs +249 -0
- package/bin/forge-utils.mjs +364 -4
- package/bin/forgedock.mjs +1064 -135
- package/bin/hooks/pre-tool-use.mjs +182 -0
- package/bin/hooks/session-start.mjs +68 -3
- package/bin/init-detect.mjs +101 -12
- package/bin/journey.mjs +917 -16
- package/bin/labels.json +10 -0
- package/bin/recall.mjs +557 -0
- package/bin/registry.mjs +91 -3
- package/bin/runner.mjs +38 -2
- package/bin/tui.mjs +49 -3
- package/commands/adopt.md +1 -1
- package/commands/analytics.md +8 -8
- package/commands/audit.md +1 -1
- package/commands/autopilot.md +958 -77
- package/commands/ci-audit.md +1 -1
- package/commands/cleanup.md +139 -55
- package/commands/compat-audit.md +1 -1
- package/commands/deploy-info.md +1 -1
- package/commands/deploy-pr.md +1 -1
- package/commands/diagnose.md +1 -1
- package/commands/explain.md +1 -1
- package/commands/fix-ci.md +1 -1
- package/commands/forgedock-init.md +1 -1
- package/commands/incident-response.md +3 -3
- package/commands/issue.md +1 -1
- package/commands/optimize.md +586 -1
- package/commands/orchestrate/config.md +13 -3
- package/commands/orchestrate/phase-1-resolve.md +36 -26
- package/commands/orchestrate/phase-2-triage.md +1 -1
- package/commands/orchestrate/phase-2.5-synthesis.md +1 -1
- package/commands/orchestrate/phase-3-dependency.md +587 -48
- package/commands/orchestrate/phase-4-execution.md +1031 -57
- package/commands/orchestrate/phase-5-cleanup.md +1 -1
- package/commands/orchestrate/phase-6-report.md +248 -11
- package/commands/orchestrate/safety.md +2 -2
- package/commands/pipeline-health/phase-2-metrics.md +305 -1
- package/commands/pipeline-health/phase-4-proposals.md +127 -0
- package/commands/qa-sweep.md +1 -1
- package/commands/quality-gate.md +418 -1
- package/commands/recover-orphans.md +5 -5
- package/commands/replay.md +1 -1
- package/commands/review-pr-agents/api.md +2 -2
- package/commands/review-pr-agents/auth.md +2 -2
- package/commands/review-pr-agents/billing.md +2 -2
- package/commands/review-pr-agents/concurrency.md +2 -2
- package/commands/review-pr-agents/database.md +2 -2
- package/commands/review-pr-agents/frontend.md +2 -2
- package/commands/review-pr-agents/infra.md +2 -2
- package/commands/review-pr-agents/protocols.md +1 -1
- package/commands/review-pr-agents/scraper.md +2 -2
- package/commands/review-pr-agents/security.md +2 -2
- package/commands/review-pr-staging.md +41 -3
- package/commands/review-pr.md +462 -19
- package/commands/rollback.md +1 -1
- package/commands/scope.md +1 -1
- package/commands/security-audit.md +1 -1
- package/commands/spec-doctor.md +429 -0
- package/commands/test-gate.md +1 -1
- package/commands/validate.md +53 -1
- package/commands/work-on/build/architect.md +78 -1
- package/commands/work-on/build/context.md +360 -22
- package/commands/work-on/build/implement.md +3 -1
- package/commands/work-on/build/validate.md +29 -1
- package/commands/work-on/build.md +75 -6
- package/commands/work-on/close.md +624 -10
- package/commands/work-on/decompose.md +1 -1
- package/commands/work-on/investigate.md +235 -5
- package/commands/work-on/remediate.md +331 -0
- package/commands/work-on/review.md +1 -1
- package/commands/work-on-monolithic.md +1 -1
- package/commands/work-on.md +205 -66
- package/docs/CI.md +2 -2
- package/docs/CODEX.md +1 -1
- package/docs/CONFIG.md +186 -0
- package/docs/FORGE-PROTOCOL.md +101 -0
- package/docs/site/command-reference.md +31 -1
- package/docs/site/getting-started.md +9 -34
- package/docs/site/index.md +1 -1
- package/docs/spec/forge-protocol-v1.md +97 -5
- package/docs/spec/label-state-machine.md +6 -1
- package/package.json +3 -2
- package/packages/protocol/src/cli.js +374 -84
- package/packages/protocol/src/types.js +75 -1
- package/scripts/build-knowledge-index.mjs +1761 -0
- package/scripts/calibration.mjs +996 -0
- package/scripts/check-command-docs-drift.sh +4 -2
- package/scripts/danger-zones.mjs +789 -0
- package/scripts/doctor-pipeline-state.sh +88 -2
- package/scripts/select-fix-targets.sh +234 -0
- package/scripts/transition-label.sh +245 -6
- package/scripts/refresh-bot-token.sh +0 -97
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
install:
|
|
2
|
+
install: core
|
|
3
3
|
---
|
|
4
4
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
5
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -21,26 +21,170 @@ done
|
|
|
21
21
|
|
|
22
22
|
Aggregate into the batch-level analytics for Step 6B.
|
|
23
23
|
|
|
24
|
-
**Also collect the machine-readable summary cards** (
|
|
25
|
-
|
|
26
|
-
batch cards in Step 6C
|
|
24
|
+
**Also collect the machine-readable summary cards** (embedded in each issue's `FORGE:TRAJECTORY`
|
|
25
|
+
comment by `/work-on` close phase as a `<!-- FORGE:CARD: v1 sha:... b64:... -->` line). These
|
|
26
|
+
power the per-issue and batch cards in Step 6C.
|
|
27
|
+
|
|
28
|
+
**CODEC PATH (forge#1727)**: Cards are now Base64url-encoded. Use the protocol CLI's `parse`
|
|
29
|
+
subcommand to decode them — do NOT use the old `sed -n 's/.*<!-- FORGE:CARD \(.*\) -->.*/\1/p'`
|
|
30
|
+
regex extraction, which only worked for the deprecated inline-JSON form:
|
|
27
31
|
|
|
28
32
|
```bash
|
|
29
33
|
CARDS=""
|
|
30
34
|
for NUM in {all_completed_issue_numbers}; do
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
[ -n "$
|
|
35
|
+
# Fetch the TRAJECTORY comment body for this issue
|
|
36
|
+
TRAJ_BODY=$(gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
37
|
+
--jq '[.[] | select(.body | contains("FORGE:CARD:"))] | last | .body // ""' 2>/dev/null || true)
|
|
38
|
+
if [ -n "$TRAJ_BODY" ]; then
|
|
39
|
+
# Decode via protocol CLI — handles both Base64url form (forge#1727) and gracefully
|
|
40
|
+
# exits 1 (skips) for pre-migration inline-JSON entries.
|
|
41
|
+
CARD=$(echo "$TRAJ_BODY" | node packages/protocol/src/cli.js parse --type CARD 2>/dev/null || true)
|
|
42
|
+
[ -n "$CARD" ] && CARDS="${CARDS}${CARD}"$'\n'
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
# CARDS is now a newline-delimited list of per-issue JSON objects decoded from FORGE:CARD payloads.
|
|
46
|
+
# Skip any issue whose card is absent — pre-card runs or non-merged terminal states degrade gracefully.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 6A.5: Collect merge-ready PRs (`workflow:awaiting-merge`) <!-- Added: forge#1811 -->
|
|
50
|
+
|
|
51
|
+
**Why a separate collection pass**: `workflow:awaiting-merge` issues are open (their PR hasn't
|
|
52
|
+
merged yet), so they are excluded from `{all_completed_issue_numbers}` above — that set only
|
|
53
|
+
contains issues that reached a closed/merged terminal state. Iterate the full batch issue set
|
|
54
|
+
(`{all_batch_issue_numbers}` — same prose-variable used by the batch-wide loops in
|
|
55
|
+
`phase-4-execution.md`) instead, and filter to the awaiting-merge label.
|
|
56
|
+
|
|
57
|
+
For each awaiting-merge issue, resolve its open PR using the `"Closes #N"`-anchored search
|
|
58
|
+
established by forge#1634/#1646 — **do not** use a bare-number `search "${NUM} in:body"`, which
|
|
59
|
+
can false-positive on changelogs or cross-references and resolve the wrong PR:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
MERGE_READY_PRS=() # each entry: "NUM|PR_NUMBER|TITLE"
|
|
63
|
+
|
|
64
|
+
for NUM in {all_batch_issue_numbers}; do
|
|
65
|
+
IS_AWAITING=$(gh issue view "$NUM" -R {GH_REPO} --json labels \
|
|
66
|
+
--jq '[.labels[].name | select(. == "workflow:awaiting-merge")] | length' 2>/dev/null || echo "0")
|
|
67
|
+
[ "$IS_AWAITING" -gt 0 ] || continue
|
|
68
|
+
|
|
69
|
+
TITLE=$(gh issue view "$NUM" -R {GH_REPO} --json title --jq '.title' 2>/dev/null || echo "")
|
|
70
|
+
|
|
71
|
+
# Anchor on "Closes #N" first (forge#1634/#1646 precedent).
|
|
72
|
+
PR_NUM=$(gh pr list -R {GH_REPO} --state open --search "\"Closes #${NUM}\" in:body" \
|
|
73
|
+
--json number,updatedAt --jq 'sort_by(.updatedAt) | last | .number' 2>/dev/null || echo "")
|
|
74
|
+
if [ -z "$PR_NUM" ]; then
|
|
75
|
+
# Fallback: a PR may close the issue via "Fixes #N"/"Resolves #N" rather than
|
|
76
|
+
# "Closes #N". Use the bare number only to generate candidates, then RE-VALIDATE
|
|
77
|
+
# each candidate's body against an anchored (Closes|Fixes|Resolves) #N word-boundary
|
|
78
|
+
# regex before accepting it — never accept a bare mention (changelog / cross-reference),
|
|
79
|
+
# which could resolve the wrong PR into the one-shot batch-merge command. This mirrors
|
|
80
|
+
# the recover-orphans.md re-validation precedent. <!-- forge#1822 -->
|
|
81
|
+
PR_NUM=$(gh pr list -R {GH_REPO} --state open --search "${NUM} in:body" \
|
|
82
|
+
--json number,updatedAt,body \
|
|
83
|
+
--jq --arg n "${NUM}" '[ .[] | select(.body | test("(?i)(close[sd]?|fix(e[sd])?|resolve[sd]?)\\s+#" + $n + "\\b")) ] | sort_by(.updatedAt) | last | .number // empty' 2>/dev/null || echo "")
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
[ -n "$PR_NUM" ] && MERGE_READY_PRS+=("${NUM}|${PR_NUM}|${TITLE}")
|
|
87
|
+
done
|
|
88
|
+
# MERGE_READY_PRS now holds one entry per merge-ready PR in the batch (empty array if none).
|
|
89
|
+
# Feeds the "### Merge-Ready" report block and the Implementation Results table row (Step 6B).
|
|
90
|
+
|
|
91
|
+
# Pre-build the batch-merge command (rendered verbatim as {MERGE_READY_CMD} in Step 6B —
|
|
92
|
+
# computed here, not inside the report template, so Step 6B stays plain template text with no
|
|
93
|
+
# nested code fences of its own). `gh pr merge` accepts only ONE PR selector per invocation,
|
|
94
|
+
# so chain one `gh pr merge` per PR with && rather than passing a space-separated list (which
|
|
95
|
+
# `gh` rejects). <!-- forge#1838 review: BUG-3 -->
|
|
96
|
+
MERGE_READY_CMD=""
|
|
97
|
+
if [ "${#MERGE_READY_PRS[@]}" -gt 0 ]; then
|
|
98
|
+
for _entry in "${MERGE_READY_PRS[@]}"; do
|
|
99
|
+
_pr=$(printf '%s' "$_entry" | cut -d'|' -f2)
|
|
100
|
+
[ -z "$_pr" ] && continue
|
|
101
|
+
[ -n "$MERGE_READY_CMD" ] && MERGE_READY_CMD="${MERGE_READY_CMD} && "
|
|
102
|
+
MERGE_READY_CMD="${MERGE_READY_CMD}gh pr merge ${_pr} --merge -R {GH_REPO}"
|
|
103
|
+
done
|
|
104
|
+
fi
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Step 6A.6: Collect blocked-on-human-merge dependents (`blocked-on-human-merge`) <!-- Added: forge#1812 -->
|
|
108
|
+
|
|
109
|
+
**Why a separate collection pass**: A `blocked-on-human-merge` issue is a *dependent* of a `GATED`
|
|
110
|
+
predecessor (`needs-human` or `workflow:awaiting-merge` — see `phase-4-execution.md` Step 4B's
|
|
111
|
+
Predecessor Classification), not itself blocked or failed. It has no PR of its own yet — it hasn't
|
|
112
|
+
even been dispatched. It is excluded from both `{all_completed_issue_numbers}` (never ran) and
|
|
113
|
+
`MERGE_READY_PRS` (Step 6A.5, which only covers issues that themselves reached `workflow:awaiting-merge`).
|
|
114
|
+
Reporting it as `⏭ Skipped (dep)` would be wrong — that label means the predecessor `FAILED` and the
|
|
115
|
+
work is abandoned; this state means the work is queued and will auto-dispatch on merge, no manual
|
|
116
|
+
re-run required.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
BLOCKED_ON_MERGE=() # each entry: "NUM|GATING_PRED|GATING_PR|TITLE"
|
|
120
|
+
|
|
121
|
+
for NUM in {all_batch_issue_numbers}; do
|
|
122
|
+
IS_BLOCKED=$(gh issue view "$NUM" -R {GH_REPO} --json labels \
|
|
123
|
+
--jq '[.labels[].name | select(. == "blocked-on-human-merge")] | length' 2>/dev/null || echo "0")
|
|
124
|
+
[ "$IS_BLOCKED" -gt 0 ] || continue
|
|
125
|
+
|
|
126
|
+
TITLE=$(gh issue view "$NUM" -R {GH_REPO} --json title --jq '.title' 2>/dev/null || echo "")
|
|
127
|
+
GATING_PRED=$(gh api repos/{GH_REPO}/issues/${NUM}/comments \
|
|
128
|
+
--jq '[.[] | select(.body | contains("FORGE:BLOCKED_ON_HUMAN_MERGE"))] | last | (.body | capture("Gating predecessor\\*\\*: #(?<p>[0-9]+)").p) // ""' 2>/dev/null || echo "")
|
|
129
|
+
GATING_PR=""
|
|
130
|
+
if [ -n "$GATING_PRED" ]; then
|
|
131
|
+
GATING_PR=$(gh pr list -R {GH_REPO} --state open --search "\"Closes #${GATING_PRED}\" in:body" \
|
|
132
|
+
--json number --jq '.[0].number // empty' 2>/dev/null || echo "")
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
BLOCKED_ON_MERGE+=("${NUM}|${GATING_PRED}|${GATING_PR}|${TITLE}")
|
|
136
|
+
done
|
|
137
|
+
# BLOCKED_ON_MERGE now holds one entry per dependent queued behind a human-gated predecessor
|
|
138
|
+
# (empty array if none). Feeds the "Blocked-on-Merge" report block and the Implementation
|
|
139
|
+
# Results table row (Step 6B).
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Step 6A.7: Determine idle-policy end state <!-- Added: forge#1814 -->
|
|
143
|
+
|
|
144
|
+
**Why**: `phase-4-execution.md` Step 4B item 6.7 can end the live monitoring loop in two visibly
|
|
145
|
+
different ways: a **clean/paused drain** (every original-batch issue reached `DONE`/`FAILED`, or
|
|
146
|
+
is `blocked-on-human-merge` with no cascade activity left to suppress), or an **idle-policy
|
|
147
|
+
pause** (`BATCH_FULLY_GATED` was true at the moment the batch stopped, meaning Step 4C actively
|
|
148
|
+
suppressed one or more newly-spawned review-finding dispatches). Both are legitimate stopping
|
|
149
|
+
points, but rendering an idle-policy pause under the same "Orchestration Complete" header as a
|
|
150
|
+
genuine full drain misrepresents a paused run as finished — the whole point of #1814 is to make
|
|
151
|
+
this pause visible, not silent.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# BATCH_FULLY_GATED is the value computed in phase-4-execution.md Step 4B item 6.7 at the point
|
|
155
|
+
# the live loop stopped — threaded into Phase 6 as a plain boolean, not recomputed here (Phase 6
|
|
156
|
+
# runs after the live loop has already ended, so re-running item 6.7's per-issue classification
|
|
157
|
+
# would be redundant; carry the value forward instead).
|
|
158
|
+
ORCHESTRATION_ENDED_IDLE="${BATCH_FULLY_GATED:-false}"
|
|
159
|
+
|
|
160
|
+
# Count of findings deferred this run for the idle-policy reason specifically (distinct from
|
|
161
|
+
# generation>=2 and comment/typo/P3-same-file deferrals, which are unaffected by this policy).
|
|
162
|
+
IDLE_POLICY_DEFERRED_COUNT=0
|
|
163
|
+
for FINDING_NUM in "${DEFERRED_FINDINGS[@]:-}"; do
|
|
164
|
+
[ -z "$FINDING_NUM" ] && continue
|
|
165
|
+
echo "${DEFERRED_REASONS[$FINDING_NUM]:-}" | grep -qi "batch fully human-gated" && \
|
|
166
|
+
IDLE_POLICY_DEFERRED_COUNT=$((IDLE_POLICY_DEFERRED_COUNT + 1))
|
|
35
167
|
done
|
|
36
|
-
# CARDS is now a newline-delimited list of per-issue JSON objects (skip any issue whose
|
|
37
|
-
# card is absent — pre-card runs or non-merged terminal states degrade gracefully).
|
|
38
168
|
```
|
|
39
169
|
|
|
40
170
|
### Step 6B: Present consolidated report
|
|
41
171
|
|
|
172
|
+
Always rendered in full, once, regardless of `{NARRATION_MODE}` — `pipeline.narration` (see `config.md`) only gates the per-completion recap in Step 4B item 8. This is the one place full tables are guaranteed to appear.
|
|
173
|
+
|
|
42
174
|
```
|
|
175
|
+
{IF ORCHESTRATION_ENDED_IDLE == "true":}
|
|
176
|
+
## Orchestration Paused — Idle (waiting on {#MERGE_READY_PRS[@]:-0} + {#BLOCKED_ON_MERGE[@]:-0} merge(s))
|
|
177
|
+
|
|
178
|
+
This run stopped because the remaining batch is fully human-gated — every original issue is
|
|
179
|
+
merged/invalid, or blocked on a human decision/merge. {IDLE_POLICY_DEFERRED_COUNT} newly-spawned
|
|
180
|
+
review-finding issue(s) were deferred (not dispatched) rather than added to the open-issue count.
|
|
181
|
+
See "Merge-Ready" and "Blocked-on-Merge" below for the exact action needed to resume. Re-run
|
|
182
|
+
`/orchestrate` (or let a still-running session's live wake pick it up) once you've merged the
|
|
183
|
+
PR(s) listed there — deferred findings are re-evaluated automatically by the next Completion
|
|
184
|
+
Sweep (Step 4F.2.5) once the batch is no longer fully gated.
|
|
185
|
+
{ELSE:}
|
|
43
186
|
## Orchestration Complete
|
|
187
|
+
{END IF}
|
|
44
188
|
|
|
45
189
|
**Scope**: {milestone / issue list}
|
|
46
190
|
**Duration**: {approximate time}
|
|
@@ -61,7 +205,62 @@ done
|
|
|
61
205
|
| #{N1} | {title} | from #{INV1} | ✓ Merged | #{PR} | staging |
|
|
62
206
|
| #{C} | {title} | original | ✗ Invalid | — | — |
|
|
63
207
|
| #{D} | {title} | original | ⚠ Blocked | — | — |
|
|
208
|
+
| #{F} | {title} | original | ⏸ Awaiting Merge | #{PR} | staging |
|
|
64
209
|
| #{E} | {title} | original | ⏭ Skipped (dep) | — | — |
|
|
210
|
+
| #{G} | {title} | original | 🔗 Blocked-on-Merge (gated by #{PRED}) | — | — |
|
|
211
|
+
|
|
212
|
+
`⏸ Awaiting Merge` (`workflow:awaiting-merge`) is structurally distinct from `⚠ Blocked`
|
|
213
|
+
(`needs-human`): a Blocked row means the pipeline hit something it cannot resolve on its own
|
|
214
|
+
and a human must diagnose it; an Awaiting Merge row means the PR was already remediated and
|
|
215
|
+
re-reviewed to a clean APPROVED verdict — a human only needs to click merge. Never render an
|
|
216
|
+
awaiting-merge PR as `⚠ Blocked`.
|
|
217
|
+
|
|
218
|
+
`🔗 Blocked-on-Merge` (`blocked-on-human-merge`, forge#1812) is distinct from all three of the
|
|
219
|
+
above: it is a *dependent* of a GATED predecessor (one currently `⚠ Blocked` or `⏸ Awaiting
|
|
220
|
+
Merge`) — the dependent issue itself was never dispatched and has no problem of its own. It is
|
|
221
|
+
also distinct from `⏭ Skipped (dep)`, which means the predecessor `FAILED` outright and the work
|
|
222
|
+
was abandoned. A Blocked-on-Merge row means the work is queued and will auto-dispatch the instant
|
|
223
|
+
the gating predecessor's PR merges — no manual `/orchestrate` re-run required. Never render a
|
|
224
|
+
blocked-on-human-merge dependent as `⏭ Skipped (dep)`.
|
|
225
|
+
|
|
226
|
+
{IF `MERGE_READY_PRS` (Step 6A.5) is non-empty:}
|
|
227
|
+
|
|
228
|
+
### Merge-Ready — {N} PR(s) awaiting only a human merge
|
|
229
|
+
|
|
230
|
+
These PRs were remediated and re-reviewed to a clean `APPROVED` verdict after an earlier
|
|
231
|
+
`needs-human` escalation. They do not need further diagnosis — merge them to land the batch.
|
|
232
|
+
|
|
233
|
+
| # | Issue | PR | Title |
|
|
234
|
+
|---|-------|----|----|
|
|
235
|
+
{one row per `MERGE_READY_PRS` entry: | {n} | #{NUM} | #{PR} | {title} |}
|
|
236
|
+
|
|
237
|
+
**One action to land all {N}:** `{MERGE_READY_CMD}`
|
|
238
|
+
|
|
239
|
+
(`{MERGE_READY_CMD}` is pre-built in Step 6A.5 by chaining one `gh pr merge <pr> --merge` per PR
|
|
240
|
+
in `MERGE_READY_PRS` with `&&` — `gh pr merge` takes a single PR selector, so a space-separated
|
|
241
|
+
list would be rejected. Render it verbatim here as plain text, no code fence.)
|
|
242
|
+
|
|
243
|
+
{ELSE: omit this section entirely — do not print an empty "Merge-Ready" heading.}
|
|
244
|
+
|
|
245
|
+
{IF `BLOCKED_ON_MERGE` (Step 6A.6) is non-empty:}
|
|
246
|
+
|
|
247
|
+
### Blocked-on-Merge — {N} issue(s) queued behind a human-gated predecessor
|
|
248
|
+
|
|
249
|
+
These issues are dependents of a predecessor that is currently `⚠ Blocked` or `⏸ Awaiting Merge`.
|
|
250
|
+
They were never dispatched — no work has started on them — and they need no action right now.
|
|
251
|
+
Each will auto-dispatch the instant its gating predecessor's PR merges (live-session wake via
|
|
252
|
+
`phase-4-execution.md` Step 4B item 6.6, or next-`/orchestrate`-invocation wake via
|
|
253
|
+
`phase-3-dependency.md`'s wake/compaction reconstruction). This batch is a **paused drain**, not
|
|
254
|
+
a complete one — re-running `/orchestrate` after merging the gating PR(s) below will pick these up.
|
|
255
|
+
|
|
256
|
+
| # | Issue | Gated By | Gating PR | Title |
|
|
257
|
+
|---|-------|----------|-----------|-------|
|
|
258
|
+
{one row per `BLOCKED_ON_MERGE` entry: | {n} | #{NUM} | #{GATING_PRED} | #{GATING_PR} | {title} |}
|
|
259
|
+
|
|
260
|
+
**To unblock**: merge the gating PR(s) referenced above, then re-run `/orchestrate` (or let the
|
|
261
|
+
current session's live wake pick them up automatically if it is still running).
|
|
262
|
+
|
|
263
|
+
{ELSE: omit this section entirely — do not print an empty "Blocked-on-Merge" heading.}
|
|
65
264
|
|
|
66
265
|
### Review-Spawned Issues
|
|
67
266
|
|
|
@@ -88,9 +287,11 @@ done
|
|
|
88
287
|
|
|
89
288
|
### Summary
|
|
90
289
|
- **Investigations**: {N} completed, spawned {M} new issues
|
|
91
|
-
- **Review findings**: {N} spawned, {M} resolved in-batch, {K} swept, {J} deferred (cosmetic), {L} deferred (gen2)
|
|
290
|
+
- **Review findings**: {N} spawned, {M} resolved in-batch, {K} swept, {J} deferred (cosmetic), {L} deferred (gen2), {IDLE_POLICY_DEFERRED_COUNT} deferred (idle policy, forge#1814)
|
|
92
291
|
- **Succeeded**: {N} issues resolved (implementation + sweep)
|
|
93
292
|
- **Failed**: {N} issues need attention
|
|
293
|
+
- **Merge-ready**: {#MERGE_READY_PRS[@]:-0} PRs awaiting only a human merge (see "Merge-Ready" section above)
|
|
294
|
+
- **Blocked-on-merge**: {#BLOCKED_ON_MERGE[@]:-0} issues queued behind a human-gated predecessor, will auto-dispatch on merge (see "Blocked-on-Merge" section above)
|
|
94
295
|
- **Skipped**: {N} issues (dependency failures)
|
|
95
296
|
|
|
96
297
|
### Post-Batch Cleanup
|
|
@@ -120,10 +321,44 @@ done
|
|
|
120
321
|
| Contract→code divergences | {N} (agents that updated contract mid-build) |
|
|
121
322
|
| Review findings created | {N_total} |
|
|
122
323
|
| Findings queued after cascade control | {N_queued}/{N_total} ({N_deferred} deferred — see Step 4C) |
|
|
324
|
+
| Findings deferred — idle policy (forge#1814) | {IDLE_POLICY_DEFERRED_COUNT} (batch fully human-gated at defer time — see Step 4B item 6.7) |
|
|
325
|
+
| P3 findings clubbed (surface-area batching, forge#1818) | {SURFACE_BATCH_COUNT:-0} batch(es) covering {#SURFACE_BATCHED_FINDINGS[@]:-0} finding(s) — see Step 4C |
|
|
326
|
+
| Findings deferred — token budget (forge#1858) | {#TOKEN_DEFERRED[@]:-0} (batch spend {BATCH_TOKEN_SPEND:-0}/{TOKEN_BUDGET:-uncapped} tokens — see Step 4C) |
|
|
123
327
|
| Competing recommendations reconciled (Phase 2.5) | {RECONCILED_COUNT} (investigation plans arbitrated in place + serialized) |
|
|
124
328
|
| Findings validated | {N} |
|
|
125
329
|
| False positives | {N} ({%}) |
|
|
126
330
|
| Anomalies flagged | {N} |
|
|
331
|
+
| Budget limit ($) | ${BUDGET_LIMIT:-uncapped} |
|
|
332
|
+
| Projected spend (dispatched issues) | ${PROJECTED_SPEND:-—} |
|
|
333
|
+
| Actual spend (best-effort telemetry) | ${ACTUAL_SPEND:-—} |
|
|
334
|
+
| Issues deferred (budget ceiling) | {#DEFERRED_BUDGET_ISSUES[@]:-0} |
|
|
335
|
+
| ε-reserve issued (no-prior dispatch) | {EPSILON_DISPATCHED:-no} |
|
|
336
|
+
| **Value-weighted throughput** | **{VALUE_THROUGHPUT:-—} value-pts/USD** |
|
|
337
|
+
|
|
338
|
+
`value-weighted throughput` = Σ(priority_weight × danger_zone_weight) for **merged** issues ÷ actual spend (USD). A higher value means more high-priority issues were resolved per dollar. Trend this across runs via `/pipeline-health` to measure the economic scheduling ROI. <!-- Added: forge#1743 -->
|
|
339
|
+
|
|
340
|
+
`P3 findings clubbed` and `Findings deferred — token budget` are a DIFFERENT mechanism from the `$`-denominated `Budget limit`/`Projected spend`/`Actual spend`/`Issues deferred (budget ceiling)` rows above (forge#1743, opt-in `--budget N` flag, gates the *original* issue dispatch order). The token-budget row reads the always-on, token-denominated ceiling that scopes ONLY to Step 4C's review-finding cascade dispatch (forge#1858); `SURFACE_BATCH_COUNT` and `SURFACE_BATCHED_FINDINGS` are populated by the same Step 4C surface-area-batching block (forge#1818) that clubs P3 findings sharing a file/leaf-directory into one dispatched pipeline. Both degrade gracefully to `0`/`uncapped` when the batch had no review findings or ran with defaults. <!-- Added: forge#1858 -->
|
|
341
|
+
|
|
342
|
+
**Compute value-weighted throughput** (populate before rendering the table):
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Collect value scores for merged issues (ISSUE_VALUE[] populated in Step 3E.5)
|
|
346
|
+
MERGED_VALUE_SUM="0"
|
|
347
|
+
for NUM in {all_completed_issue_numbers}; do
|
|
348
|
+
IS_MERGED=$(gh issue view "$NUM" -R {GH_REPO} --json labels \
|
|
349
|
+
--jq '[.labels[].name | select(. == "workflow:merged")] | length' 2>/dev/null || echo "0")
|
|
350
|
+
if [ "$IS_MERGED" -gt 0 ] && [ -n "${ISSUE_VALUE[$NUM]:-}" ]; then
|
|
351
|
+
MERGED_VALUE_SUM=$(echo "scale=4; $MERGED_VALUE_SUM + ${ISSUE_VALUE[$NUM]}" | bc 2>/dev/null \
|
|
352
|
+
|| echo "$MERGED_VALUE_SUM")
|
|
353
|
+
fi
|
|
354
|
+
done
|
|
355
|
+
|
|
356
|
+
if [ "${ACTUAL_SPEND:-0}" != "0" ] && echo "${ACTUAL_SPEND:-0}" | grep -qP '^\d+(\.\d+)?$'; then
|
|
357
|
+
VALUE_THROUGHPUT=$(echo "scale=2; $MERGED_VALUE_SUM / $ACTUAL_SPEND" | bc 2>/dev/null || echo "—")
|
|
358
|
+
else
|
|
359
|
+
VALUE_THROUGHPUT="—" # no spend telemetry available
|
|
360
|
+
fi
|
|
361
|
+
```
|
|
127
362
|
|
|
128
363
|
**Domain breakdown**: {N} scraping, {N} frontend, {N} billing, ...
|
|
129
364
|
**Routing**: {N} fast-lane, {N} feature-lane
|
|
@@ -137,8 +372,10 @@ done
|
|
|
137
372
|
- Contract divergences > 20% → investigation quality may need improvement
|
|
138
373
|
- **Idle% > 50%** → agents stalling at phase boundaries; check work-on routing loop
|
|
139
374
|
- **Avg resumes > 1** → orchestrator having to compensate for agent stops
|
|
375
|
+
- **Value-weighted throughput trending down** → high-value issues deferred or blocked; check Step 3E.5 score distribution
|
|
140
376
|
|
|
141
377
|
### Next Steps
|
|
378
|
+
{If ORCHESTRATION_ENDED_IDLE == "true": "This run paused on the human-gated idle policy (forge#1814) — merge the PR(s) listed in the Merge-Ready section above, then re-run `/orchestrate` (or let a still-running session's live wake pick it up automatically) to resume dispatch of blocked-on-merge dependents and re-evaluate the {IDLE_POLICY_DEFERRED_COUNT} deferred finding(s)."}
|
|
142
379
|
{If milestone and all issues done: "Milestone ready to ship. Run `/milestone ship {slug}` when ready. The ship command includes a pre-merge hunk-loss audit (Step 2.5) that detects staging-only hunks in milestone-modified files and rebases the milestone branch to absorb them before creating the PR — protecting against squash-merge regressions."}
|
|
143
380
|
{If some failed: "Issues #{X}, #{Y} need manual attention. Re-run with `/work-on #{X}` after resolving blockers."}
|
|
144
381
|
{If fast-lane: "All fixes merged to staging. Merge staging → main via GitHub web UI when ready to deploy."}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
install:
|
|
2
|
+
install: core
|
|
3
3
|
---
|
|
4
4
|
<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios -->
|
|
5
5
|
<!-- SPDX-License-Identifier: AGPL-3.0-or-later -->
|
|
@@ -10,7 +10,7 @@ install: internal
|
|
|
10
10
|
|
|
11
11
|
1. **Every agent MUST invoke `/work-on` via the Skill tool.** No custom prompts. No manual implementation. Copy the Phase 4A template, fill in variables, done. (See HARD RULES at top of file.)
|
|
12
12
|
2. **NEVER merge anything to `main`** — agents merge to `staging` or `milestone/{slug}` only
|
|
13
|
-
3. **
|
|
13
|
+
3. **Concurrency is capped by default (12 in-flight agents)** <!-- Updated: forge#1912 --> — file overlap and dependencies still determine which issues are *eligible* to run in parallel, but Phase 4 never dispatches more than `MAX_CONCURRENT` at once (default 12); the rest queue and dispatch as running agents complete. Set `forge.yaml → orchestration.max_concurrent` to raise or lower the cap (see Engine mode § Concurrency model, and `phase-4-execution.md` Step 4A-pre.0.2).
|
|
14
14
|
4. **Always confirm with user before launching** — Step 3E is the mandatory checkpoint
|
|
15
15
|
5. **No retries** — if an agent fails, report it and move on
|
|
16
16
|
6. **Respect existing work** — skip issues already being worked on (`workflow:building`, `workflow:in-review`)
|