forgedock 1.10.2 → 1.10.3
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/bin/forgedock.mjs
CHANGED
|
@@ -3941,6 +3941,15 @@ switch (command) {
|
|
|
3941
3941
|
await run();
|
|
3942
3942
|
break;
|
|
3943
3943
|
case "backend-check": {
|
|
3944
|
+
// Exit codes: 0 = ready, 1 = no usable backend, 2 = bad usage (unknown option).
|
|
3945
|
+
// Only --quiet is accepted; anything else is a usage error so callers can tell a
|
|
3946
|
+
// plugin/CLI version mismatch apart from a real backend failure.
|
|
3947
|
+
const unknownFlag = restArgs.find((a) => a !== "--quiet");
|
|
3948
|
+
if (unknownFlag !== undefined) {
|
|
3949
|
+
process.stderr.write(`Unknown option: ${unknownFlag}\n`);
|
|
3950
|
+
exitCode = 2;
|
|
3951
|
+
break;
|
|
3952
|
+
}
|
|
3944
3953
|
const { checkExecutionBackend } = await import("./runner.mjs");
|
|
3945
3954
|
const result = checkExecutionBackend();
|
|
3946
3955
|
if (!restArgs.includes("--quiet")) {
|
|
@@ -920,8 +920,30 @@ FORGEDOCK_AVAILABLE=$(command -v forgedock >/dev/null 2>&1 && echo "true" || ech
|
|
|
920
920
|
# explicit FORGEDOCK_BACKEND, and accepts API fallback only when ANTHROPIC_API_KEY is configured.
|
|
921
921
|
# It performs no paid model request.
|
|
922
922
|
if [ "$FORGEDOCK_AVAILABLE" = "true" ]; then
|
|
923
|
-
|
|
924
|
-
|
|
923
|
+
# Time-bounded, non-interactive probe. `backend-check` exit codes: 0 ready, 1 no usable
|
|
924
|
+
# backend, 2 bad usage (unknown option), 124 = probe timed out (hung CLI). Three distinct
|
|
925
|
+
# outcomes must not collapse into one "no backend" verdict: an older installed CLI that
|
|
926
|
+
# rejects `--quiet` is plugin/CLI version skew, not a backend failure.
|
|
927
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
928
|
+
PROBE_OUT=$(timeout 10 forgedock backend-check --quiet 2>&1 </dev/null); PROBE_RC=$?
|
|
929
|
+
CLI_VERSION=$(timeout 10 forgedock --version 2>&1 </dev/null | head -n1)
|
|
930
|
+
else
|
|
931
|
+
PROBE_OUT=$(forgedock backend-check --quiet 2>&1 </dev/null); PROBE_RC=$?
|
|
932
|
+
CLI_VERSION=$(forgedock --version 2>&1 </dev/null | head -n1)
|
|
933
|
+
fi
|
|
934
|
+
if [ "$PROBE_RC" -eq 0 ]; then
|
|
935
|
+
: # backend ready — keep engine-first dispatch
|
|
936
|
+
elif [ "$PROBE_RC" -eq 124 ]; then
|
|
937
|
+
echo "WARNING: forgedock CLI probe timed out after 10s (hung CLI, installed: ${CLI_VERSION:-unknown}). Downgrading to the Agent-spawn fallback path for this entire run."
|
|
938
|
+
FORGEDOCK_AVAILABLE="false"
|
|
939
|
+
elif [ "$PROBE_RC" -eq 2 ] || printf '%s' "$PROBE_OUT" | grep -qiE 'unknown (option|command)'; then
|
|
940
|
+
echo "WARNING: plugin/CLI version skew — installed forgedock '${CLI_VERSION:-unknown}' does not support 'backend-check --quiet' (needs a newer CLI; upgrade with: npm i -g forgedock). This is NOT a backend failure. Downgrading to the Agent-spawn fallback path for this entire run."
|
|
941
|
+
FORGEDOCK_AVAILABLE="false"
|
|
942
|
+
elif [ "$PROBE_RC" -eq 1 ]; then
|
|
943
|
+
echo "WARNING: forgedock CLI is on PATH, but no configured execution backend is locally usable (${PROBE_OUT:-no detail}). Downgrading to the Agent-spawn fallback path for this entire run — see forge#2743."
|
|
944
|
+
FORGEDOCK_AVAILABLE="false"
|
|
945
|
+
else
|
|
946
|
+
echo "WARNING: forgedock backend probe failed unexpectedly (rc=$PROBE_RC, installed: ${CLI_VERSION:-unknown}): ${PROBE_OUT}. Downgrading to the Agent-spawn fallback path for this entire run."
|
|
925
947
|
FORGEDOCK_AVAILABLE="false"
|
|
926
948
|
fi
|
|
927
949
|
fi
|
|
@@ -2288,7 +2310,7 @@ done
|
|
|
2288
2310
|
|
|
2289
2311
|
**YOUR MISSION**: Invoke `Skill(skill='{FORGE_SKILL_PREFIX}work-on', args='{GATING_PR} --remediate --issue {PRED} --repo {GH_REPO} --gh-flag {GH_FLAG} --under-orchestration')` and let it run to completion. This is a self-contained flow: it classifies the gate first, replaces `needs-human` with `workflow:in-review` only for fixable remediation, checks out the PR branch, fixes any fixable review findings, re-reviews, and either auto-lands the PR, holds it at `workflow:awaiting-merge` for a human, re-escalates back to `needs-human`, or reports the block as policy-level and unfixable. Do NOT intervene manually — do not run raw git/gh commands yourself.
|
|
2290
2312
|
|
|
2291
|
-
**DO NOT STOP EARLY**: if the Skill call returns without a terminal `REMEDIATE_RESULT.status`, invoke it again — it re-reads GitHub state and resumes. Terminal statuses are: `COMPLETE`, `ALREADY_DONE`, `UNFIXABLE`, `BLOCKED`, `REREVIEW_REQUIRED`.
|
|
2313
|
+
**DO NOT STOP EARLY**: if the Skill call returns without a terminal `REMEDIATE_RESULT.status`, invoke it again — it re-reads GitHub state and resumes. Terminal statuses are: `COMPLETE`, `ALREADY_DONE`, `UNFIXABLE`, `BLOCKED`, `REREVIEW_REQUIRED`. `REREVIEW_REQUIRED` is terminal for the worker only: the orchestrator then runs the re-review handoff (item 6.4) or the terminal fallback, so it is never a silent end state.
|
|
2292
2314
|
|
|
2293
2315
|
Do not ask the user questions — you are running autonomously in the background."
|
|
2294
2316
|
)
|
|
@@ -2297,27 +2319,68 @@ Do not ask the user questions — you are running autonomously in the background
|
|
|
2297
2319
|
fi
|
|
2298
2320
|
```
|
|
2299
2321
|
|
|
2300
|
-
**Re-review handoff (forge#3240)**: a remediation worker can finish with `REMEDIATE_RESULT: status: REREVIEW_REQUIRED` — the fix is pushed and CI is green, but the
|
|
2322
|
+
**Re-review handoff (forge#3240)**: a remediation worker can finish with `REMEDIATE_RESULT: status: REREVIEW_REQUIRED` — the fix is pushed and CI is green, but the remediation had no sub-agent dispatch tool, so `review-pr` (which refuses to review inline) never ran. The issue is then at `workflow:in-review` WITHOUT `needs-human`, so the trigger above does not fire and the `ALREADY_REMEDIATED` guard (which counts any `FORGE:REMEDIATION`) is irrelevant. This is not a human gate, but it must never be left for a poll to find: it ends in a re-review from THIS session (which has dispatch) or in the terminal fallback below. On the next completion-monitoring cycle, for the issue that just completed, run the three steps in order. <!-- Updated: forge#3406 -->
|
|
2323
|
+
|
|
2324
|
+
**Step 1 — detect (bash; read-only, no dispatch, no marker write).** A marker counts only from a trusted author, using the same predicate as `trail_escalation_state` above (`OWNER`, the orchestrator login from `resolve_orch_login`, or a `MEMBER`/`COLLABORATOR` with admin/maintain/write permission; a failed permission lookup drops the row), and only as the comment's leading marker, never as text quoted inside another comment (forge#3412). The dispatched marker must also embed the current head SHA. A lookup error is `UNREADABLE`, never "no marker":
|
|
2301
2325
|
|
|
2302
2326
|
```bash
|
|
2303
2327
|
PRED="$NUM"
|
|
2304
|
-
REREVIEW_PR
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
#
|
|
2328
|
+
REREVIEW_STATE="NONE"; REREVIEW_PR=""; REREVIEW_SHA=""; REREVIEW_BASE=""
|
|
2329
|
+
if ! REREVIEW_PR=$(gh pr list -R {GH_REPO} --state open --search "\"Closes #${PRED}\" in:body" \
|
|
2330
|
+
--json number,body --jq '[.[] | select(.body | test("(?i)closes\\s+#'"${PRED}"'\\b"))][0].number // empty' 2>/dev/null); then
|
|
2331
|
+
REREVIEW_STATE="UNREADABLE"
|
|
2332
|
+
elif [ -n "$REREVIEW_PR" ]; then
|
|
2333
|
+
if ! PR_META=$(gh pr view "$REREVIEW_PR" -R {GH_REPO} --json headRefOid,baseRefName --jq '"\(.headRefOid) \(.baseRefName)"' 2>/dev/null) \
|
|
2334
|
+
|| ! RAW=$(gh api --paginate "repos/{GH_REPO}/issues/${REREVIEW_PR}/comments" \
|
|
2335
|
+
--jq '.[] | {body: (.body // ""), login: (.user.login // ""), assoc: (.author_association // "")}' 2>/dev/null); then
|
|
2336
|
+
REREVIEW_STATE="UNREADABLE"
|
|
2337
|
+
else
|
|
2338
|
+
REREVIEW_SHA="${PR_META%% *}"; REREVIEW_BASE="${PR_META#* }"
|
|
2339
|
+
# Trusted rows only, same predicate as trail_escalation_state (forge#3207): OWNER, the orchestrator login, or
|
|
2340
|
+
# MEMBER/COLLABORATOR with admin/maintain/write permission. A failed permission lookup drops the row (fail closed).
|
|
2341
|
+
ORCH=$(resolve_orch_login); TRUSTED_RAW=""; PERMS=""
|
|
2342
|
+
while IFS= read -r ROW; do
|
|
2343
|
+
[ -n "$ROW" ] || continue
|
|
2344
|
+
RA=$(printf '%s' "$ROW" | jq -r '.assoc'); RL=$(printf '%s' "$ROW" | jq -r '.login')
|
|
2345
|
+
if [ "$RA" = "OWNER" ] || { [ -n "$ORCH" ] && [ "$(printf '%s' "$RL" | tr '[:upper:]' '[:lower:]')" = "$(printf '%s' "$ORCH" | tr '[:upper:]' '[:lower:]')" ]; }; then
|
|
2346
|
+
TRUSTED_RAW="${TRUSTED_RAW}${ROW}"$'\n'; continue
|
|
2347
|
+
fi
|
|
2348
|
+
case "$RA" in MEMBER|COLLABORATOR) ;; *) continue ;; esac
|
|
2349
|
+
RP=$(printf '%s\n' "$PERMS" | awk -v l="$RL" '$1==l{print $2; exit}')
|
|
2350
|
+
if [ -z "$RP" ]; then RP=$(gh api "repos/{GH_REPO}/collaborators/${RL}/permission" --jq '.permission' 2>/dev/null || true); [ -n "$RP" ] || RP="none"; PERMS="${PERMS}${RL} ${RP}"$'\n'; fi
|
|
2351
|
+
case "$RP" in admin|maintain|write) TRUSTED_RAW="${TRUSTED_RAW}${ROW}"$'\n' ;; esac
|
|
2352
|
+
done < <(printf '%s\n' "$RAW" | jq -c '.' 2>/dev/null)
|
|
2353
|
+
# Leading-marker match only (forge#3412): remediation trail comments start with <!-- FORGE:REMEDIATION -->.
|
|
2354
|
+
NEEDS_REREVIEW=$(printf '%s' "$TRUSTED_RAW" | jq -s '[.[] | select((.body | startswith("<!-- FORGE:REMEDIATION -->")) and (.body | contains("<!-- FORGE:REMEDIATION:COMPLETE -->")) and (.body | contains("REREVIEW-REQUIRED")))] | length' 2>/dev/null) || NEEDS_REREVIEW=""
|
|
2355
|
+
REREVIEW_DONE=$(printf '%s' "$TRUSTED_RAW" | jq -s --arg sha "$REREVIEW_SHA" '[.[] | select((.body | startswith("<!-- FORGE:REREVIEW_DISPATCHED -->")) and (.body | contains($sha)))] | length' 2>/dev/null) || REREVIEW_DONE=""
|
|
2356
|
+
if [ -z "$NEEDS_REREVIEW" ] || [ -z "$REREVIEW_DONE" ]; then REREVIEW_STATE="UNREADABLE"
|
|
2357
|
+
elif [ "$NEEDS_REREVIEW" -ge 1 ] && [ "$REREVIEW_DONE" -eq 0 ] && [ "${DRY_RUN:-false}" != "true" ]; then REREVIEW_STATE="PENDING"
|
|
2358
|
+
fi
|
|
2316
2359
|
fi
|
|
2317
2360
|
fi
|
|
2361
|
+
echo "REREVIEW_STATE=$REREVIEW_STATE PR=$REREVIEW_PR SHA=$REREVIEW_SHA BASE=$REREVIEW_BASE"
|
|
2362
|
+
```
|
|
2363
|
+
|
|
2364
|
+
`REREVIEW_STATE=NONE` means nothing to do. `UNREADABLE` fails closed: classify the issue `GATED` this cycle without writing anything, and re-run Step 1 next cycle. Only `PENDING` continues.
|
|
2365
|
+
|
|
2366
|
+
**Step 2 — dispatch (a real call, not part of the bash block above).** Invoke, with the `REREVIEW_PR`, `REREVIEW_BASE` and `PRED` values Step 1 printed:
|
|
2367
|
+
|
|
2368
|
+
```
|
|
2369
|
+
if DRY_RUN=true:
|
|
2370
|
+
record "Would re-review PR #${REREVIEW_PR} with review-pr --auto-merge; skipped (dry-run)."
|
|
2371
|
+
else:
|
|
2372
|
+
Skill(skill="{FORGE_SKILL_PREFIX}review-pr", args="${REREVIEW_PR} --auto-merge --issue ${PRED} --base ${REREVIEW_BASE} --gh-flag -R {GH_REPO}")
|
|
2373
|
+
```
|
|
2374
|
+
|
|
2375
|
+
If the call returns no `REVIEW_RESULT` (interrupted or no result), invoke it once more; this retry is the only one (bounded, independent of the Phase 4R `github-unavailable` waits). Then post the marker AFTER the dispatch, so an interrupted session never leaves a marker that blocks a retry:
|
|
2376
|
+
|
|
2377
|
+
```bash
|
|
2378
|
+
[ "${DRY_RUN:-false}" = "true" ] && { echo "[DRY_RUN] would post FORGE:REREVIEW_DISPATCHED on PR #${REREVIEW_PR}"; exit 0; }
|
|
2379
|
+
gh pr comment "$REREVIEW_PR" -R {GH_REPO} --body "<!-- FORGE:REREVIEW_DISPATCHED -->
|
|
2380
|
+
Re-review dispatched by the orchestrator at head ${REREVIEW_SHA}: remediation had no sub-agent dispatch tool."
|
|
2318
2381
|
```
|
|
2319
2382
|
|
|
2320
|
-
|
|
2383
|
+
**Step 3 — outcome.** On `REVIEW_RESULT: status: COMPLETE` (merged), drive `work-on:close` and let item 6.6 wake dependents as normal. If `review-pr` returns another result with its own labelled terminal state (CHANGES REQUESTED, or `needs-human` for genuine blockers), that verdict applies and the issue is `GATED` or failed per the existing rules. If dispatch failed, the skill did not resolve, or the issue is still at `workflow:in-review` with no `needs-human` after the retry, apply the **terminal fallback** defined in `commands/work-on.md` Phase 0A.1 (comment with the reason, add `needs-human` and remove `workflow:in-review` in one edit, verify the write), classify the issue `GATED`, and surface it to the operator in the run summary as `GATED: re-review could not run (#{PRED}, PR #{REREVIEW_PR}): <reason>`. A failed label write is reported as such, not as done. The marker bounds this to one re-review per PR head (no loop). Never review inline.
|
|
2321
2384
|
|
|
2322
2385
|
This satisfies #1809 Q2 (the orchestrator auto-dispatches remediation against the gated issue itself — the exact gap forge#1812's item 6.5/6.6 left open, since those items only ever track and wake *dependents*, never the gated PR's own remediation) — and closes forge#2243 (the gap that #1812's fix left open for *leaf* issues with no dependents: because this item's `$PRED` binding was never made explicit and self-contained, it was only ever reached while walking a dependent's predecessor list, so a `needs-human` issue that has no dependents never got remediation dispatched and its CHANGES-REQUESTED PR re-reviewed the same unchanged commit forever). The remediation agent's outcome is picked up on the **next** completion-monitoring cycle of this same Step 4B loop: if it lands (`workflow:merged`), item 6.6 below fires normally and wakes any `blocked-on-human-merge` dependents (if any exist — a leaf issue simply has none to wake); if it holds/re-escalates, the issue simply remains `GATED` and item 6.5 continues tracking its dependents (if any) unchanged.
|
|
2323
2386
|
|
|
@@ -240,7 +240,7 @@ Note the marker is `<!-- FORGE:REMEDIATION -->` with **no** `:COMPLETE` suffix y
|
|
|
240
240
|
|
|
241
241
|
**Dispatch-tool probe (forge#3240 — run FIRST)**: `review-pr` must launch its domain review agents through a sub-agent dispatch tool and refuses to review inline. This only fails when remediation was invoked deeper than the router allows (see `docs/WORK-ON-RUNTIME.md`); invoked from the router, a dispatch tool is available, so the branch below is a safety net. Resolve the tool with the identical order `commands/review-pr.md` § "Sub-Agent Dispatch Tool Resolution" uses (`Task`, then `Agent`; OpenCode uses `task`). Do not copy or weaken that section, and never review inline here.
|
|
242
242
|
|
|
243
|
-
If no dispatch tool resolves, a missing tool is not a human decision, so do NOT invoke `review-pr`, do NOT add `needs-human`, and leave `workflow:in-review` in place. Set `RE_GATE_OUTCOME="REREVIEW-REQUIRED"`, skip Phase M7, go to Phase M8 (which posts `FORGE:REMEDIATION:COMPLETE` with a `REREVIEW-REQUIRED` re-gate line), and return `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`. The caller re-runs `/review-pr {PR_NUMBER} --auto-merge --issue {ISSUE_NUMBER} --base {PR_BASE}` from a session that has dispatch. If a dispatch tool resolves, continue below.
|
|
243
|
+
If no dispatch tool resolves, a missing tool is not a human decision, so do NOT invoke `review-pr`, do NOT add `needs-human`, and leave `workflow:in-review` in place. Set `RE_GATE_OUTCOME="REREVIEW-REQUIRED"`, skip Phase M7, go to Phase M8 (which posts `FORGE:REMEDIATION:COMPLETE` with a `REREVIEW-REQUIRED` re-gate line), and return `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`. The caller re-runs `/review-pr {PR_NUMBER} --auto-merge --issue {ISSUE_NUMBER} --base {PR_BASE}` from a session that has dispatch. The caller owns the terminal fallback if that re-review cannot run (`commands/work-on.md` Phase 0A.1); remediation itself stays single-attempt and adds no `needs-human` here. If a dispatch tool resolves, continue below.
|
|
244
244
|
|
|
245
245
|
```
|
|
246
246
|
if DRY_RUN=true:
|
|
@@ -454,7 +454,7 @@ Skill("{FORGE_SKILL_PREFIX}work-on:close", args="{ISSUE_NUMBER} --repo {GH_REPO}
|
|
|
454
454
|
|
|
455
455
|
`work-on:close` handles project board update, final issue body, parent tracker, trajectory log, and worktree cleanup (including the remediation worktree at `{WORKTREE_PATH}`) — do not duplicate any of that here.
|
|
456
456
|
|
|
457
|
-
**If the outcome was `REREVIEW-REQUIRED`** (forge#3240): do not invoke close and do not add `needs-human`. Leave the worktree and `workflow:in-review` in place and return `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`; the caller runs the re-review and, on `AUTO-LANDED`, drives close itself.
|
|
457
|
+
**If the outcome was `REREVIEW-REQUIRED`** (forge#3240): do not invoke close and do not add `needs-human`. Leave the worktree and `workflow:in-review` in place and return `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`; the caller runs the re-review and, on `AUTO-LANDED`, drives close itself; if the re-review cannot run, the caller applies the terminal fallback (`commands/work-on.md` Phase 0A.1).
|
|
458
458
|
|
|
459
459
|
**If the outcome was `HELD-AWAITING-MERGE`, `RE-ESCALATED`, or `UNFIXABLE`**: leave the worktree in place (a human may need it for manual inspection/merge) and return the structured result below without invoking close. Do not close the issue.
|
|
460
460
|
|
package/commands/work-on.md
CHANGED
|
@@ -294,7 +294,9 @@ If detected, dispatch immediately and STOP — do NOT fall through to Phase 0B's
|
|
|
294
294
|
Skill(skill="{FORGE_SKILL_PREFIX}work-on:remediate", args="${REMEDIATE_PR_NUMBER} ${REMEDIATE_ISSUE_FLAG} --repo {GH_REPO} --gh-flag {GH_FLAG}")
|
|
295
295
|
```
|
|
296
296
|
|
|
297
|
-
**If `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`** (forge#3240, fallback only since forge#3398: fix pushed, but remediation had no sub-agent dispatch tool, which cannot happen when the Phase 0A spawn-depth preflight passed and remediation is invoked from this router): run the re-review from this top-level session, which has dispatch — `Skill(skill="{FORGE_SKILL_PREFIX}review-pr", args="${REMEDIATE_PR_NUMBER} --auto-merge --issue ${ISSUE} --base ${PR_BASE} --gh-flag {GH_FLAG}")` (`ISSUE` and `PR_BASE` from the result and the PR) — never review inline. If it returns `REVIEW_RESULT: status: COMPLETE` (merged), invoke `Skill("{FORGE_SKILL_PREFIX}work-on:close", ...)` as remediate M8 does for `AUTO-LANDED`. Then STOP.
|
|
297
|
+
**If `REMEDIATE_RESULT: status: REREVIEW_REQUIRED`** (forge#3240, fallback only since forge#3398: fix pushed, but remediation had no sub-agent dispatch tool, which cannot happen when the Phase 0A spawn-depth preflight passed and remediation is invoked from this router): run the re-review from this top-level session, which has dispatch — `Skill(skill="{FORGE_SKILL_PREFIX}review-pr", args="${REMEDIATE_PR_NUMBER} --auto-merge --issue ${ISSUE} --base ${PR_BASE} --gh-flag {GH_FLAG}")` (`ISSUE` and `PR_BASE` from the result and the PR) — never review inline. If it returns `REVIEW_RESULT: status: COMPLETE` (merged), invoke `Skill("{FORGE_SKILL_PREFIX}work-on:close", ...)` as remediate M8 does for `AUTO-LANDED`. If the `review-pr` skill does not resolve, cannot dispatch, or returns anything other than `REVIEW_RESULT: status: COMPLETE` while the issue is still at `workflow:in-review` with no `needs-human` (no state anything will advance), apply the **terminal fallback**. Single attempt: no retry loop, no polling. Then STOP. <!-- Added: forge#3406 -->
|
|
298
|
+
|
|
299
|
+
**Terminal fallback** (canonical definition; Phase 4R and `commands/orchestrate/phase-4-execution.md` item 6.4 reference it, so the review and remediate paths share one): a re-review that cannot run must never leave the issue at `workflow:in-review` with nothing to advance it. Post a comment naming the PR and the reason (e.g. `review-pr could not be dispatched: <reason>`), then in ONE `gh issue edit` add `needs-human` and remove `workflow:in-review` (never one without the other), and re-read the labels to verify the write. If the label write failed, report that failure as the outcome instead of treating the fallback as done. Never review inline, and never re-nest remediation to retry.
|
|
298
300
|
|
|
299
301
|
**After `REMEDIATE_RESULT` returns (any other status), STOP unconditionally** — do not run any further Phase 0–7 logic in this file. `work-on/remediate.md` is self-contained: a FIXABLE remediation replaces `needs-human` with the active `workflow:in-review` state only while it is running, then ends at `workflow:merged`, `workflow:awaiting-merge`, or a newly asserted `needs-human` label. When `re_gate_outcome: AUTO-LANDED`, it drives its own close phase internally (Phase M8 invokes `Skill("{FORGE_SKILL_PREFIX}work-on:close", ...)` directly) before returning. For every other outcome (`HELD-AWAITING-MERGE`, `RE-ESCALATED`, `UNFIXABLE`, `BLOCKED`, `ALREADY_DONE`), the issue is already at a terminal state (`workflow:awaiting-merge` or `needs-human`, or already closed) per the Universal Phase Dispatcher — nothing further to do.
|
|
300
302
|
|
|
@@ -750,7 +752,7 @@ Skill(skill="{FORGE_SKILL_PREFIX}work-on:remediate", args="{PR_NUMBER} --issue {
|
|
|
750
752
|
| `REMEDIATE_RESULT` | Router action |
|
|
751
753
|
|---|---|
|
|
752
754
|
| `re_gate_outcome: AUTO-LANDED` | Merged. Remediation's Phase M8 already ran `work-on:close`; if the issue is still open, run Phase 5 with `--terminal-state merged`. Then done. |
|
|
753
|
-
| `status: REREVIEW_REQUIRED` | Fallback only (should not occur at this depth): run the re-review from this router as in 0A.1, then Phase 5 on `REVIEW_RESULT: status: COMPLETE`. |
|
|
755
|
+
| `status: REREVIEW_REQUIRED` | Fallback only (should not occur at this depth): run the re-review from this router as in 0A.1, then Phase 5 on `REVIEW_RESULT: status: COMPLETE`. If the re-review cannot run or returns anything else, apply the terminal fallback defined in 0A.1 (comment with reason, add `needs-human`, remove `workflow:in-review`), then STOP; do not poll. |
|
|
754
756
|
| `status: BLOCKED`, blocker starts with `github-unavailable:` | Transient, not a decision (see Transient GitHub failures). Re-add `needs-human` with a short comment (remediation's Phase M0 only accepts `needs-human`-gated issues and its M1 clears the label for a FIXABLE run), wait 2 min (5 min before the second retry), then re-invoke `work-on:remediate` with the same args; do NOT re-post the bound marker. At most 2 retries; if the third attempt still returns `github-unavailable:`, fall through to the `status: BLOCKED` (any kind) row below. |
|
|
755
757
|
| `status: BLOCKED` (any kind) | Make sure `needs-human` is on the issue (add it with the blocker as a comment if absent: remediation can exit after its M1 cleared the label). STOP. |
|
|
756
758
|
| `status: ALREADY_DONE` (single-attempt guard: an earlier remediation already completed on this PR), `remediation: inpr-fix` | Same as any other `inpr-fix` outcome below: re-invoke Phase 4 once, which waives the in-PR gate. |
|
|
@@ -781,7 +783,7 @@ Omit `--pr/--branch/--worktree` when the value is unknown (PR-less terminals).
|
|
|
781
783
|
|
|
782
784
|
## Remediation entry (`--remediate`)
|
|
783
785
|
|
|
784
|
-
Handled in Phase 0A.1: `/work-on <pr> --remediate [--issue N]` dispatches `Skill(skill="{FORGE_SKILL_PREFIX}work-on:remediate", ...)` (forked) and STOPS after its `REMEDIATE_RESULT`, except that `REREVIEW_REQUIRED` makes the router run `review-pr` itself first (see 0A.1).
|
|
786
|
+
Handled in Phase 0A.1: `/work-on <pr> --remediate [--issue N]` dispatches `Skill(skill="{FORGE_SKILL_PREFIX}work-on:remediate", ...)` (forked) and STOPS after its `REMEDIATE_RESULT`, except that `REREVIEW_REQUIRED` makes the router run `review-pr` itself first, with the terminal fallback if that cannot run (see 0A.1).
|
|
785
787
|
|
|
786
788
|
---
|
|
787
789
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forgedock",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"description": "Autonomous development pipeline for coding agents. GitHub as institutional memory, with native Claude Code and OpenCode entrypoints.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forgedock": "bin/forgedock.mjs"
|