@windyroad/itil 1.2.0 → 2.0.0-preview.1111
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/.agents/plugins/marketplace.json +12 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +42 -0
- package/README.md +34 -25
- package/agents/hang-off-check.md +34 -34
- package/bin/install.mjs +71 -5
- package/bin/wr-itil-catchup-scan +4 -4
- package/bin/wr-itil-check-deferred-placeholder-staleness +4 -4
- package/bin/wr-itil-check-fail-soft-skip-discipline +4 -4
- package/bin/wr-itil-check-fix-rfc-trace +4 -4
- package/bin/wr-itil-check-locale-discipline +4 -4
- package/bin/wr-itil-check-outbound-responses-staleness +4 -4
- package/bin/wr-itil-check-problems-readme-budget +4 -4
- package/bin/wr-itil-check-rfc-has-stories +4 -4
- package/bin/wr-itil-check-rfc-stories-ratified +4 -4
- package/bin/wr-itil-check-ticket-jtbd-ratification +4 -4
- package/bin/wr-itil-check-upstream-cache-staleness +4 -4
- package/bin/wr-itil-check-upstream-responses +4 -4
- package/bin/wr-itil-classify-readme-drift +4 -4
- package/bin/wr-itil-derive-release-vehicle +4 -4
- package/bin/wr-itil-detect-unratified-stories-maps +4 -4
- package/bin/wr-itil-effort-tally +4 -4
- package/bin/wr-itil-enumerate-postrelease-kv-candidates +4 -4
- package/bin/wr-itil-evaluate-relevance +4 -4
- package/bin/wr-itil-mark-create-gate +4 -4
- package/bin/wr-itil-mark-story-oversight-confirmed +4 -4
- package/bin/wr-itil-migrate-problems-layout +4 -4
- package/bin/wr-itil-migrate-story-status-mirror +4 -4
- package/bin/wr-itil-next-rfc-id +4 -4
- package/bin/wr-itil-plugin-exercise-index +4 -4
- package/bin/wr-itil-plugin-maturity-populate +4 -4
- package/bin/wr-itil-plugin-maturity-render +4 -4
- package/bin/wr-itil-plugin-validate-ci-gate +4 -4
- package/bin/wr-itil-reconcile-readme +4 -4
- package/bin/wr-itil-reconcile-rfcs +4 -4
- package/bin/wr-itil-reconcile-stories +4 -4
- package/bin/wr-itil-reconcile-story-maps +4 -4
- package/bin/wr-itil-render-story-map +4 -4
- package/bin/wr-itil-resolve-governance-plugin-dirs +4 -4
- package/bin/wr-itil-skill-invocations +4 -4
- package/bin/wr-itil-story-map-edit +4 -4
- package/bin/wr-itil-story-map-query +4 -4
- package/bin/wr-itil-update-jtbd-references-section +4 -4
- package/bin/wr-itil-update-problem-references-section +4 -4
- package/bin/wr-itil-update-problem-rfcs-section +4 -4
- package/bin/wr-itil-update-rfc-commits-section +4 -4
- package/bin/wr-itil-update-rfc-references-section +4 -4
- package/bin/wr-itil-verify-iter-summary +4 -4
- package/hooks/itil-assistant-output-gate.sh +3 -3
- package/hooks/itil-assistant-output-review.sh +5 -5
- package/hooks/itil-bash-polling-antipattern-detect.sh +11 -11
- package/hooks/itil-changeset-discipline.sh +24 -24
- package/hooks/itil-claude-space-protection.sh +21 -14
- package/hooks/itil-codex-dispatch.sh +164 -0
- package/hooks/itil-commit-trailer-transition-advisory.sh +11 -11
- package/hooks/itil-correction-detect.sh +8 -8
- package/hooks/itil-deferral-cadence-gate.sh +23 -23
- package/hooks/itil-fictional-defer-detect.sh +16 -16
- package/hooks/itil-fix-title-lifecycle-advisory.sh +11 -11
- package/hooks/itil-mid-loop-ask-detect.sh +14 -14
- package/hooks/itil-no-implement-draft-gate.sh +18 -18
- package/hooks/itil-pending-questions-surface.sh +11 -11
- package/hooks/itil-readme-refresh-discipline.sh +27 -27
- package/hooks/itil-rfc-oversight-nudge.sh +7 -7
- package/hooks/itil-rfc-trailer-advisory.sh +28 -28
- package/hooks/itil-runtime-sid-marker.sh +11 -11
- package/hooks/itil-story-mirror-migration-nudge.sh +7 -7
- package/hooks/lib/block-list.sh +17 -17
- package/hooks/lib/changeset-detect.sh +27 -27
- package/hooks/lib/claude-space-gate.sh +23 -15
- package/hooks/lib/command-detect.sh +12 -12
- package/hooks/lib/create-gate.sh +9 -39
- package/hooks/lib/detectors.sh +12 -12
- package/hooks/lib/readme-refresh-detect.sh +51 -51
- package/hooks/lib/runtime-sid.sh +12 -12
- package/hooks/lib/session-id.sh +28 -28
- package/hooks/lib/session-marker.sh +1 -1
- package/hooks/lib/staging-detect.sh +13 -13
- package/hooks/manage-problem-enforce-create.sh +16 -27
- package/hooks/p057-staging-trap-detect.sh +18 -18
- package/hooks/pre-publish-intake-gate.sh +5 -5
- package/hooks/staleness-check.sh +6 -6
- package/hooks-codex/hooks.json +57 -0
- package/lib/check-deferred-placeholder-staleness.sh +10 -10
- package/lib/check-outbound-responses-staleness.sh +2 -2
- package/lib/check-upstream-cache-staleness.sh +2 -2
- package/lib/derive-first-dispatch.sh +19 -19
- package/lib/enumerate-postrelease-kv-candidates.sh +18 -18
- package/lib/migrate-problems-layout.sh +12 -12
- package/lib/story-oversight.sh +27 -27
- package/package.json +16 -3
- package/scripts/catchup-scan.sh +25 -25
- package/scripts/check-fail-soft-skip-discipline.sh +10 -10
- package/scripts/check-fix-rfc-trace.sh +8 -8
- package/scripts/check-locale-discipline.sh +13 -13
- package/scripts/check-problems-readme-budget.sh +12 -12
- package/scripts/check-rfc-has-stories.sh +7 -7
- package/scripts/check-rfc-rejected-alternatives.sh +11 -11
- package/scripts/check-rfc-stories-ratified.sh +9 -9
- package/scripts/check-ticket-jtbd-ratification.sh +10 -10
- package/scripts/check-upstream-responses.sh +22 -22
- package/scripts/classify-readme-drift.sh +13 -13
- package/scripts/codex-agent.mjs +104 -0
- package/scripts/derive-release-vehicle.sh +23 -23
- package/scripts/detect-unoversighted-rfcs.sh +3 -3
- package/scripts/detect-unratified-stories-maps.sh +5 -5
- package/scripts/effort-tally.sh +10 -10
- package/scripts/evaluate-relevance.sh +16 -16
- package/scripts/mark-create-gate.sh +4 -4
- package/scripts/mark-story-oversight-confirmed.sh +14 -14
- package/scripts/migrate-story-status-mirror.sh +6 -6
- package/scripts/next-rfc-id.sh +5 -5
- package/scripts/plugin-exercise-index.sh +26 -26
- package/scripts/plugin-maturity-populate.sh +38 -38
- package/scripts/plugin-maturity-render.sh +26 -26
- package/scripts/plugin-validate-ci-gate.sh +14 -14
- package/scripts/reconcile-readme.sh +23 -23
- package/scripts/reconcile-rfcs.sh +13 -13
- package/scripts/reconcile-stories.sh +12 -12
- package/scripts/reconcile-story-maps.sh +6 -6
- package/scripts/render-story-map.mjs +24 -24
- package/scripts/render-story-map.sh +3 -3
- package/scripts/resolve-governance-plugin-dirs.sh +10 -10
- package/scripts/run-check-deferred-placeholder-staleness.sh +3 -3
- package/scripts/run-check-outbound-responses-staleness.sh +3 -3
- package/scripts/run-check-upstream-cache-staleness.sh +3 -3
- package/scripts/run-enumerate-postrelease-kv-candidates.sh +3 -3
- package/scripts/run-migrate-problems-layout.sh +3 -3
- package/scripts/skill-invocations.sh +29 -29
- package/scripts/story-map-edit.mjs +6 -6
- package/scripts/story-map-edit.sh +3 -3
- package/scripts/story-map-query.mjs +8 -8
- package/scripts/story-map-query.sh +3 -3
- package/scripts/update-jtbd-references-section.sh +8 -8
- package/scripts/update-problem-references-section.sh +12 -12
- package/scripts/update-problem-rfcs-section.sh +9 -9
- package/scripts/update-rfc-commits-section.sh +7 -7
- package/scripts/update-rfc-references-section.sh +3 -3
- package/scripts/update-story-references-section.sh +5 -5
- package/scripts/verify-iter-summary.sh +3 -3
- package/skills/capture-problem/REFERENCE.md +33 -33
- package/skills/capture-problem/SKILL.md +108 -108
- package/skills/capture-problem/agents/openai.yaml +3 -0
- package/skills/capture-rfc/SKILL.md +21 -323
- package/skills/capture-rfc/agents/openai.yaml +3 -0
- package/skills/capture-story/SKILL.md +65 -65
- package/skills/capture-story/agents/openai.yaml +3 -0
- package/skills/capture-story-map/SKILL.md +31 -31
- package/skills/capture-story-map/agents/openai.yaml +3 -0
- package/skills/check-upstream-responses/SKILL.md +38 -38
- package/skills/check-upstream-responses/agents/openai.yaml +3 -0
- package/skills/close-incident/SKILL.md +25 -25
- package/skills/close-incident/agents/openai.yaml +3 -0
- package/skills/link-incident/SKILL.md +22 -22
- package/skills/link-incident/agents/openai.yaml +3 -0
- package/skills/list-incidents/SKILL.md +9 -9
- package/skills/list-incidents/agents/openai.yaml +3 -0
- package/skills/list-problems/SKILL.md +17 -17
- package/skills/list-problems/agents/openai.yaml +3 -0
- package/skills/list-stories/SKILL.md +23 -23
- package/skills/list-stories/agents/openai.yaml +3 -0
- package/skills/list-story-maps/SKILL.md +9 -9
- package/skills/list-story-maps/agents/openai.yaml +3 -0
- package/skills/manage-incident/SKILL.md +59 -59
- package/skills/manage-incident/agents/openai.yaml +3 -0
- package/skills/manage-problem/SKILL.md +222 -222
- package/skills/manage-problem/agents/openai.yaml +3 -0
- package/skills/manage-rfc/SKILL.md +62 -62
- package/skills/manage-rfc/agents/openai.yaml +3 -0
- package/skills/manage-story/SKILL.md +49 -49
- package/skills/manage-story/agents/openai.yaml +3 -0
- package/skills/manage-story-map/SKILL.md +30 -30
- package/skills/manage-story-map/agents/openai.yaml +3 -0
- package/skills/mitigate-incident/SKILL.md +40 -40
- package/skills/mitigate-incident/agents/openai.yaml +3 -0
- package/skills/reconcile-readme/SKILL.md +28 -28
- package/skills/reconcile-readme/agents/openai.yaml +3 -0
- package/skills/reconcile-stories/SKILL.md +17 -17
- package/skills/reconcile-stories/agents/openai.yaml +3 -0
- package/skills/reconcile-story-maps/SKILL.md +11 -11
- package/skills/reconcile-story-maps/agents/openai.yaml +3 -0
- package/skills/report-upstream/SKILL.md +73 -73
- package/skills/report-upstream/agents/openai.yaml +3 -0
- package/skills/restore-incident/SKILL.md +28 -28
- package/skills/restore-incident/agents/openai.yaml +3 -0
- package/skills/review-problems/SKILL.md +129 -129
- package/skills/review-problems/agents/openai.yaml +3 -0
- package/skills/scaffold-intake/SKILL.md +26 -26
- package/skills/scaffold-intake/agents/openai.yaml +3 -0
- package/skills/transition-problem/SKILL.md +85 -85
- package/skills/transition-problem/agents/openai.yaml +3 -0
- package/skills/transition-problems/SKILL.md +69 -69
- package/skills/transition-problems/agents/openai.yaml +3 -0
- package/skills/update-upstream/SKILL.md +97 -97
- package/skills/update-upstream/agents/openai.yaml +3 -0
- package/skills/work-problem/SKILL.md +42 -42
- package/skills/work-problem/agents/openai.yaml +3 -0
- package/skills/work-problems/SKILL.md +327 -327
- package/skills/work-problems/agents/openai.yaml +3 -0
- package/skills-codex/capture-problem/REFERENCE.md +139 -0
- package/skills-codex/capture-problem/SKILL.md +438 -0
- package/skills-codex/capture-problem/agents/openai.yaml +3 -0
- package/skills-codex/capture-rfc/SKILL.md +45 -0
- package/skills-codex/capture-rfc/agents/openai.yaml +3 -0
- package/skills-codex/capture-story/SKILL.md +407 -0
- package/skills-codex/capture-story/agents/openai.yaml +3 -0
- package/skills-codex/capture-story-map/SKILL.md +286 -0
- package/skills-codex/capture-story-map/agents/openai.yaml +3 -0
- package/skills-codex/check-upstream-responses/SKILL.md +160 -0
- package/skills-codex/check-upstream-responses/agents/openai.yaml +3 -0
- package/skills-codex/close-incident/SKILL.md +192 -0
- package/skills-codex/close-incident/agents/openai.yaml +3 -0
- package/skills-codex/link-incident/SKILL.md +173 -0
- package/skills-codex/link-incident/agents/openai.yaml +3 -0
- package/skills-codex/list-incidents/SKILL.md +92 -0
- package/skills-codex/list-incidents/agents/openai.yaml +3 -0
- package/skills-codex/list-problems/SKILL.md +126 -0
- package/skills-codex/list-problems/agents/openai.yaml +3 -0
- package/skills-codex/list-stories/SKILL.md +170 -0
- package/skills-codex/list-stories/agents/openai.yaml +3 -0
- package/skills-codex/list-story-maps/SKILL.md +104 -0
- package/skills-codex/list-story-maps/agents/openai.yaml +3 -0
- package/skills-codex/manage-incident/SKILL.md +378 -0
- package/skills-codex/manage-incident/agents/openai.yaml +3 -0
- package/skills-codex/manage-problem/SKILL.md +1180 -0
- package/skills-codex/manage-problem/agents/openai.yaml +3 -0
- package/skills-codex/manage-rfc/SKILL.md +314 -0
- package/skills-codex/manage-rfc/agents/openai.yaml +3 -0
- package/skills-codex/manage-story/SKILL.md +284 -0
- package/skills-codex/manage-story/agents/openai.yaml +3 -0
- package/skills-codex/manage-story-map/SKILL.md +198 -0
- package/skills-codex/manage-story-map/agents/openai.yaml +3 -0
- package/skills-codex/mitigate-incident/SKILL.md +239 -0
- package/skills-codex/mitigate-incident/agents/openai.yaml +3 -0
- package/skills-codex/reconcile-readme/SKILL.md +175 -0
- package/skills-codex/reconcile-readme/agents/openai.yaml +3 -0
- package/skills-codex/reconcile-stories/SKILL.md +124 -0
- package/skills-codex/reconcile-stories/agents/openai.yaml +3 -0
- package/skills-codex/reconcile-story-maps/SKILL.md +81 -0
- package/skills-codex/reconcile-story-maps/agents/openai.yaml +3 -0
- package/skills-codex/report-upstream/SKILL.md +716 -0
- package/skills-codex/report-upstream/agents/openai.yaml +3 -0
- package/skills-codex/restore-incident/SKILL.md +216 -0
- package/skills-codex/restore-incident/agents/openai.yaml +3 -0
- package/skills-codex/review-problems/SKILL.md +524 -0
- package/skills-codex/review-problems/agents/openai.yaml +3 -0
- package/skills-codex/scaffold-intake/SKILL.md +209 -0
- package/skills-codex/scaffold-intake/agents/openai.yaml +3 -0
- package/skills-codex/scaffold-intake/templates/CONTRIBUTING.md.tmpl +31 -0
- package/skills-codex/scaffold-intake/templates/SECURITY.md.tmpl +39 -0
- package/skills-codex/scaffold-intake/templates/SUPPORT.md.tmpl +32 -0
- package/skills-codex/scaffold-intake/templates/config.yml.tmpl +8 -0
- package/skills-codex/scaffold-intake/templates/problem-report.yml.tmpl +114 -0
- package/skills-codex/transition-problem/SKILL.md +371 -0
- package/skills-codex/transition-problem/agents/openai.yaml +3 -0
- package/skills-codex/transition-problems/SKILL.md +310 -0
- package/skills-codex/transition-problems/agents/openai.yaml +3 -0
- package/skills-codex/update-upstream/SKILL.md +583 -0
- package/skills-codex/update-upstream/agents/openai.yaml +3 -0
- package/skills-codex/work-problem/SKILL.md +160 -0
- package/skills-codex/work-problem/agents/openai.yaml +3 -0
- package/skills-codex/work-problems/SKILL.md +58 -0
- package/skills-codex/work-problems/agents/openai.yaml +3 -0
- package/templates/story-map.css +1 -1
- package/bin/wr-itil-mark-rfc-capture-gate +0 -51
- package/scripts/mark-rfc-capture-gate.sh +0 -32
|
@@ -14,9 +14,9 @@ The user is AFK during this process, so every decision point that would normally
|
|
|
14
14
|
|
|
15
15
|
Each iteration is one cycle of: scan backlog, pick highest-WSJF problem, work it, report result. The loop continues until a stop condition is met.
|
|
16
16
|
|
|
17
|
-
## First-run intake-scaffold pointer (
|
|
17
|
+
## First-run intake-scaffold pointer (the "Problem 065: No skill scaffolds intake files (ISSUE_TEMPLATE, SECURITY.md, CONTRIBUTING.md, SUPPORT.md) in downstream projects" problem / the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule)
|
|
18
18
|
|
|
19
|
-
This skill is one of the two host skills wired to surface the [`/wr-itil:scaffold-intake`](../scaffold-intake/SKILL.md) skill on first invocation in a project that has not yet adopted the OSS intake surface. The contract is documented in [
|
|
19
|
+
This skill is one of the two host skills wired to surface the [`/wr-itil:scaffold-intake`](../scaffold-intake/SKILL.md) skill on first invocation in a project that has not yet adopted the OSS intake surface. The contract is documented in [the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule](../../../../docs/decisions/036-scaffold-downstream-oss-intake.proposed.md) (Scaffold downstream OSS intake — skill + layered triggers).
|
|
20
20
|
|
|
21
21
|
**Preamble check** (run once at session start, before Step 0 of the loop):
|
|
22
22
|
|
|
@@ -28,17 +28,17 @@ If any intake file is missing AND both markers are absent: this skill is **alway
|
|
|
28
28
|
|
|
29
29
|
- Do **not** fire `AskUserQuestion`.
|
|
30
30
|
- Do **not** auto-scaffold.
|
|
31
|
-
- Append a one-line `"pending intake scaffold"` note to the iteration's `ITERATION_SUMMARY` notes field. The note is a per-iteration audit trail signal — accumulating one line per AFK iter is acceptable per
|
|
31
|
+
- Append a one-line `"pending intake scaffold"` note to the iteration's `ITERATION_SUMMARY` notes field. The note is a per-iteration audit trail signal — accumulating one line per AFK iter is acceptable per the "Scaffold downstream OSS intake — skill + layered triggers" architecture rule § Bad consequences and the ": Progress the Backlog While I'm Away" user outcome "audit trail — every action taken during AFK mode should be traceable".
|
|
32
32
|
|
|
33
|
-
The user reviews the pending note on their next interactive session and runs `/wr-itil:scaffold-intake` (or `/wr-itil:manage-problem` with the foreground prompt branch) at that point.
|
|
33
|
+
The user reviews the pending note on their next interactive session and runs `/wr-itil:scaffold-intake` (or `/wr-itil:manage-problem` with the foreground prompt branch) at that point. the ": Progress the Backlog While I'm Away" user outcome forbids the agent from making this judgement call autonomously.
|
|
34
34
|
|
|
35
|
-
### Step 0: Preflight (per
|
|
35
|
+
### Step 0: Preflight (per the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule)
|
|
36
36
|
|
|
37
|
-
Before opening the work loop, **get the repo into a clean state** so the orchestrator does not iterate against a stale backlog, silently strand prior-session in-flight work, or proceed past an ambiguously-dirty tree (
|
|
37
|
+
Before opening the work loop, **get the repo into a clean state** so the orchestrator does not iterate against a stale backlog, silently strand prior-session in-flight work, or proceed past an ambiguously-dirty tree (the "Problem 040: work-problems does not fetch origin before starting" problem, the "`/wr-itil:work-problems` preflight Step 0 does not detect prior-session partial-work state (untracked ADRs, `.afk-run-state/iter-*.json` with 429/error statuses, existing `.claude/worktrees/*` branches)" problem, the "Generalise preflight from "fetch + ff-only divergence" to "get the repo into a clean state before starting"" problem). the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule names three branches under the umbrella goal:
|
|
38
38
|
|
|
39
39
|
- **Branch 1 — Pull**: origin moved; trivial fast-forward divergence. Action: `git pull --ff-only` non-interactively (the existing fetch/divergence path below).
|
|
40
|
-
- **Branch 2 — Commit**: pre-existing uncommitted work that belongs in a commit (prior AFK iter hit quota / cancel / crash mid-ticket). Auto-commit when **both** discriminator conditions hold: (a) provenance is unambiguous (attributable to the prior iter's own in-flight flow) AND (b) risk is within appetite per
|
|
41
|
-
- **Branch 3 — AskUserQuestion / AFK-halt**: genuinely messy tree (ambiguous uncommitted state, non-fast-forward divergence, partial-prior-session work whose provenance is unclear). Interactive: `AskUserQuestion` per
|
|
40
|
+
- **Branch 2 — Commit**: pre-existing uncommitted work that belongs in a commit (prior AFK iter hit quota / cancel / crash mid-ticket). Auto-commit when **both** discriminator conditions hold: (a) provenance is unambiguous (attributable to the prior iter's own in-flight flow) AND (b) risk is within appetite per the "Inter-iteration release cadence for AFK loops" architecture rule. **Deferred — current implementation routes Branch 2 → Branch 3**: the auto-commit mechanism + gate-composition wiring + bats are not yet shipped. Pre-existing uncommitted source edits demote to Branch 3 (halt-with-report) until the follow-up lands.
|
|
41
|
+
- **Branch 3 — AskUserQuestion / AFK-halt**: genuinely messy tree (ambiguous uncommitted state, non-fast-forward divergence, partial-prior-session work whose provenance is unclear). Interactive: `AskUserQuestion` per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 (four-option report: Resume / Discard / Leave-and-lower-priority / Halt). AFK: halt with structured Prior-Session State report — a **deliberate carve-out from the 2026-06-06 the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 queue-and-continue default** (ambiguous session-continuity state requires user input; non-interactive recovery would mask the bug this preflight is meant to surface).
|
|
42
42
|
|
|
43
43
|
The Branch 1 fetch/divergence table below is the live implementation of Branch 1. The session-continuity detection pass after it is **Branch 3's detection mechanism** — it enumerates the signals that populate the Prior-Session State report when Branch 3 fires.
|
|
44
44
|
|
|
@@ -56,11 +56,11 @@ The Branch 1 fetch/divergence table below is the live implementation of Branch 1
|
|
|
56
56
|
|
|
57
57
|
**Network failure**: if `git fetch origin` returns a network error, stop and report. Default behaviour is fail-closed — the user can retry when network is restored.
|
|
58
58
|
|
|
59
|
-
**Non-interactive authorisation**: per
|
|
59
|
+
**Non-interactive authorisation**: per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6, `git fetch origin` and `git pull --ff-only` are policy-authorised actions (no semantic merge, no destructive overwrite). `git pull --rebase`, `git merge`, and any operation that resolves conflicts are NOT policy-authorised — they require user input.
|
|
60
60
|
|
|
61
|
-
**Cross-cutting**: this rule applies to every AFK orchestrator skill. The next-ID collision guard (
|
|
61
|
+
**Cross-cutting**: this rule applies to every AFK orchestrator skill. The next-ID collision guard (the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule confirmation criterion 2) belongs in the ticket-creator skills (`manage-problem` and `wr-architect:create-adr`), not here — see the related problem ticket for that work.
|
|
62
62
|
|
|
63
|
-
#### Branch 3 detection mechanism — session-continuity signal enumeration (per
|
|
63
|
+
#### Branch 3 detection mechanism — session-continuity signal enumeration (per the "`/wr-itil:work-problems` preflight Step 0 does not detect prior-session partial-work state (untracked ADRs, `.afk-run-state/iter-*.json` with 429/error statuses, existing `.claude/worktrees/*` branches)" problem)
|
|
64
64
|
|
|
65
65
|
After the Branch 1 fetch/divergence check, Step 0 MUST run the session-continuity detection pass that populates Branch 3's signal set (and, when the Branch 2 follow-up lands, feeds the Branch 2 / Branch 3 discriminator). The Branch 1 check handles "did origin move under us"; this pass handles the distinct failure mode "did the prior session leave partial work that changes what iter 1 should do". A prior AFK subprocess can exit mid-ticket (quota 429, user-cancel, subprocess crash) and leave observable state in the working tree that the orchestrator must classify before opening the work loop.
|
|
66
66
|
|
|
@@ -70,41 +70,41 @@ After the Branch 1 fetch/divergence check, Step 0 MUST run the session-continuit
|
|
|
70
70
|
|---|---|
|
|
71
71
|
| Untracked `docs/decisions/*.proposed.md` | `git status --porcelain docs/decisions/` filtered for `??` entries ending `.proposed.md` — drafted but unlanded ADRs from a prior iter. |
|
|
72
72
|
| Untracked `docs/problems/*.md` | `git status --porcelain docs/problems/` filtered for `??` entries ending `.md` — drafted but unlanded problem tickets. |
|
|
73
|
-
| `.afk-run-state/iter-*.json` error markers | Files under `.afk-run-state/` containing `"is_error": true` OR `"api_error_status" >= 400` AND **fresh per the staleness filter** — file mtime is newer than HEAD's commit time (`git log -1 --format=%at HEAD`) OR within the last 24h, whichever is more permissive. Stale residuals (mtime older than HEAD's commit time AND older than 24h) are skipped silently — they represent prior-session partial work whose load-bearing trace has since been verified/landed via a subsequent commit, and the directional asymmetry of the contract is fresh = halt, stale = silent skip (
|
|
73
|
+
| `.afk-run-state/iter-*.json` error markers | Files under `.afk-run-state/` containing `"is_error": true` OR `"api_error_status" >= 400` AND **fresh per the staleness filter** — file mtime is newer than HEAD's commit time (`git log -1 --format=%at HEAD`) OR within the last 24h, whichever is more permissive. Stale residuals (mtime older than HEAD's commit time AND older than 24h) are skipped silently — they represent prior-session partial work whose load-bearing trace has since been verified/landed via a subsequent commit, and the directional asymmetry of the contract is fresh = halt, stale = silent skip (the "/wr-itil:work-problems Step 0 session-continuity detection has no staleness filter on .afk-run-state/iter-*.json error markers — stale residuals false-positive the halt/ask gate indefinitely" problem; closes the indefinite false-positive halt where e.g. an iter-4-p246.json from 2026-05-18 was still firing the gate on 2026-05-30 despite the "Agent waits on calendar trigger for held-cohort graduation — violates symmetric balance principle" problem having been verified-closed on a subsequent session). Success files (`"is_error": false`) are ignored regardless of freshness. When ≥1 stale iter-error-marker is silently skipped, emit a one-line iter-summary annotation per the ": Progress the Backlog While I'm Away" user outcome audit-trail outcome: `Step 0: N stale iter-error-markers skipped (oldest: iter-X-pNNN.json, age: D days). Run \`ls .afk-run-state/iter-*.json\` to inspect.` — preserves traceability of the skip action at near-zero cost and gives a recovery path if a stale-skipped marker was actually load-bearing. Contract source: the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess artefact + the "/wr-itil:work-problems Step 0 session-continuity detection has no staleness filter on .afk-run-state/iter-*.json error markers — stale residuals false-positive the halt/ask gate indefinitely" problem staleness refinement. |
|
|
74
74
|
| Stale `.claude/worktrees/*` dirs + matching `claude/*` branches | `git worktree list` filtered on `claude/*` branches adjacent to `.claude/worktrees/*` directories — prior subagent worktrees that were not cleaned up. Detection only — mutation (cleanup) is out of scope and requires a separate ADR. |
|
|
75
75
|
| Uncommitted modifications to SKILL.md / source / ADR files | `git status --porcelain` filtered for `M ` / ` M` entries on `packages/*/skills/*/SKILL.md`, `packages/*/hooks/*`, `docs/decisions/*.proposed.md`, or other source paths the prior session was mid-authoring. |
|
|
76
76
|
|
|
77
77
|
**Classification**: when any signal is present, build a structured Prior-Session State report listing each hit (signal category, path, one-line summary). An empty signal set means clean pass-through to Step 1.
|
|
78
78
|
|
|
79
|
-
**Routing on interactive-vs-AFK (per
|
|
79
|
+
**Routing on interactive-vs-AFK (per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 / Rule 6):**
|
|
80
80
|
|
|
81
81
|
- **Interactive** (`AskUserQuestion` is available AND the loop was not started in AFK mode): prompt the user with the Prior-Session State report and four options — **Resume the prior work** (land the drafted files as iter 1), **Discard the draft** and restart from scratch, **Leave-and-lower-priority** (skip the dirty paths and work the next backlog item that doesn't touch them), **Halt the loop** (too much dirty state to proceed non-interactively). Route the chosen branch before opening Step 1.
|
|
82
|
-
- **Non-interactive / AFK** (default for this skill per
|
|
82
|
+
- **Non-interactive / AFK** (default for this skill per the ": Progress the Backlog While I'm Away" user outcome): do NOT call `AskUserQuestion`. Halt the loop with the structured Prior-Session State report in the AFK summary. Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 fail-safe: ambiguous session-continuity state requires user input; non-interactive recovery would mask the bug this check is meant to surface. This matches Step 6.75's "dirty for unknown reason → halt" stance at the Step 0 layer — the orchestrator does not silently proceed past partial work.
|
|
83
83
|
|
|
84
|
-
**Step 2.5b cross-reference (
|
|
84
|
+
**Step 2.5b cross-reference (the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)**: before emitting the final AFK summary for a Step 0 session-continuity halt, run Step 2.5b's surfacing routine. The routine is gated on ≥1 accumulated user-answerable skip; at Step 0 no iters have run yet so the gate is normally empty and Step 2.5b returns immediately, but the cross-reference is named here for contract uniformity — every halt path that emits a final summary routes through Step 2.5b regardless of whether the gating clause is empty in the typical case (`halt-paths-must-route-design-questions-through-Step-2.5b`).
|
|
85
85
|
|
|
86
86
|
**Network failure halt (Step 0 fetch failure)**: if `git fetch origin` returns a network error, the loop halts and reports per the rule above. Before emitting the final AFK summary for a network-failure halt, run Step 2.5b's surfacing routine — same Step 2.5b cross-reference as the session-continuity halt. The gating clause is normally empty at Step 0 (no iters have run), but the cross-reference is named here for contract uniformity (`halt-paths-must-route-design-questions-through-Step-2.5b`).
|
|
87
87
|
|
|
88
88
|
Step 6.75 treats a Step-0-resolved-with-user-confirmation state as `dirty-for-known-reason`: if the interactive branch's Resume option landed the drafted ADR as iter 1, the iter's commit clears the dirty state and the rest of the loop proceeds normally.
|
|
89
89
|
|
|
90
|
-
#### README reconciliation preflight (per
|
|
90
|
+
#### README reconciliation preflight (per the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem)
|
|
91
91
|
|
|
92
|
-
After the session-continuity detection pass, Step 0 MUST run the diagnose-only README reconciliation check. The orchestrator reads `docs/problems/README.md`'s WSJF Rankings table to pick the highest-WSJF actionable ticket (Step 3); if that table lies about which tickets are open vs verifying vs closed, the orchestrator burns iterations on no-op tickets — exactly the failure class
|
|
92
|
+
After the session-continuity detection pass, Step 0 MUST run the diagnose-only README reconciliation check. The orchestrator reads `docs/problems/README.md`'s WSJF Rankings table to pick the highest-WSJF actionable ticket (Step 3); if that table lies about which tickets are open vs verifying vs closed, the orchestrator burns iterations on no-op tickets — exactly the failure class the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem captures (a prior session committed a ticket transition without staging the README refresh, and no subsequent session systematically reconciled).
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
95
|
wr-itil-reconcile-readme docs/problems
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
The `wr-itil-reconcile-readme` command is a `$PATH`-resolved shim shipped in `packages/itil/bin/` that dispatches the canonical `packages/itil/scripts/reconcile-readme.sh` body.
|
|
98
|
+
The `wr-itil-reconcile-readme` command is a `$PATH`-resolved shim shipped in `packages/itil/bin/` that dispatches the canonical `packages/itil/scripts/reconcile-readme.sh` body. the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — never invoke the canonical script via repo-relative path; the path does not resolve in adopter trees.
|
|
99
99
|
|
|
100
100
|
Exit-code routing:
|
|
101
101
|
- **Exit 0 (clean)**: continue to Step 1.
|
|
102
|
-
- **Exit 1 (drift detected)**: structured diff lines printed to stdout, one per drift entry (≤150 bytes per
|
|
102
|
+
- **Exit 1 (drift detected)**: structured diff lines printed to stdout, one per drift entry (≤150 bytes per the "Progressive disclosure + once-per-session budget for UserPromptSubmit governance prose" architecture rule progressive-disclosure budget). Capture stdout to a temp file and classify the drift via the **uncommitted-rename carve-out** (the "`/wr-itil:manage-problem` Step 0 reconcile halt-on-drift directive doesn't distinguish uncommitted-rename-rooted drift (same-session pending) from committed cross-session drift — should refresh inline rather than halt for the former case" problem) before halt-routing — see "Drift classification carve-out" immediately below.
|
|
103
103
|
- **Exit 2 (parse error)**: README missing or malformed. Halt the loop with the parse-error message and the structured Prior-Session State report — this is a deeper repair that needs investigation, not mechanical reconciliation.
|
|
104
104
|
|
|
105
|
-
##### Drift classification carve-out (
|
|
105
|
+
##### Drift classification carve-out (the "`/wr-itil:manage-problem` Step 0 reconcile halt-on-drift directive doesn't distinguish uncommitted-rename-rooted drift (same-session pending) from committed cross-session drift — should refresh inline rather than halt for the former case" problem)
|
|
106
106
|
|
|
107
|
-
The Exit 1 auto-route to `/wr-itil:reconcile-readme` is correct for **committed cross-session drift** but **wrong for uncommitted-rename-rooted drift** — when a prior AFK iter (or any in-flight session) carries a staged ticket rename that the next iteration's in-flow
|
|
107
|
+
The Exit 1 auto-route to `/wr-itil:reconcile-readme` is correct for **committed cross-session drift** but **wrong for uncommitted-rename-rooted drift** — when a prior AFK iter (or any in-flight session) carries a staged ticket rename that the next iteration's in-flow the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem / the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem refresh will reconcile in the upcoming commit per the "Governance Skills Commit Their Own Completed Work" architecture rule's single-commit grain. Auto-routing in the latter case fires an extra `chore(problems): reconcile README ...` commit and splits one logical change across two commits, violating the grain. Worse for the AFK orchestrator: that extra commit lands BEFORE the iter's actual work commit, so the audit trail reads "reconcile, then ticket work" when the truth is "ticket work in progress, README refresh deferred to its in-flow contract".
|
|
108
108
|
|
|
109
109
|
Run the classifier on Exit 1 to distinguish the two cases:
|
|
110
110
|
|
|
@@ -118,17 +118,17 @@ if [ "$reconcile_exit" -eq 1 ]; then
|
|
|
118
118
|
fi
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
The `wr-itil-classify-readme-drift` command is a `$PATH`-resolved shim (
|
|
121
|
+
The `wr-itil-classify-readme-drift` command is a `$PATH`-resolved shim (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule naming grammar) dispatching `packages/itil/scripts/classify-readme-drift.sh`. It cross-references drifting IDs from the script's stdout against `git status --porcelain docs/problems/` filtered for staged rename (`R`) entries.
|
|
122
122
|
|
|
123
123
|
Classifier exit-code routing:
|
|
124
124
|
|
|
125
|
-
- **`classify_exit == 0` (INLINE_REFRESH)**: every drifting ID is the destination of a staged rename in the working tree. Log a one-line note in the iter summary ("Step 0 reconcile drift covered by N staged rename(s); deferring README refresh to in-flow Step 5 / Step 7 per
|
|
126
|
-
- **`classify_exit == 1` (HALT_ROUTE_RECONCILE)**: at least one drifting ID is NOT covered by a staged rename — committed cross-session drift OR mixed. Per
|
|
125
|
+
- **`classify_exit == 0` (INLINE_REFRESH)**: every drifting ID is the destination of a staged rename in the working tree. Log a one-line note in the iter summary ("Step 0 reconcile drift covered by N staged rename(s); deferring README refresh to in-flow Step 5 / Step 7 per the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem / the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem + the "Governance Skills Commit Their Own Completed Work" architecture rule single-commit grain") and continue to Step 1. Do NOT invoke `/wr-itil:reconcile-readme` — the in-flow refresh will land the README correction in the same commit as the iter's ticket work.
|
|
126
|
+
- **`classify_exit == 1` (HALT_ROUTE_RECONCILE)**: at least one drifting ID is NOT covered by a staged rename — committed cross-session drift OR mixed. Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 (non-interactive AFK fail-safe), invoke `/wr-itil:reconcile-readme` to apply the corrections + commit a `chore(problems): reconcile README ...` commit, then proceed to Step 1. The reconciled README is the orchestrator's source of truth for Step 3 ranking — a stale read at Step 1 would propagate the lie into the iteration's selection. Mixed routes to halt because `/wr-itil:reconcile-readme` resolves both classes safely; the in-flow refresh only handles the rename'd subset.
|
|
127
127
|
- **`classify_exit == 2` (parse error)**: classifier received empty / missing drift input — contract violation upstream. Fall back to the conservative auto-route.
|
|
128
128
|
|
|
129
|
-
This is a robustness layer ON TOP of
|
|
129
|
+
This is a robustness layer ON TOP of the "Problem 094: `/wr-itil:manage-problem` does not refresh `docs/problems/README.md` on ticket creation" problem + the "Problem 062: `manage-problem` does not refresh `docs/problems/README.md` on single-ticket transitions; fast-path cache goes stale silently" problem, not a supersession — both per-operation contracts remain in force inside each iteration's manage-problem / transition-problem invocation.
|
|
130
130
|
|
|
131
|
-
### Step 0a: Auto-migrate adopter layout (
|
|
131
|
+
### Step 0a: Auto-migrate adopter layout (the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem / the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design / the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule)
|
|
132
132
|
|
|
133
133
|
After Step 0's fetch/divergence preflight and the README reconciliation block but **before** Step 1's backlog scan, source the shared shell migration routine and call the idempotent entrypoint:
|
|
134
134
|
|
|
@@ -136,27 +136,27 @@ After Step 0's fetch/divergence preflight and the README reconciliation block bu
|
|
|
136
136
|
wr-itil-migrate-problems-layout "$PWD"
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
-
`wr-itil-migrate-problems-layout` is the
|
|
139
|
+
`wr-itil-migrate-problems-layout` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim (adopter-safe — resolves `lib/migrate-problems-layout.sh` relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises the former inline `source packages/itil/lib/migrate-problems-layout.sh; migrate_problems_to_per_state_layout "$PWD"`. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
140
140
|
|
|
141
141
|
The routine is **idempotent and partial-migration-safe**. It no-ops when no flat-layout files (`docs/problems/*.<state>.md` at the top level of `docs/problems/`) are detected — the common case post-Slice-5 T5a in this monorepo and in freshly-migrated adopter repos.
|
|
142
142
|
|
|
143
|
-
**Closes the Step 1 false-zero defect** (per
|
|
143
|
+
**Closes the Step 1 false-zero defect** (per the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule § Backward Compatibility line 126 "Why both skills"): Step 1 enumerates BEFORE delegating to manage-problem. On a flat-layout adopter repo, the post-the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule Step 1 glob would return zero matches at the per-state shape and stop-condition #1 would fire incorrectly — the orchestrator would exit with a false "nothing to do" signal, never reaching manage-problem's Step 0a auto-migrate. Wiring auto-migrate here at Step 0a is structurally required, not an optimisation.
|
|
144
144
|
|
|
145
|
-
On a flat-layout adopter repo (first invocation post-update —
|
|
145
|
+
On a flat-layout adopter repo (first invocation post-update — the "Extend the Suite with New Plugins" user outcome plugin-developer auto-migration path), the routine:
|
|
146
146
|
|
|
147
147
|
1. Creates the five state subdirectories under `docs/problems/`.
|
|
148
148
|
2. Runs `git mv` to relocate every existing ticket from flat to per-state subdir.
|
|
149
|
-
3. Emits a standalone commit with subject `docs(problems): auto-migrate to per-state subdirectory layout (
|
|
149
|
+
3. Emits a standalone commit with subject `docs(problems): auto-migrate to per-state subdirectory layout (the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule)` and footer trailer `RISK_BYPASS: adr-031-migration` (recognised by the commit-gate hook per T11).
|
|
150
150
|
|
|
151
|
-
**AFK authorisation per
|
|
151
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: this fires unconditionally even in AFK / non-interactive / orchestrated mode. Pure-rename + pure-mkdir + standalone-commit actions are policy-authorised under the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule precedent — fully reversible (`git revert`), no external-comms surface, no destructive overwrite. No `AskUserQuestion` gate.
|
|
152
152
|
|
|
153
153
|
**First-fire signal**: the routine emits a single stderr line on the migrating invocation; silent on no-op re-invocations.
|
|
154
154
|
|
|
155
|
-
After Step 0a completes (whether no-op or migration), proceed to Step 0b's inbound-discovery pre-flight check. The dual-tolerant glob at Step 1 (
|
|
155
|
+
After Step 0a completes (whether no-op or migration), proceed to Step 0b's inbound-discovery pre-flight check. The dual-tolerant glob at Step 1 (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design transitional window) continues to match both layouts; post-T6 (single-pattern collapse), Step 1 will tighten to per-state only and the migration commit ensures the adopter tree matches.
|
|
156
156
|
|
|
157
|
-
### Step 0b: Upstream inbound-discovery pre-flight (per
|
|
157
|
+
### Step 0b: Upstream inbound-discovery pre-flight (per the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule § the ": Progress the Backlog While I'm Away" user outcome driver)
|
|
158
158
|
|
|
159
|
-
After Step 0a's auto-migrate and before Step 1's backlog scan, check whether the upstream inbound-discovery cache is fresh.
|
|
159
|
+
After Step 0a's auto-migrate and before Step 1's backlog scan, check whether the upstream inbound-discovery cache is fresh. the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule § Decision Drivers names `/wr-itil:work-problems` as the surface that should keep inbound reports visible during AFK loops; the TTL self-healing branch inside `/wr-itil:review-problems` Step 4.5b only fires if review-problems is entered. This step closes that gap by pre-flighting `/wr-itil:review-problems` when the cache is stale or missing.
|
|
160
160
|
|
|
161
161
|
**Mechanism:**
|
|
162
162
|
|
|
@@ -164,19 +164,19 @@ After Step 0a's auto-migrate and before Step 1's backlog scan, check whether the
|
|
|
164
164
|
preflight_reason="$(wr-itil-check-upstream-cache-staleness "$PWD")"
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
`wr-itil-check-upstream-cache-staleness` is the
|
|
167
|
+
`wr-itil-check-upstream-cache-staleness` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim (adopter-safe — resolves `lib/check-upstream-cache-staleness.sh` relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises the former inline `source ...; should_promote_inbound_discovery_preflight "$PWD"` and echoes the result. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
168
168
|
|
|
169
169
|
The helper returns one of five outcomes (contract documented at `packages/itil/lib/check-upstream-cache-staleness.sh` + asserted by `packages/itil/skills/work-problems/test/work-problems-step-0b-cache-staleness-behavioural.bats`):
|
|
170
170
|
|
|
171
171
|
| `preflight_reason` | Action |
|
|
172
172
|
|-----------------------------------|--------------------------------------------------------------------------------------------------------|
|
|
173
|
-
| `no-channels-config` | Silent-pass. Downstream-adopter non-obligation per
|
|
173
|
+
| `no-channels-config` | Silent-pass. Downstream-adopter non-obligation per the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule § Downstream-adopter contract. Proceed to Step 1. |
|
|
174
174
|
| `first-run-cache-absent` | Dispatch `/wr-itil:review-problems` as a pre-flight iter via the standard `claude -p` subprocess wrapper (same shape as Step 5; see Step 5 for the subprocess invocation contract). |
|
|
175
175
|
| `first-run-last-checked-null` | Same as `first-run-cache-absent` — cache schema present but never populated. |
|
|
176
176
|
| `ttl-expiry age=<N>s ttl=<M>s` | Dispatch `/wr-itil:review-problems` as a pre-flight iter. Cache is stale; review-problems' Step 4.5b's TTL-expiry auto-recheck branch fires inside the dispatched subprocess and refreshes the cache + audit-log + README. |
|
|
177
|
-
| `fresh-within-ttl` | Silent-pass per
|
|
177
|
+
| `fresh-within-ttl` | Silent-pass per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 + the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem mechanical-stage carve-out. Proceed to Step 1. |
|
|
178
178
|
|
|
179
|
-
**Pre-flight dispatch shape**: when promoted, dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:review-problems` (per
|
|
179
|
+
**Pre-flight dispatch shape**: when promoted, dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:review-problems` (per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess isolation). The subprocess runs the full Step 4.5 inbound-discovery + assessment pipeline; the cache + `docs/audits/inbound-discovery-log.md` + `docs/problems/README.md` are refreshed in its own commit per the "Governance Skills Commit Their Own Completed Work" architecture rule (review-problems' Slice E commit grain). After the subprocess completes, the orchestrator reads the freshly-refreshed README at Step 1. **If the pre-flight subprocess exits non-zero OR returns `is_error: true`**, apply the non-blocking revert-and-proceed contract in "Step 0 pre-flight subprocess failure handling (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem)" below — do NOT halt the loop (a failed pre-flight is a non-load-bearing cache-refresh dependency, NOT an iter).
|
|
180
180
|
|
|
181
181
|
**Iter-summary annotation**:
|
|
182
182
|
|
|
@@ -184,19 +184,19 @@ The helper returns one of five outcomes (contract documented at `packages/itil/l
|
|
|
184
184
|
- Cache fresh: `Step 0b skipped — upstream inbound-discovery cache fresh within TTL`.
|
|
185
185
|
- Pre-flight ran: `Step 0b pre-flighted /wr-itil:review-problems — reason=<preflight_reason>, <N> reports discovered, <M> local tickets created`.
|
|
186
186
|
|
|
187
|
-
The annotation pre-empts the "surprise heavy iter" perception
|
|
187
|
+
The annotation pre-empts the "surprise heavy iter" perception the ": Progress the Backlog While I'm Away" user outcome expects auditability for — a maintainer running multiple short AFK loops within a 24h window will hit `fresh-within-ttl` on subsequent invocations and see the cache-fresh annotation, confirming the system's silent-pass discipline rather than wondering whether the check ran at all.
|
|
188
188
|
|
|
189
|
-
**AFK authorisation per
|
|
189
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: review-problems' Step 4.5 pipeline is itself AFK-safe — branch decisions are mechanical per the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 silent framework action; external-comms gates on verdict/acknowledgement/pushback comments silent-pass on low-risk verdicts per the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule + the `wr-risk-scorer:external-comms` subagent's *"policy-authorised drafts proceed silently"* contract (`packages/risk-scorer/agents/external-comms.md` § PASS Output); gate-denial sub-branches fail-soft and retry on the next discovery pass. No new user-attention surface introduced at the Step 0b promotion point.
|
|
190
190
|
|
|
191
|
-
**Compose-with**:
|
|
191
|
+
**Compose-with**: the "Governance Skills Commit Their Own Completed Work" architecture rule (review-problems' Slice E commit grain holds — the pre-flight subprocess emits its own commit; orchestrator-main-turn does not commit Step 0b), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5/6 (silent-pass + AFK fail-safe — both honored), the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem (subprocess isolation reuse — same `claude -p` wrapper as Step 5), the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule (preflight surface — Step 0b is the natural extension of "reconcile state before opening the loop"), the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem (mechanical-stage carve-out — no `AskUserQuestion` at the promotion point). Mid-loop ticket creation by Step 4.5e's safe-and-valid branch enters the WSJF queue Step 1 reads on the same invocation — natural absorption, no deadlock; the pre-flight commit lands before Step 1's README read.
|
|
192
192
|
|
|
193
193
|
**Staleness contract drift**: the staleness comparison MUST stay symmetric with `/wr-itil:review-problems` Step 4.5b's branches (first-run / TTL-expiry / cache-fresh). Drift here re-opens the inbound-discovery staleness contract — any change to TTL semantics MUST update both this Step 0b helper and review-problems Step 4.5b in the same commit. <!-- INBOUND-CACHE-STALENESS-CONTRACT-SOURCE: packages/itil/skills/review-problems/SKILL.md Step 4.5b -->
|
|
194
194
|
|
|
195
195
|
After Step 0b completes (whether dispatched or silent-passed), proceed to Step 0c.
|
|
196
196
|
|
|
197
|
-
### Step 0c: Deferred-placeholder + README-cadence pre-flight (per
|
|
197
|
+
### Step 0c: Deferred-placeholder + README-cadence pre-flight (per the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem)
|
|
198
198
|
|
|
199
|
-
After Step 0b's inbound-discovery pre-flight and before Step 1's backlog scan, check whether the deferred-placeholder backlog has accumulated past threshold AND the `docs/problems/README.md` "Last reviewed" cadence has slipped. This step closes the load-bearing gap
|
|
199
|
+
After Step 0b's inbound-discovery pre-flight and before Step 1's backlog scan, check whether the deferred-placeholder backlog has accumulated past threshold AND the `docs/problems/README.md` "Last reviewed" cadence has slipped. This step closes the load-bearing gap the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem names: `/wr-itil:capture-problem` leaves deferred-placeholder Priority + Effort lines that `/wr-itil:review-problems` is the only authoritative re-rate path for; without an auto-fire trigger, placeholders accumulate silently across sessions (76 → 83 evidenced on the 2026-05-24 work-problems session) and the orchestrator dispatches iters against stale WSJF rankings.
|
|
200
200
|
|
|
201
201
|
**Mechanism:**
|
|
202
202
|
|
|
@@ -204,27 +204,27 @@ After Step 0b's inbound-discovery pre-flight and before Step 1's backlog scan, c
|
|
|
204
204
|
preflight_reason="$(wr-itil-check-deferred-placeholder-staleness "$PWD")"
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
`wr-itil-check-deferred-placeholder-staleness` is the
|
|
207
|
+
`wr-itil-check-deferred-placeholder-staleness` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule + the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule `$PATH` shim (adopter-safe — resolves `lib/check-deferred-placeholder-staleness.sh` relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises `should_promote_review_problems_dispatch "$PWD"` and echoes the result. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
208
208
|
|
|
209
209
|
The helper returns one of five outcomes (contract documented at `packages/itil/lib/check-deferred-placeholder-staleness.sh` + asserted by `packages/itil/skills/work-problems/test/work-problems-step-0c-deferred-placeholder-staleness-behavioural.bats`):
|
|
210
210
|
|
|
211
211
|
| `preflight_reason` | Action |
|
|
212
212
|
|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
|
|
213
|
-
| `no-deferred-placeholders` | Silent-pass per
|
|
213
|
+
| `no-deferred-placeholders` | Silent-pass per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 + the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem mechanical-stage carve-out. Proceed to Step 1. |
|
|
214
214
|
| `below-threshold count=<N> threshold=3` | Silent-pass — there is work to re-rate but not enough to be worth a heavyweight pass. Proceed to Step 1. |
|
|
215
215
|
| `no-readme count=<N>` | Dispatch `/wr-itil:review-problems` as a pre-flight iter via the standard `claude -p` subprocess wrapper (same shape as Step 0b / Step 5). README absent OR malformed line 3 → first-run dispatch. |
|
|
216
|
-
| `fresh-readme count=<N> age=<X>s threshold=<Y>s` | Silent-pass per
|
|
216
|
+
| `fresh-readme count=<N> age=<X>s threshold=<Y>s` | Silent-pass per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 — the cadence is in spec; today's captures are tomorrow's review. |
|
|
217
217
|
| `stale-readme count=<N> age=<X>s threshold=<Y>s` | Dispatch `/wr-itil:review-problems` as a pre-flight iter. Both axes met — there is work AND the cadence has slipped. |
|
|
218
218
|
|
|
219
|
-
**Two-axis AND rule (load-bearing per architect verdict on the
|
|
219
|
+
**Two-axis AND rule (load-bearing per architect verdict on the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem fix shape).** Both axes — count ≥ 3 AND README age > 7 days — must hold. Either axis alone over-fires:
|
|
220
220
|
- Count ≥ 3 alone fires on a backlog where review-problems was run yesterday and 3 captures came in today (that's the in-spec deferred-placeholder behaviour, not a staleness signal).
|
|
221
221
|
- Age > 7 days alone fires on quiet weeks where no captures occurred and there is nothing to re-rate.
|
|
222
222
|
|
|
223
223
|
The intersection is the actual signal: "there is work to do AND the cadence has slipped".
|
|
224
224
|
|
|
225
|
-
**Pre-flight dispatch shape**: when promoted (`no-readme` or `stale-readme`), dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:review-problems` (per
|
|
225
|
+
**Pre-flight dispatch shape**: when promoted (`no-readme` or `stale-readme`), dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:review-problems` (per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess isolation). Reuse the Step 5 subprocess wrapper verbatim — same flag set, same idle-timeout SIGTERM poll loop, same retro-on-exit contract. The subprocess runs the full Step 2 + Step 2.5 + Step 4 + Step 5 re-rate + README refresh + commit; the orchestrator reads the freshly-refreshed README at Step 1. **If the pre-flight subprocess exits non-zero OR returns `is_error: true`**, apply the non-blocking revert-and-proceed contract in "Step 0 pre-flight subprocess failure handling (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem)" below — do NOT halt the loop (a failed pre-flight is a non-load-bearing cache-refresh dependency, NOT an iter).
|
|
226
226
|
|
|
227
|
-
**ADR-
|
|
227
|
+
**the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule composition note**: Step 0c dispatches `/wr-itil:review-problems` which includes Step 4.6 relevance-close per the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule — relevance-close fires as a side-effect of the auto-dispatch. This is desirable: relevance closes accumulate the same way deferred placeholders do, and the AND-trigger reasonably gates both pieces of work.
|
|
228
228
|
|
|
229
229
|
**Iter-summary annotation**:
|
|
230
230
|
|
|
@@ -232,21 +232,21 @@ The intersection is the actual signal: "there is work to do AND the cadence has
|
|
|
232
232
|
- Fresh README cadence: `Step 0c skipped — README cadence fresh (age=<X>s within 7-day window)`.
|
|
233
233
|
- Pre-flight ran: `Step 0c pre-flighted /wr-itil:review-problems — reason=<preflight_reason>, <N> placeholders re-rated, <M> tickets auto-transitioned, <K> tickets relevance-closed`.
|
|
234
234
|
|
|
235
|
-
The annotation pre-empts the "surprise heavy iter" perception
|
|
235
|
+
The annotation pre-empts the "surprise heavy iter" perception the ": Progress the Backlog While I'm Away" user outcome expects auditability for — a maintainer running multiple short AFK loops with fresh-cache will see the silent-pass annotation, confirming the system's silent-pass discipline rather than wondering whether the check ran at all.
|
|
236
236
|
|
|
237
|
-
**AFK authorisation per
|
|
237
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: review-problems is itself AFK-safe — branch decisions are mechanical per the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 silent framework action; Step 4 verification prompts skip silently when `AskUserQuestion` is unavailable per the review-problems Step 4 AFK branch. No new user-attention surface introduced at the Step 0c promotion point.
|
|
238
238
|
|
|
239
|
-
**Compose-with**:
|
|
239
|
+
**Compose-with**: the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5/6 (silent-pass + AFK fail-safe), the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 (silent-framework — the trigger is policy + observable evidence), the "Governance Skills Commit Their Own Completed Work" architecture rule (review-problems' commit grain holds — the pre-flight subprocess emits its own commit), the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule / the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule (PATH shim grammar + highest-version-wins wrapper), the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule § Step 0b (precedent staleness-pre-flight shape), the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule § Step 4.6 (relevance-close composition), the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem (subprocess isolation reuse — same `claude -p` wrapper as Step 5), the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem (mechanical-stage carve-out — no `AskUserQuestion` at the promotion point), the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem / the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design (dual-tolerant glob — the helper handles both layouts), the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem / the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design (adopter-safe PATH shim).
|
|
240
240
|
|
|
241
|
-
**Staleness contract drift**: the two-axis trigger (count ≥ 3 AND age > 7 days) MUST stay symmetric across the four SKILL surfaces that read it — this Step 0c, `/wr-itil:manage-problem` Step 0.5 (advisory), `/wr-itil:capture-problem` Step 7 (conditional trailing pointer), AND the helper's threshold constants. Drift here re-opens
|
|
241
|
+
**Staleness contract drift**: the two-axis trigger (count ≥ 3 AND age > 7 days) MUST stay symmetric across the four SKILL surfaces that read it — this Step 0c, `/wr-itil:manage-problem` Step 0.5 (advisory), `/wr-itil:capture-problem` Step 7 (conditional trailing pointer), AND the helper's threshold constants. Drift here re-opens the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem. <!-- DEFERRED-PLACEHOLDER-STALENESS-CONTRACT-SOURCE: packages/itil/lib/check-deferred-placeholder-staleness.sh -->
|
|
242
242
|
|
|
243
|
-
<!-- @jtbd
|
|
243
|
+
<!-- @jtbd the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away — AFK orchestrator pre-flights review-problems so iters dispatch against fresh WSJF rankings) -->
|
|
244
244
|
|
|
245
245
|
After Step 0c completes (whether dispatched or silent-passed), proceed to Step 0d.
|
|
246
246
|
|
|
247
|
-
### Step 0d: Outbound upstream-responses pre-flight (per
|
|
247
|
+
### Step 0d: Outbound upstream-responses pre-flight (per the ": Progress the Backlog While I'm Away" user outcome AFK driver + the ": Connect Agents Across Repos to Collaborate" user outcome cross-repo coordination)
|
|
248
248
|
|
|
249
|
-
After Step 0c's deferred-placeholder pre-flight and before Step 1's backlog scan, check whether the outbound-responses cache is fresh.
|
|
249
|
+
After Step 0c's deferred-placeholder pre-flight and before Step 1's backlog scan, check whether the outbound-responses cache is fresh. the "No process for issue reporters to check for responses — symmetric gap to inbound discovery" problem Phase 1 shipped `/wr-itil:check-upstream-responses` as a manual skill (the outbound symmetric counterpart to Step 0b's inbound pipeline); the "manage-problem has no cadence for checking upstream-bound tickets" problem names the cadence gap that without an auto-fire trigger, upstream responses to issues we filed via `/wr-itil:report-upstream` go unread until the maintainer remembers to invoke the skill. This step closes that gap with the same pre-flight shape Step 0b uses for the inbound axis.
|
|
250
250
|
|
|
251
251
|
**Mechanism:**
|
|
252
252
|
|
|
@@ -254,7 +254,7 @@ After Step 0c's deferred-placeholder pre-flight and before Step 1's backlog scan
|
|
|
254
254
|
preflight_reason="$(wr-itil-check-outbound-responses-staleness "$PWD")"
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
-
`wr-itil-check-outbound-responses-staleness` is the
|
|
257
|
+
`wr-itil-check-outbound-responses-staleness` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule + the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule `$PATH` shim (adopter-safe — resolves `lib/check-outbound-responses-staleness.sh` relative to the script, NOT cwd; the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem/the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design) that internalises `should_promote_outbound_responses_preflight "$PWD"` and echoes the result. NEVER `source packages/...` repo-relative from a SKILL — those paths only resolve in the source monorepo, not adopter installs.
|
|
258
258
|
|
|
259
259
|
The helper returns one of five outcomes (contract documented at `packages/itil/lib/check-outbound-responses-staleness.sh` + asserted by `packages/itil/skills/work-problems/test/work-problems-step-0d-outbound-responses-staleness-behavioural.bats`):
|
|
260
260
|
|
|
@@ -264,9 +264,9 @@ The helper returns one of five outcomes (contract documented at `packages/itil/l
|
|
|
264
264
|
| `first-run-cache-absent` | Dispatch `/wr-itil:check-upstream-responses` as a pre-flight iter via the standard `claude -p` subprocess wrapper (same shape as Step 0b / Step 0c / Step 5). |
|
|
265
265
|
| `first-run-last-checked-null` | Same as `first-run-cache-absent` — cache schema present but never populated. |
|
|
266
266
|
| `ttl-expiry age=<N>s ttl=<M>s` | Dispatch `/wr-itil:check-upstream-responses` as a pre-flight iter. Cache stale; the skill polls each back-linked upstream URL, diffs against the cache, and emits STATE / NEW / LABEL / NONE / FAIL per back-link ticket. |
|
|
267
|
-
| `fresh-within-ttl` | Silent-pass per
|
|
267
|
+
| `fresh-within-ttl` | Silent-pass per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 + the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem mechanical-stage carve-out. Proceed to Step 1. |
|
|
268
268
|
|
|
269
|
-
**Pre-flight dispatch shape**: when promoted, dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:check-upstream-responses` (per
|
|
269
|
+
**Pre-flight dispatch shape**: when promoted, dispatch a single `claude -p --permission-mode bypassPermissions --output-format json` subprocess that invokes `/wr-itil:check-upstream-responses` (per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess isolation). Reuse the Step 5 subprocess wrapper verbatim — same flag set, same idle-timeout SIGTERM poll loop. The subprocess runs the full check-upstream-responses Step 1 + Step 2 + Step 3 pipeline; the cache file `docs/problems/.outbound-responses-cache.json` + audit-log `docs/audits/outbound-responses-log.md` are refreshed in its own commit per the "Governance Skills Commit Their Own Completed Work" architecture rule (check-upstream-responses' SKILL.md Step 3 commit grain). After the subprocess completes, the orchestrator proceeds to Step 1. **If the pre-flight subprocess exits non-zero OR returns `is_error: true`**, apply the non-blocking revert-and-proceed contract in "Step 0 pre-flight subprocess failure handling (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem)" below — do NOT halt the loop (a failed pre-flight is a non-load-bearing cache-refresh dependency, NOT an iter).
|
|
270
270
|
|
|
271
271
|
**Iter-summary annotation**:
|
|
272
272
|
|
|
@@ -274,38 +274,38 @@ The helper returns one of five outcomes (contract documented at `packages/itil/l
|
|
|
274
274
|
- Cache fresh: `Step 0d skipped — outbound-responses cache fresh within TTL`.
|
|
275
275
|
- Pre-flight ran: `Step 0d pre-flighted /wr-itil:check-upstream-responses — reason=<preflight_reason>, <N> back-link tickets polled, <M> STATE/NEW deltas surfaced`.
|
|
276
276
|
|
|
277
|
-
The annotation pre-empts the "surprise heavy iter" perception
|
|
277
|
+
The annotation pre-empts the "surprise heavy iter" perception the ": Progress the Backlog While I'm Away" user outcome expects auditability for — a maintainer running multiple short AFK loops within a 24h window will hit `fresh-within-ttl` on subsequent invocations and see the cache-fresh annotation, confirming the system's silent-pass discipline rather than wondering whether the check ran at all.
|
|
278
278
|
|
|
279
|
-
**AFK authorisation per
|
|
279
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: check-upstream-responses is itself AFK-safe by construction — read-only externally (`gh issue view` only; no `gh issue comment` / `gh issue create`), so does NOT trip the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule's external-comms gate; zero `AskUserQuestion` calls (flag-based knobs per CLAUDE.md the "Problem 085: Assistant asks for input when the next step is obvious, AND uses prose asks instead of AskUserQuestion when input is actually needed" problem); partial-failure exit code 2 distinguishes "some upstream URLs unreachable" from "everything broke" so AFK orchestrators can branch correctly. No new user-attention surface introduced at the Step 0d promotion point.
|
|
280
280
|
|
|
281
|
-
**Compose-with**:
|
|
281
|
+
**Compose-with**: the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5/6 (silent-pass + AFK fail-safe), the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 (silent-framework — the trigger is policy + observable evidence), the "Governance Skills Commit Their Own Completed Work" architecture rule (check-upstream-responses' commit grain holds — the pre-flight subprocess emits its own commit), the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule (back-link `## Reported Upstream` section is the source-of-truth scanned by the helper and read by the dispatched skill), the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule / the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule (PATH shim grammar + highest-version-wins wrapper), the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule § Step 0b (precedent staleness-pre-flight shape — Step 0d is the outbound symmetric counterpart), the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem (subprocess isolation reuse — same `claude -p` wrapper as Step 5), the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem (mechanical-stage carve-out — no `AskUserQuestion` at the promotion point), the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem / the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design (dual-tolerant glob — the helper handles both layouts), the "capture-problem / capture-rfc / manage-problem Step 2 create-gate marker step sources repo-relative `packages/itil/hooks/lib/*.sh` — fails in adopter installs (recurring published-path class: //)" problem / the ": Adopter-safe path resolution in shipped SKILLs ( — 24 repo-relative references)" release design (adopter-safe PATH shim), the "No process for issue reporters to check for responses — symmetric gap to inbound discovery" problem Phase 1 (the manual skill this step wires into a cadence).
|
|
282
282
|
|
|
283
283
|
**Staleness contract drift**: the staleness comparison MUST stay symmetric with the check-upstream-responses SKILL's Confirmation surface (TTL semantics + outcome shape). Drift here re-opens the outbound-responses staleness contract — any change to TTL semantics MUST update this Step 0d, the lib helper, AND the check-upstream-responses SKILL.md Confirmation section in the same commit. <!-- OUTBOUND-RESPONSES-STALENESS-CONTRACT-SOURCE: packages/itil/skills/check-upstream-responses/SKILL.md ## Confirmation -->
|
|
284
284
|
|
|
285
|
-
<!-- @jtbd
|
|
286
|
-
<!-- @jtbd
|
|
285
|
+
<!-- @jtbd the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away — AFK orchestrator pre-flights check-upstream-responses so outbound STATE/NEW deltas surface without manual polling) -->
|
|
286
|
+
<!-- @jtbd the ": Connect Agents Across Repos to Collaborate" user outcome (Connect Agents Across Repos to Collaborate — closes the outbound symmetric feedback loop) -->
|
|
287
287
|
|
|
288
288
|
After Step 0d completes (whether dispatched or silent-passed), proceed to the shared pre-flight failure-handling contract below, then to Step 0e, then to Step 1.
|
|
289
289
|
|
|
290
|
-
### Step 0 pre-flight subprocess failure handling (
|
|
290
|
+
### Step 0 pre-flight subprocess failure handling (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem — non-blocking revert-and-proceed)
|
|
291
291
|
|
|
292
|
-
Step 0b / Step 0c / Step 0d (and **any future Step 0x pre-flight** that reuses the Step 5 `claude -p` subprocess wrapper) dispatch a `/wr-itil:review-problems` or `/wr-itil:check-upstream-responses` **pre-flight subprocess** "same shape as Step 5". That phrase imports the Step 5 *dispatch mechanism* (the `claude -p --output-format json` wrapper + the idle-timeout SIGTERM poll loop), but the **failure semantics are NOT shared** — and the prior prose left this implicit, which
|
|
292
|
+
Step 0b / Step 0c / Step 0d (and **any future Step 0x pre-flight** that reuses the Step 5 `claude -p` subprocess wrapper) dispatch a `/wr-itil:review-problems` or `/wr-itil:check-upstream-responses` **pre-flight subprocess** "same shape as Step 5". That phrase imports the Step 5 *dispatch mechanism* (the `claude -p --output-format json` wrapper + the idle-timeout SIGTERM poll loop), but the **failure semantics are NOT shared** — and the prior prose left this implicit, which the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem surfaced. Step 5's exit-code semantics HALT the loop on non-zero exit / `is_error: true` because **the iter IS the loop body unit** — its failure is the loop's failure. A **pre-flight is a non-load-bearing cache-refresh dependency**, not an iteration of the loop body: Step 1's backlog scan reads whatever `docs/problems/README.md` already exists (freshly-refreshed or slightly-stale), so a failed pre-flight degrades to "cache not refreshed this pass" — never to "halt the loop".
|
|
293
293
|
|
|
294
294
|
**Contract — a pre-flight subprocess that exits non-zero OR returns `is_error: true` is NON-BLOCKING** (general rule; every Step 0x pre-flight inherits it):
|
|
295
295
|
|
|
296
|
-
1. **Revert any dirty working-tree state the failed pre-flight left.** The dispatched skill commits its own refresh per
|
|
297
|
-
2. **Log a one-line iter-summary annotation** naming the failed pre-flight + the failure class: `Step 0<b|c|d> pre-flight FAILED (<exit-code | is_error class>) — reverted partial cache write, proceeding to Step 1 with existing README`. Preserves the
|
|
296
|
+
1. **Revert any dirty working-tree state the failed pre-flight left.** The dispatched skill commits its own refresh per the "Governance Skills Commit Their Own Completed Work" architecture rule (review-problems' Slice E grain / check-upstream-responses' Step 3 grain) — it commits end-to-end or not at all. A subprocess that died mid-refresh may leave an **UNSTAGED** partial write across any path the dispatched skill is contractually allowed to touch: the staleness cache (`docs/problems/.upstream-cache.json` for 0b, `docs/problems/.outbound-responses-cache.json` for 0d), the audit log (`docs/audits/inbound-discovery-log.md` for 0b, `docs/audits/outbound-responses-log.md` for 0d), AND `docs/problems/README.md` + re-rated ticket bodies (0c). Revert the whole contractually-touchable set — not just the cache JSON — so a half-written README or audit-log is also restored. Revert each path **independently** (`git checkout -- docs/problems/ 2>/dev/null; git checkout -- docs/audits/ 2>/dev/null`) rather than as a combined `git checkout -- docs/problems/ docs/audits/` pathspec: the combined form errors and reverts NOTHING when `docs/audits/` is absent (a fresh adopter repo that has never run inbound/outbound discovery), whereas the per-path form tolerates the missing directory and still reverts the dirty `docs/problems/` write. Do NOT commit a partial write: a half-refreshed cache/README is worse than a stale-but-coherent one. If the dead pre-flight somehow left **STAGED** residue (it should not — the pre-flight owns its commit end-to-end), `git reset` (unstage) it first, then revert, so the orchestrator's own subsequent Step 1+ gate flow is not contaminated by a dead subprocess's index (mirrors the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule no-trust-window-extension reasoning — a dead `is_error: true` subprocess MUST NOT seed the parent's commit).
|
|
297
|
+
2. **Log a one-line iter-summary annotation** naming the failed pre-flight + the failure class: `Step 0<b|c|d> pre-flight FAILED (<exit-code | is_error class>) — reverted partial cache write, proceeding to Step 1 with existing README`. Preserves the ": Progress the Backlog While I'm Away" user outcome audit-trail outcome (the silent degradation becomes observable rather than invisible).
|
|
298
298
|
3. **Proceed to Step 1.** The pre-flight failure does NOT halt the loop and does NOT count against the Step 0 prior-session-state Branch 3 detection (step 1 above restored a clean tree, so the iter dispatches that follow start from a clean state).
|
|
299
299
|
|
|
300
|
-
**`is_error: true` sub-class note (reconciles
|
|
300
|
+
**`is_error: true` sub-class note (reconciles the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem with the Step 5 taxonomy).** A pre-flight subprocess failure is the SAME `is_error: true` family the Step 5 exit-code semantics taxonomise (the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem SALVAGE / the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem HALT) — **including** the `socket connection was closed unexpectedly` variant (an `is_error: true` shape that routes to the Step 5 catch-all advisory). The load-bearing distinction the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem surfaces is **orthogonal to the SALVAGE-vs-HALT axis**: that axis is scoped to **iters** (the loop body); pre-flights have their own non-blocking failure contract. The Step 5 SALVAGE branch does **NOT** apply to a pre-flight even when the pre-flight left staged work — a pre-flight is not an iteration whose work the orchestrator salvages-and-commits; its job is a cache refresh the dispatched skill owns end-to-end. Pre-flight failure is therefore ALWAYS the revert-and-proceed branch above, never SALVAGE.
|
|
301
301
|
|
|
302
|
-
**AFK authorisation per
|
|
302
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: revert-and-proceed is a deterministic, non-interactive recovery — no `AskUserQuestion`. Reverting an unstaged partial write is fully reversible (the next loop pass re-attempts the refresh) and policy-authorised (the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule preflight-reconciliation "leave the tree clean" precedent). Mirrors the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem SIGTERM Rule-6 posture.
|
|
303
303
|
|
|
304
|
-
**Compose-with**:
|
|
304
|
+
**Compose-with**: the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule § "Pre-flight subprocess failure handling — non-blocking revert-and-proceed (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem amendment)" (the architectural record + the iter-vs-pre-flight failure-semantics distinction), Step 5 exit-code semantics (the iter-failure HALT contract this is distinguished from), the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule (preflight-reconciliation clean-tree surface), the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule (no-trust-window-extension — the `git reset` of any staged residue), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 (non-interactive recovery), the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem (driver ticket). This is a fourth symmetric pre-flight surface alongside the three "Staleness contract drift" clauses (lines for Step 0b/0c/0d) — a future Step 0x pre-flight inherits this failure rule by construction; do NOT re-derive a step-specific copy.
|
|
305
305
|
|
|
306
|
-
### Step 0e: `/goal` loop-anchor (
|
|
306
|
+
### Step 0e: `/goal` loop-anchor (the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem / the "AFK loops anchor completion with the native `/goal` external evaluator" architecture rule / the ": AFK loop `/goal` anchor — external evaluator judges the stop" release design / the ": AFK loop anchored with the native `/goal` external evaluator" delivery story)
|
|
307
307
|
|
|
308
|
-
The loop's stop decision is anchored by Claude Code's native [`/goal`](https://code.claude.com/docs/en/goal) command (≥ v2.1.139): a per-turn **external evaluator** (the configured small fast model, wrapping a session-scoped prompt-based Stop hook) judges a completion condition against what the orchestrator has printed in the transcript. This breaks the
|
|
308
|
+
The loop's stop decision is anchored by Claude Code's native [`/goal`](https://code.claude.com/docs/en/goal) command (≥ v2.1.139): a per-turn **external evaluator** (the configured small fast model, wrapping a session-scoped prompt-based Stop hook) judges a completion condition against what the orchestrator has printed in the transcript. This breaks the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem same-actor conflation — the working agent that is prone to inventing subjective stops no longer decides whether stopping is justified; Step 2.4 Gate (0) remains the first-line objective *self*-check, and `/goal` is the *external* check that the orchestrator keeps turning until Gate (0) genuinely passes.
|
|
309
309
|
|
|
310
310
|
**Canonical goal condition** (owned here; the Step 2.4 Gate (0) table shape and this condition are a coupled contract — reshape both in the same commit):
|
|
311
311
|
|
|
@@ -313,9 +313,9 @@ The loop's stop decision is anchored by Claude Code's native [`/goal`](https://c
|
|
|
313
313
|
The /wr-itil:work-problems AFK backlog drain is complete: the final summary printed in the conversation contains a Step 2.4 Gate (0) re-scan table (fresh open/known-error glob) classifying every ticket and showing ZERO dispatchable tickets, followed by the ALL_DONE sentinel — or the session ends with a Hard-fail halt directive naming the gate that could not complete — or the summary reports quota exhaustion.
|
|
314
314
|
```
|
|
315
315
|
|
|
316
|
-
There is no turn-bound: the loop runs until a real end state (printed Gate (0) zero-dispatchable + ALL_DONE, a Hard-fail halt, or quota exhaustion). Trust the goal — a turn cap would just re-create the premature stop this anchor exists to prevent (
|
|
316
|
+
There is no turn-bound: the loop runs until a real end state (printed Gate (0) zero-dispatchable + ALL_DONE, a Hard-fail halt, or quota exhaustion). Trust the goal — a turn cap would just re-create the premature stop this anchor exists to prevent (the "Agent silently ships X-prime (a hedged/lesser version of the requested X) instead of asking before deviating" problem). the "Ship quota-pacing surface to prevent weekly-quota exhaustion — advisory or blocking nudge when burn rate exceeds sustainable pace, so users retain Claude tokens for non-Claude-Code surfaces (chat, cowork) for the full week" problem/the "Mechanical quota-pace throttle — frequently-firing PreToolUse hook, calculated sleep, never blocks" architecture rule quota pacing throttles token burn so an honest ALL_DONE is reachable within the window.
|
|
317
317
|
|
|
318
|
-
**Placement — orchestrator session ONLY.** The goal lives on the orchestrator session, never on the `claude -p` iter subprocesses: iters end naturally after one ticket (
|
|
318
|
+
**Placement — orchestrator session ONLY.** The goal lives on the orchestrator session, never on the `claude -p` iter subprocesses: iters end naturally after one ticket (the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule / the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem / the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem), and a backlog-empty goal there would push an iter past its one-ticket carve-out.
|
|
319
319
|
|
|
320
320
|
**Setting the anchor.** There is no programmatic mid-session surface (empirically probed 2026-07-06, v2.1.201: no `--goal` CLI flag; the Skill tool rejects it — "goal is a UI command, not a skill"; only the user can type it mid-session). So:
|
|
321
321
|
|
|
@@ -327,20 +327,20 @@ There is no turn-bound: the loop runs until a real end state (printed Gate (0) z
|
|
|
327
327
|
|
|
328
328
|
(The condition text itself carries the skill invocation, so the anchored session enters the loop — a bare condition would set a goal over an empty session.)
|
|
329
329
|
|
|
330
|
-
- **Interactive invocation (nudge-and-proceed)** — when the loop starts without an active goal (no `/goal` directive or evaluator-reason lines visible in the session context), print ONE nudge line surfacing the exact command for the user to type — `/goal <canonical condition above>` — then **proceed with the loop regardless**. The anchor is defense-in-depth over Gate (0), never a precondition: halting an AFK loop for a missing anchor would itself defeat
|
|
330
|
+
- **Interactive invocation (nudge-and-proceed)** — when the loop starts without an active goal (no `/goal` directive or evaluator-reason lines visible in the session context), print ONE nudge line surfacing the exact command for the user to type — `/goal <canonical condition above>` — then **proceed with the loop regardless**. The anchor is defense-in-depth over Gate (0), never a precondition: halting an AFK loop for a missing anchor would itself defeat the ": Progress the Backlog While I'm Away" user outcome. No `AskUserQuestion` fires here (mechanical stage; the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4).
|
|
331
331
|
|
|
332
332
|
**One-directional anchor.** The goal forces continuation; it never authorises a stop. A goal that is cleared (or was never set) does NOT discharge Gate (0) — `ALL_DONE` still requires the full Step 2.4 sequence. Requirements floor: `/goal` needs workspace trust + hooks enabled; below the floor the loop degrades honestly to Gate (0)-only behaviour.
|
|
333
333
|
|
|
334
334
|
### Step 1: Scan the backlog
|
|
335
335
|
|
|
336
|
-
Read `docs/problems/README.md` if it exists and is fresh (check via git history — see manage-problem step 9 for the cache freshness check). If stale or missing, scan all open + known-error tickets via the dual-tolerant pattern `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (
|
|
336
|
+
Read `docs/problems/README.md` if it exists and is fresh (check via git history — see manage-problem step 9 for the cache freshness check). If stale or missing, scan all open + known-error tickets via the dual-tolerant pattern `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design migration window — covers BOTH the flat `<NNN>-<title>.<state>.md` filename-suffix layout AND the per-state subdir `<state>/<NNN>-<title>.md` layout), extract their WSJF scores, and rank them.
|
|
337
337
|
|
|
338
|
-
**README row order matches Step 3 tier + tie-break selection (
|
|
338
|
+
**README row order matches Step 3 tier + tie-break selection (the "`docs/problems/README.md` WSJF Rankings table row order doesn't match `/wr-itil:work-problems`'s tie-break selection — users assume the orchestrator is broken" problem + the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule)**: the README's WSJF Rankings table is rendered tier-first — rows partition into Tier 0 Critical-bypass (Severity ≥17 OR security-classified OR incident-linked) → Tier 1 Inbound-reported (`**Origin**: inbound-reported`) → Tier 2 Internal, and within each tier by the multi-key sort `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)`. The cache-fresh path can therefore read the rendered table top-to-bottom and the first row is the orchestrator's pick — no in-memory tier/tie-break re-application needed. The slow path scan must apply the same tier partition then multi-key sort. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) --> <!-- TIE-BREAK-LADDER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 -->
|
|
339
339
|
|
|
340
340
|
Exclude:
|
|
341
341
|
- `.closed.md` files (done)
|
|
342
342
|
- `.parked.md` files (blocked on upstream)
|
|
343
|
-
- `.verifying.md` files (Verification Pending — fix released, awaiting user verification per
|
|
343
|
+
- `.verifying.md` files (Verification Pending — fix released, awaiting user verification per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule; surfaced in the Verification Queue section, never in dev-work ranking)
|
|
344
344
|
- Problems with no WSJF score (need a review first — run `/wr-itil:review-problems` as the first iteration if scores are missing)
|
|
345
345
|
|
|
346
346
|
### Step 2: Check stop conditions
|
|
@@ -351,37 +351,37 @@ Stop the loop and report a summary if any of these are true:
|
|
|
351
351
|
2. **All remaining problems require interactive input** — e.g., they all need user verification (known-errors with `## Fix Released`), or their scope expanded beyond what's safe to auto-resolve
|
|
352
352
|
3. **All remaining problems are blocked** — investigation hit a dead end, or the fix requires changes outside the project
|
|
353
353
|
|
|
354
|
-
**Step 2.5 fires unconditionally at loop end** (
|
|
354
|
+
**Step 2.5 fires unconditionally at loop end** (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem Phase 3 / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule) — promoted from "fallback when stop-condition #2" to **default loop-end emit shape**. Anti-BUFD framing per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule: the AFK loop is the empirical-discovery engine; direction-class observations + deviation-candidates accumulate from real friction across iters; loop-end batched presentation is the user-facing deliverable. Per-iter surfacing was the old (now-superseded) pattern; Phase 3 makes batch-at-loop-end the default for ALL stop conditions, not just #2.
|
|
355
355
|
|
|
356
|
-
For stop-conditions #1 and #3 (no actionable problems / all blocked), Step 2.5 still runs — it reads the accumulated `outstanding_questions` queue from `.afk-run-state/outstanding-questions.jsonl` and presents the batch. Empty queue → no `AskUserQuestion` fires; non-empty queue → batched per
|
|
356
|
+
For stop-conditions #1 and #3 (no actionable problems / all blocked), Step 2.5 still runs — it reads the accumulated `outstanding_questions` queue from `.afk-run-state/outstanding-questions.jsonl` and presents the batch. Empty queue → no `AskUserQuestion` fires; non-empty queue → batched per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 cap (≤4 per call, sequential if >4).
|
|
357
357
|
|
|
358
|
-
### Step 2.4: Pre-`ALL_DONE` gate sequence (UNCONDITIONAL — fires before every `ALL_DONE` emit,
|
|
358
|
+
### Step 2.4: Pre-`ALL_DONE` gate sequence (UNCONDITIONAL — fires before every `ALL_DONE` emit, the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem)
|
|
359
359
|
|
|
360
|
-
Before the orchestrator emits the final `ALL_DONE` sentinel for the AFK loop, it MUST run the following gate sequence. The sequence fires **unconditionally** — at every stop-condition (`#1`, `#2`, `#3` per Step 2) AND at every halt-path that emits a final AFK summary AND on quota-exhaustion / natural loop end. The sequence has four parts that MUST complete in order (gate (0) prepended per
|
|
360
|
+
Before the orchestrator emits the final `ALL_DONE` sentinel for the AFK loop, it MUST run the following gate sequence. The sequence fires **unconditionally** — at every stop-condition (`#1`, `#2`, `#3` per Step 2) AND at every halt-path that emits a final AFK summary AND on quota-exhaustion / natural loop end. The sequence has four parts that MUST complete in order (gate (0) prepended per the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem); the structural rule is `ALL_DONE` emits ONLY after (0) AND (a) AND (b) complete cleanly. Per-state subdir layout reminder: this step's order in the SKILL is logical (Step 2.4 fires *between* the Step 2 stop-check and the Step 2.5 surfacing routine *only as a wrapper*); the numerical ordering reflects the conceptual sequence (Step 2.4 wraps Step 2.5 + the new retro gate, then Step 2.5/2.5b execute as gate (a)'s worker).
|
|
361
361
|
|
|
362
|
-
**Gate (0) — Objective backlog-empty assertion (
|
|
362
|
+
**Gate (0) — Objective backlog-empty assertion (the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem, fires FIRST, before gate (a)).** Before the rest of the sequence runs, the orchestrator MUST re-scan the live backlog and prove that the Step 2 stop-condition it is about to act on OBJECTIVELY holds. `ALL_DONE` is forbidden while ≥1 dispatchable ticket remains — a non-empty actionable backlog is itself the disproof of stop-condition #1/#2/#3.
|
|
363
363
|
|
|
364
|
-
1. *Re-scan.* Re-run the Step 1 dual-tolerant glob `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (
|
|
364
|
+
1. *Re-scan.* Re-run the Step 1 dual-tolerant glob `ls docs/problems/*.open.md docs/problems/*.known-error.md docs/problems/open/*.md docs/problems/known-error/*.md 2>/dev/null` (the ": docs/problems/ flat layout migration — per-state subdirs + adopter auto-migration" release design window — both layouts). This is a fresh filesystem read, NOT a re-use of the Step 1 cache or the agent's recollection — tickets may have transitioned, closed, or been created by prior iters / the session-level retro since Step 1.
|
|
365
365
|
|
|
366
366
|
2. *Classify each ticket as dispatchable or not — objectively, per recorded marker, never by salience.* A ticket is **non-dispatchable** ONLY when an objective, recorded condition excludes it:
|
|
367
367
|
- it is `verifying` / carries `## Fix Released` awaiting user verification (stop-condition #2, interactive);
|
|
368
368
|
- it carries an upstream-blocked marker (`## Reported Upstream` / `- **Upstream report pending** --` / em-dash legacy) or a recorded blocked classification with a dead-end investigation (stop-condition #3);
|
|
369
369
|
- it was filtered out THIS session by Step 3.5 (interactive-ratification predicate) or Step 3.6 (already-shipped relevance gate) — keyed off the durable per-session skip record those steps write (the `outstanding_questions` entry in `.afk-run-state/outstanding-questions.jsonl` carrying the ticket id), NOT agent recollection, so the classification is reproducible across the re-scan and cannot loop forever;
|
|
370
|
-
Every other open / known-error ticket is **dispatchable** — ordinary autonomous fix-and-commit work. The agent MUST NOT reclassify a dispatchable ticket as non-dispatchable because the *salient* remainder of the backlog is interactive-gated, because the ticket "feels" out of scope, or because a user-directed pivot consumed the loop's attention. The subjective "this is a natural stopping point" judgement is exactly the
|
|
370
|
+
Every other open / known-error ticket is **dispatchable** — ordinary autonomous fix-and-commit work. The agent MUST NOT reclassify a dispatchable ticket as non-dispatchable because the *salient* remainder of the backlog is interactive-gated, because the ticket "feels" out of scope, or because a user-directed pivot consumed the loop's attention. The subjective "this is a natural stopping point" judgement is exactly the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem failure; the classification is per-ticket and marker-bound. **The classification MUST be PRINTED as a table in the turn output** (ticket → dispatchable/non-dispatchable → the recorded marker that decided) — not merely computed. A computed-but-unprinted re-scan is invisible to the Step 0e `/goal` external evaluator, which judges only what the transcript surfaces (the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding); the printed table is the evidence the canonical goal condition names.
|
|
371
371
|
|
|
372
|
-
3. *Decide.* If the re-scan yields **≥1 dispatchable ticket**, `ALL_DONE` is FORBIDDEN: the stop-condition the orchestrator was about to emit does NOT objectively hold. The orchestrator loops back to Step 3 tier-first selection (Critical-bypass → Inbound-reported → Internal, within-tier WSJF per
|
|
372
|
+
3. *Decide.* If the re-scan yields **≥1 dispatchable ticket**, `ALL_DONE` is FORBIDDEN: the stop-condition the orchestrator was about to emit does NOT objectively hold. The orchestrator loops back to Step 3 tier-first selection (Critical-bypass → Inbound-reported → Internal, within-tier WSJF per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) over the dispatchable set and dispatches the next iter — it does NOT proceed to gate (a)/(b)/(c). Only when the re-scan yields **zero dispatchable tickets** does gate (0) pass and the sequence proceed to gate (a). Gate (0) finding work is a **loopback, not a halt** — it is productive (the loop resumes draining), so it is NOT a Hard-fail halt trigger.
|
|
373
373
|
|
|
374
|
-
**Why gate (0) fires first**: gates (a)/(b)/(c) (surface questions → retro → emit) presume the loop is genuinely done; running the retro and emitting `ALL_DONE` while dispatchable work remains prematurely ends the AFK drain (
|
|
374
|
+
**Why gate (0) fires first**: gates (a)/(b)/(c) (surface questions → retro → emit) presume the loop is genuinely done; running the retro and emitting `ALL_DONE` while dispatchable work remains prematurely ends the AFK drain (the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem), forcing the user to re-prompt "keep working the backlog" and defeating the ": Progress the Backlog While I'm Away" user outcome. Gate (0) makes "the backlog is objectively empty of dispatchable tickets" a hard, re-verified precondition of the whole sequence rather than a subjective agent judgement. A user-directed mid-loop pivot (e.g. an eval-cohort detour) does NOT discharge the Tier-exhaustion obligation: after the pivot, gate (0)'s re-scan resumes tier selection rather than terminating — which also catches the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem coverage miss where a Tier-1 ticket (the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem) was skipped entirely. Sibling class: the "run-retro skips Step 1.5 / Step 3 / Step 4b Stage 1 under session-length rationalization — recurrence of anti-pattern class on the run-retro meta-surface" problem (run-retro skip rationalisation), the "Agent defers ticket creation to retro summary "Tickets Deferred" section instead of immediately invoking `/wr-itil:manage-problem` — observations could be lost if user is in a rush" problem (Stage-1 ticketing skip), the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem (scope-pin loop-control inference) — all agent-invented loop-control stops the framework did not authorise (the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule "Continue / stop loops" is framework-resolved: the natural stop is concrete — `ALL_DONE` conditions objectively met — not "this feels done").
|
|
375
375
|
|
|
376
|
-
**Gate (0) × Step 0e `/goal` anchor (
|
|
376
|
+
**Gate (0) × Step 0e `/goal` anchor (the "AFK loops anchor completion with the native `/goal` external evaluator" architecture rule).** Under an active goal, the `ALL_DONE` emit does not by itself end the session — the Step 0e external evaluator reads the printed gate (0) table + sentinel and independently confirms the condition holds; a premature emit just triggers a "keep working" turn with the evaluator's reason as guidance. The anchor is one-directional: a cleared goal (or a loop that was never anchored) does NOT relax this gate — gate (0) fires unconditionally either way.
|
|
377
377
|
|
|
378
|
-
**Gate (a) — Outstanding-questions surface + oversight-unconfirmed drain (
|
|
378
|
+
**Gate (a) — Outstanding-questions surface + oversight-unconfirmed drain (the "A ratification marker can only be written when someone actually ratified" architecture rule / the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem).** Two sub-surfaces, both fire in this gate:
|
|
379
379
|
|
|
380
|
-
1. *Outstanding-questions surface.* Read `.afk-run-state/outstanding-questions.jsonl`. If non-empty, invoke Step 2.5b's surfacing routine to present the accumulated queue (via `AskUserQuestion`-when-available-else-table per
|
|
380
|
+
1. *Outstanding-questions surface.* Read `.afk-run-state/outstanding-questions.jsonl`. If non-empty, invoke Step 2.5b's surfacing routine to present the accumulated queue (via `AskUserQuestion`-when-available-else-table per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 / Rule 6). On completion, truncate the queue file. If the queue is empty, this sub-surface returns immediately. The surfacing routine is the existing Step 2.5b — Step 2.4 does NOT re-implement; it sequences.
|
|
381
381
|
|
|
382
|
-
2. *Oversight-unconfirmed drain.* Run `wr-architect-detect-unoversighted`, `wr-jtbd-detect-unoversighted`, and `wr-itil-detect-unratified-stories-maps` (all
|
|
382
|
+
2. *Oversight-unconfirmed drain.* Run `wr-architect-detect-unoversighted`, `wr-jtbd-detect-unoversighted`, and `wr-itil-detect-unratified-stories-maps` (all the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule PATH shims, all always exit 0; output is the list of unoversighted/unratified artefact paths). The story/map detector (**the "Story maps and stories carry a drift-invalidated human-oversight marker" architecture rule** / **the "A release row is the RFC, and the map is the approval surface" architecture rule**) is **drift-aware**: it lists story MAPS that are never-ratified, explicitly `unconfirmed`, or **drift-reopened** — a `confirmed` marker whose `oversight-hash` no longer matches the map's substance — plus the stories those maps leave unapproved. Re-ratify via `/wr-itil:manage-story-map` (or `wr-itil-mark-story-oversight-confirmed <map-file>`) — never per-story: a story carries no marker and the command refuses one; the nudge + 2-option `Drain now` / `Defer` surface below applies to this list identically. If either lists ≥ 1 artefact whose frontmatter carries `human-oversight: unconfirmed` (the AFK-explicit-deferred state, distinct from the implicit-absent state pre-existing ADR/JTBD files carry), surface a one-line nudge: *"N iter-deferred decision(s)/job(s) carry `human-oversight: unconfirmed`. Run `/wr-architect:review-decisions` and `/wr-jtbd:confirm-jobs-and-personas` to drain."* If `AskUserQuestion` is available (`/wr-itil:work-problems` was invoked interactively before the AFK loop started), surface a 2-option choice — `Drain now` (invokes the appropriate drain skill before `ALL_DONE`) / `Defer to next session` (proceeds to gate (b) with the nudge in the final summary). If `AskUserQuestion` is unavailable, the nudge prints in the final summary table and gate (b) proceeds. The drain is NOT a halt — `unconfirmed` markers are explicit-by-design AFK signals (the iter wrote them KNOWING the user would need to confirm), and the drain is the documented path. Detector difference matters: ADRs/JTBDs that pre-date the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule/the ": JTBD + persona human-oversight marker + `/wr-jtbd:confirm-jobs-and-personas` drain (sibling of )" architecture rule marker contract carry NO `human-oversight:` line at all; they fall through to the existing review-decisions/confirm-jobs-and-personas backlog drain (no new surfacing here). The new surfacing fires ONLY on the explicit `unconfirmed` value — the AFK-iter-deferred class the "iter subprocesses set `human-oversight: confirmed` marker on ADRs / personas / JTBDs without an actual user-confirmation event" problem introduces.
|
|
383
383
|
|
|
384
|
-
**Gate (b) — Session-level retro.** Invoke `/wr-retrospective:run-retro` via the Skill tool. This is the **orchestrator-main-turn session-level retro**, distinct from the per-iter retro fired inside each iter subprocess (per
|
|
384
|
+
**Gate (b) — Session-level retro.** Invoke `/wr-retrospective:run-retro` via the Skill tool. This is the **orchestrator-main-turn session-level retro**, distinct from the per-iter retro fired inside each iter subprocess (per the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem / Step 5 retro-on-exit clause). The session-level retro covers cross-iter patterns, friction observations, framework-improvement candidates, and the AFK loop's overall trajectory — surface visible only after multiple iters have completed. Retro commits its own work per the "Governance Skills Commit Their Own Completed Work" architecture rule; any tickets retro creates ride retro's own commit, and the orchestrator picks them up on the *next* invocation of `/wr-itil:work-problems` rather than re-entering the loop here.
|
|
385
385
|
|
|
386
386
|
**Gate (c) — Emit `ALL_DONE`.** The sentinel emits ONLY after gate (0), gate (a), and gate (b) complete. The final summary (per Output Format below) includes the Session Cost section and the Outstanding Design Questions table (when gate (a)'s fallback branch fired). `ALL_DONE` is the single canonical emit position — Step 2.5 no longer emits `ALL_DONE` directly; its closing prose hands control to Step 2.4 (b) per the cross-reference.
|
|
387
387
|
|
|
@@ -394,15 +394,15 @@ ALL_DONE
|
|
|
394
394
|
Halt triggers:
|
|
395
395
|
|
|
396
396
|
- **Gate (a) cannot complete**: queue has user-input-required entries AND `AskUserQuestion` is unavailable AND the fallback Outstanding Design Questions table cannot render (e.g. write error to `.afk-run-state/`). The halt directive cites the queue file path + entry count + the rendering failure.
|
|
397
|
-
- **Gate (b) cannot complete**: `/wr-retrospective:run-retro` returns a non-zero exit code or the Skill tool itself is unavailable. The halt directive cites the run-retro failure mode (skill-unavailable / non-zero exit / commit-gate rejection per
|
|
397
|
+
- **Gate (b) cannot complete**: `/wr-retrospective:run-retro` returns a non-zero exit code or the Skill tool itself is unavailable. The halt directive cites the run-retro failure mode (skill-unavailable / non-zero exit / commit-gate rejection per the "Governance Skills Commit Their Own Completed Work" architecture rule). Retro is non-blocking *within* the iter subprocess (per Step 5's retro-on-exit clause) but **load-bearing** at the orchestrator-main-turn session-level gate — these are distinct surfaces.
|
|
398
398
|
|
|
399
|
-
**Why unconditional**: prior to this gate, Step 2.5's outstanding-questions surface fired conditionally on stop-condition #2; stop-conditions #1 and #3 did NOT route through it unless the queue happened to be non-empty AND the agent remembered the cross-reference. Session-level retro was implicit — only per-iter retros existed. The structural gap was that `ALL_DONE` could emit while direction-class observations remained queued AND without a session-level retro running — both gates were nominally documented but neither was a hard prerequisite. Step 2.4 closes this by making the gate sequence a hard, unconditional prerequisite. The 2026-05-31 user direction codified the invariant: *"the work-problems skill MUST surface the outstanding questions at the end before emitting ALL_DONE. It MUST then run a retro. Only then should it emit ALL_DONE"* (
|
|
399
|
+
**Why unconditional**: prior to this gate, Step 2.5's outstanding-questions surface fired conditionally on stop-condition #2; stop-conditions #1 and #3 did NOT route through it unless the queue happened to be non-empty AND the agent remembered the cross-reference. Session-level retro was implicit — only per-iter retros existed. The structural gap was that `ALL_DONE` could emit while direction-class observations remained queued AND without a session-level retro running — both gates were nominally documented but neither was a hard prerequisite. Step 2.4 closes this by making the gate sequence a hard, unconditional prerequisite. The 2026-05-31 user direction codified the invariant: *"the work-problems skill MUST surface the outstanding questions at the end before emitting ALL_DONE. It MUST then run a retro. Only then should it emit ALL_DONE"* (the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem Description verbatim).
|
|
400
400
|
|
|
401
|
-
**Composition**: gate (a) inherits the Step 2.5 / Step 2.5b surfacing routine without modification — the new structure is a wrapper, not a re-implementation. Gate (b) is the orchestrator-level extension of
|
|
401
|
+
**Composition**: gate (a) inherits the Step 2.5 / Step 2.5b surfacing routine without modification — the new structure is a wrapper, not a re-implementation. Gate (b) is the orchestrator-level extension of the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem (which fires retro at iter-subprocess level only). Gate (c) is the same `ALL_DONE` sentinel; only its emit position is amended. The pre-existing the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem cross-reference principle (`halt-paths-must-route-design-questions-through-Step-2.5b`) is preserved — halt-paths still route through Step 2.5b; the only addition is that even *successful* loop ends now route through Step 2.4 (a)+(b) before `ALL_DONE`. Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary: the agent-internal trust-boundary for *when* to surface is now framework-resolved (unconditional pre-`ALL_DONE`); the user-input surface *within* gate (a) is unchanged (still the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 batched-AskUserQuestion when available, Rule 6 table fallback otherwise).
|
|
402
402
|
|
|
403
|
-
### Step 2.5: Surface accumulated outstanding questions at loop end (
|
|
403
|
+
### Step 2.5: Surface accumulated outstanding questions at loop end (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem Phase 3 — default emit shape)
|
|
404
404
|
|
|
405
|
-
Per
|
|
405
|
+
Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary: human input is for direction-setting / deviation-approval / one-time-override / silent-framework / taste / authentic-correction (six categories). Across N iters, those observations accumulate at iter level (`ITERATION_SUMMARY.outstanding_questions`) and persist to a session-level queue file. Loop-end Step 2.5 reads, ranks, and presents the batch.
|
|
406
406
|
|
|
407
407
|
**1. Read the accumulated queue.** Read `.afk-run-state/outstanding-questions.jsonl` — each line is one entry per the ITERATION_SUMMARY `outstanding_questions` schema (see Step 5 Output contract). De-duplicate identical entries (same `category` + same `question` text + same `existing_decision` for deviation-approval).
|
|
408
408
|
|
|
@@ -410,15 +410,15 @@ Per ADR-044 framework-resolution boundary: human input is for direction-setting
|
|
|
410
410
|
|
|
411
411
|
**3. Branch on interactivity.**
|
|
412
412
|
|
|
413
|
-
- **Default branch — call `AskUserQuestion` when available** (the orchestrator's main turn is interactive by construction; the user is presumed at the keyboard at loop end). Batch the entries into one or more `AskUserQuestion` calls per
|
|
413
|
+
- **Default branch — call `AskUserQuestion` when available** (the orchestrator's main turn is interactive by construction; the user is presumed at the keyboard at loop end). Batch the entries into one or more `AskUserQuestion` calls per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 cap. Header per category: `"Outstanding direction"`, `"Approve deviation from existing decision"`, `"One-time override"`, etc. For deviation-approval entries, options are `Approve + amend ADR` / `Approve + supersede ADR` / `Approve + one-time exception` / `Reject (existing decision stands)` / `Defer (need more evidence)` — the 5-option shape matching the `proposed_shape` field. For other entries, options are extracted from the entry's `question` text or candidate fixes. Write answers back to the corresponding ticket files so the next AFK loop does not re-ask.
|
|
414
414
|
|
|
415
415
|
- **Fallback branch — emit `### Outstanding Design Questions` table** when `AskUserQuestion` is unavailable (restricted permission mode, hook-disabled tool surface). The table lists each entry with its `category`, `question`, `existing_decision` / `contradicting_evidence` for deviation-approval entries, and `ticket_id`. The user answers on return.
|
|
416
416
|
|
|
417
417
|
**4. Cleanup.** After all entries are resolved (whether via `AskUserQuestion` or table), truncate `.afk-run-state/outstanding-questions.jsonl` to empty. The next AFK loop starts with a clean queue.
|
|
418
418
|
|
|
419
|
-
**5. Cleanup + hand control to Step 2.4 (b) for session-level retro (
|
|
419
|
+
**5. Cleanup + hand control to Step 2.4 (b) for session-level retro (the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem).** Step 2.5 is the worker of Step 2.4 gate (a); after gate (a)'s surfacing routine completes and the queue file is truncated, control passes to Step 2.4 gate (b) for the session-level retro. The final summary (including the Outstanding Design Questions table when Step 2.5b's fallback branch fired) is prepared here but the `ALL_DONE` sentinel emits at Step 2.4 (c) AFTER retro completes — not at Step 2.5 directly. This makes Step 2.4 the single canonical `ALL_DONE` emit position; external scripts watching for completion read the sentinel from the post-retro position per Step 2.4.
|
|
420
420
|
|
|
421
|
-
### Step 2.5b: Surface accumulated user-answerable skips (reusable surfacing routine,
|
|
421
|
+
### Step 2.5b: Surface accumulated user-answerable skips (reusable surfacing routine, the "`/wr-itil:work-problems` stop-condition #2 defaults to the AFK Outstanding Design Questions table when AskUserQuestion is available — interactive users get no questions" problem + the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)
|
|
422
422
|
|
|
423
423
|
Step 2.5b is the single source of truth for routing accumulated user-answerable skip-reasons through `AskUserQuestion`-when-available-else-table. It is the sub-step that Step 2.5 (stop-condition #2) AND every halt path that fires after iters have accumulated skipped tickets cross-references — keeping the surfacing logic in one place rather than duplicated across each halt path.
|
|
424
424
|
|
|
@@ -426,21 +426,21 @@ Step 2.5b is the single source of truth for routing accumulated user-answerable
|
|
|
426
426
|
|
|
427
427
|
**1. Extract the question set.** For every skipped ticket whose classifier skip-reason is `user-answerable` (see Step 4's taxonomy), extract its outstanding question(s) from the ticket body — typically from a "Pacing decision", "Naming decision", or outstanding "Investigation Tasks" section. Cap at 4 questions per `AskUserQuestion` call per Anthropic's tool documentation; the same cap applies regardless of whether Step 2.5b was invoked from stop-condition #2 or a halt path.
|
|
428
428
|
|
|
429
|
-
**2. Branch on interactivity per
|
|
429
|
+
**2. Branch on interactivity per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 / Rule 6.**
|
|
430
430
|
|
|
431
|
-
- **Default branch — call `AskUserQuestion` when available** (the orchestrator's main turn is interactive by construction; the user is presumed at the keyboard). Batch the questions into one `AskUserQuestion` call (or more, if >4 questions, issued sequentially). Header: `"Outstanding design questions"`. For each question, set the prompt from the extracted text and the options from the ticket's candidate fixes or option list. Write each answer back to the corresponding ticket file so the next AFK loop does not re-ask. This is
|
|
432
|
-
- **Fallback branch — emit `### Outstanding Design Questions` table** when `AskUserQuestion` is unavailable (restricted permission mode, hook-disabled tool surface, or any other context where the structured-question primitive cannot fire). The table lists each question with its Ticket ID, the question text, and one-line context. The user answers on return. This is
|
|
431
|
+
- **Default branch — call `AskUserQuestion` when available** (the orchestrator's main turn is interactive by construction; the user is presumed at the keyboard). Batch the questions into one `AskUserQuestion` call (or more, if >4 questions, issued sequentially). Header: `"Outstanding design questions"`. For each question, set the prompt from the extracted text and the options from the ticket's candidate fixes or option list. Write each answer back to the corresponding ticket file so the next AFK loop does not re-ask. This is the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 applied to the orchestrator's main-turn surface.
|
|
432
|
+
- **Fallback branch — emit `### Outstanding Design Questions` table** when `AskUserQuestion` is unavailable (restricted permission mode, hook-disabled tool surface, or any other context where the structured-question primitive cannot fire). The table lists each question with its Ticket ID, the question text, and one-line context. The user answers on return. This is the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 fail-safe — fall back to a structured summary when the structured-interaction primitive is unavailable.
|
|
433
433
|
|
|
434
|
-
**Return.** Hand control back to the caller. The caller is responsible for emitting its own final summary (and the `ALL_DONE` sentinel for stop-condition #2; halt paths each have their own outcome label per Step 6 /
|
|
434
|
+
**Return.** Hand control back to the caller. The caller is responsible for emitting its own final summary (and the `ALL_DONE` sentinel for stop-condition #2; halt paths each have their own outcome label per Step 6 / the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5 / Step 6.75 / etc.).
|
|
435
435
|
|
|
436
|
-
**Cross-skill principle (architect FLAG,
|
|
436
|
+
**Cross-skill principle (architect FLAG, the "`/wr-itil:work-problems` stop-condition #2 defaults to the AFK Outstanding Design Questions table when AskUserQuestion is available — interactive users get no questions" problem + the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)**: orchestrator main turns default to `AskUserQuestion` when available; the AFK persona (the ": Progress the Backlog While I'm Away" user outcome) is served by the **subprocess-boundary contract under the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule** (iteration subprocess workers are AFK by construction via `claude -p` — they exit at `ITERATION_SUMMARY` and never reach the orchestrator's stop or halt surfaces), NOT by suppressing `AskUserQuestion` at the orchestrator layer. Step 5's iteration-prompt template carries the per-subprocess AFK contract (constraint: "Do not call `AskUserQuestion`"); the orchestrator's stop and halt surfaces fire only in the main turn where the user is presumed present. the "`/wr-itil:work-problems` stop-condition #2 defaults to the AFK Outstanding Design Questions table when AskUserQuestion is available — interactive users get no questions" problem established this principle at Step 2.5; the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem extends it to every halt path that emits a final AFK summary (the principle: **halt-paths-must-route-design-questions-through-Step-2.5b** — every halt path that fires after iters have accumulated user-answerable skips MUST run Step 2.5b before emitting its summary).
|
|
437
437
|
|
|
438
438
|
### Step 3: Pick the highest-WSJF problem in the highest non-empty tier
|
|
439
439
|
|
|
440
|
-
Selection partitions the backlog into three **tiers** and works the highest non-empty tier first; the WSJF tie-break ladder applies **within** a tier, not across tiers. Tiers, highest first (
|
|
440
|
+
Selection partitions the backlog into three **tiers** and works the highest non-empty tier first; the WSJF tie-break ladder applies **within** a tier, not across tiers. Tiers, highest first (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule):
|
|
441
441
|
|
|
442
442
|
1. **Tier 0 — Critical bypass**: Severity Very High (≥17) OR security-classified OR incident-linked. The most critical issues always come first, regardless of origin.
|
|
443
|
-
2. **Tier 1 — Inbound-reported**: ticket carries `**Origin**: inbound-reported` (reported to us by an external user;
|
|
443
|
+
2. **Tier 1 — Inbound-reported**: ticket carries `**Origin**: inbound-reported` (reported to us by an external user; the "Inbound upstream-report discovery + assessment pipeline (peer of )" architecture rule). Worked ahead of internal tickets — customer-service / feedback-signal preservation: ignored reporters stop reporting and churn.
|
|
444
444
|
3. **Tier 2 — Internal**: everything else (`**Origin**: internal` or no Origin field).
|
|
445
445
|
|
|
446
446
|
Within the highest non-empty tier, select the problem with the highest WSJF score. If there's a tie, prefer:
|
|
@@ -449,11 +449,11 @@ Within the highest non-empty tier, select the problem with the highest WSJF scor
|
|
|
449
449
|
3. Older reported date (longer wait = higher urgency)
|
|
450
450
|
4. Lower ID (deterministic final tiebreaker)
|
|
451
451
|
|
|
452
|
-
The full selection order is therefore: **tier** (Critical-bypass → Inbound-reported → Internal), then the within-tier ladder `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)`. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (
|
|
452
|
+
The full selection order is therefore: **tier** (Critical-bypass → Inbound-reported → Internal), then the within-tier ladder `(WSJF desc, Known-Error-first, Effort-divisor asc, Reported-date asc, ID asc)`. <!-- REPORTED-FIRST-TIER-SOURCE: /wr-itil:work-problems SKILL.md Step 3 (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) -->
|
|
453
453
|
|
|
454
|
-
### Step 3.5: JTBD ratification predicate-check (per
|
|
454
|
+
### Step 3.5: JTBD ratification predicate-check (per the ": — `/wr-itil:work-problems` Step 3.5 JTBD ratification predicate-check (orchestrator-layer mirror of surface 3)" release design / the "`/wr-itil:work-problems` orchestrator should predicate-check the cited JTBDs of the selected ticket BEFORE dispatching the iter-worker — wasted-iter-dispatch class when JTBDs are unratified" problem)
|
|
455
455
|
|
|
456
|
-
After Step 3 selects a candidate ticket and before Step 4 classifies it for dispatch, predicate-check the cited JTBDs of the selected ticket. The per-iter JTBD review subagent (
|
|
456
|
+
After Step 3 selects a candidate ticket and before Step 4 classifies it for dispatch, predicate-check the cited JTBDs of the selected ticket. The per-iter JTBD review subagent (the ": JTBD + persona human-oversight marker + `/wr-jtbd:confirm-jobs-and-personas` drain (sibling of )" architecture rule surface 3 — the `[Unratified Dependency]` verdict) catches the same class INSIDE the iter subprocess, but only after spending iter-dispatch cost (~$3-5 + 5-10 min per skip). This step shifts the predicate left to the orchestrator layer for the cost of one grep + per-JTBD shim call — analogous to how Step 0b pre-flights inbound-discovery staleness rather than letting iters discover it. Driving exemplar: 2026-05-31 session 9 iter 5 dispatched the "Problem 082: No voice-and-tone or content-risk-scoring gate on commit messages" problem against unratified the ": Enforce Governance Without Slowing Down" user outcome + the ": Progress the Backlog While I'm Away" user outcome; the iter correctly skipped per the ": Confirm a decision's substance before building dependent work on it" architecture rule substance-confirm-before-build, but the per-dispatch cost was wasted.
|
|
457
457
|
|
|
458
458
|
**Mechanism:**
|
|
459
459
|
|
|
@@ -462,25 +462,25 @@ wr-itil-check-ticket-jtbd-ratification "<selected-ticket-path>"
|
|
|
462
462
|
predicate_exit=$?
|
|
463
463
|
```
|
|
464
464
|
|
|
465
|
-
`wr-itil-check-ticket-jtbd-ratification` is the
|
|
465
|
+
`wr-itil-check-ticket-jtbd-ratification` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule / the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule `$PATH` shim that dispatches `packages/itil/scripts/check-ticket-jtbd-ratification.sh`. The script extracts cited `JTBD-NNN` IDs from the ticket body (Decision Drivers / `**JTBD**:` / `**Persona**:` references) and delegates per-JTBD ratification to `wr-jtbd-is-job-or-persona-unconfirmed` (the ": JTBD + persona human-oversight marker + `/wr-jtbd:confirm-jobs-and-personas` drain (sibling of )" architecture rule surface 3 single-artifact predicate). Polarity is INVERTED vs the inner predicate — the outer script answers "are all cited JTBDs ratified?" rather than "is THIS one unconfirmed?". Behavioural contract asserted by `test/work-problems-step-3-5-jtbd-ratification-predicate.bats`.
|
|
466
466
|
|
|
467
467
|
Exit-code routing:
|
|
468
468
|
|
|
469
469
|
| `predicate_exit` | Meaning | Action |
|
|
470
470
|
|---|---|---|
|
|
471
|
-
| `0` | All cited JTBDs ratified, OR ticket cites no JTBDs, OR per-JTBD shim missing (
|
|
471
|
+
| `0` | All cited JTBDs ratified, OR ticket cites no JTBDs, OR per-JTBD shim missing (the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule silent-pass) | Proceed to Step 4 normally — the ticket is dispatchable. |
|
|
472
472
|
| `1` | ≥1 cited JTBD unratified (or unresolved) — IDs on stdout, one per line; `JTBD-NNN (unresolved)` for inner exit-2 cases | Route the ticket to Step 4's user-answerable skip path (`skip_reason_category: user-answerable`). Queue an `outstanding_questions` entry (`category: "direction"`) naming the unratified JTBDs + ticket ID + remedy: *"Run `/wr-jtbd:confirm-jobs-and-personas` to ratify the cited jobs/personas, then re-invoke `/wr-itil:work-problems`."* Loop back to Step 3 to re-run the tier-first selection over the remaining backlog minus the skipped ticket. |
|
|
473
473
|
| `2` | Ticket file missing / unreadable | Halt the loop with the structured Prior-Session State report — this is the same shape as the README-reconciliation Exit 2 halt at Step 0 (deeper repair needed, not mechanical reconciliation). |
|
|
474
474
|
|
|
475
|
-
**Loopback tier preservation**: re-run the Step 3 tier-first selection over the remaining backlog minus the skipped ticket. Tier order (Critical-bypass → Inbound-reported → Internal) and within-tier WSJF ladder are preserved per
|
|
475
|
+
**Loopback tier preservation**: re-run the Step 3 tier-first selection over the remaining backlog minus the skipped ticket. Tier order (Critical-bypass → Inbound-reported → Internal) and within-tier WSJF ladder are preserved per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule. If every actionable ticket is filtered out by Step 3.5, Step 2 stop-condition #1 (no actionable problems) fires naturally and the accumulated `outstanding_questions` entries surface at Step 2.4 gate (a) per the existing batched-`AskUserQuestion` contract.
|
|
476
476
|
|
|
477
|
-
**Why orchestrator-layer, not iter-layer**: the inner per-iter JTBD subagent stays in place (defence-in-depth — the iter-layer is the authoritative second-source, not a replacement surface). The orchestrator predicate is the optimisation: cheap pre-check eliminates wasted dispatch when the answer is knowable from a `grep` + frontmatter read. The two surfaces are not redundant — they cover different failure modes (orchestrator: shift-left cost optimisation; iter: substance-confirm-before-build governance gate per
|
|
477
|
+
**Why orchestrator-layer, not iter-layer**: the inner per-iter JTBD subagent stays in place (defence-in-depth — the iter-layer is the authoritative second-source, not a replacement surface). The orchestrator predicate is the optimisation: cheap pre-check eliminates wasted dispatch when the answer is knowable from a `grep` + frontmatter read. The two surfaces are not redundant — they cover different failure modes (orchestrator: shift-left cost optimisation; iter: substance-confirm-before-build governance gate per the ": Confirm a decision's substance before building dependent work on it" architecture rule). When the orchestrator silent-passes (predicate-exit 0 via missing-shim degenerate case per the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule), the iter-layer still catches any unratified-dep correctly.
|
|
478
478
|
|
|
479
|
-
**AFK authorisation per
|
|
479
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: this is a pure read-only predicate-check (no writes, no commits, no external comms). No `AskUserQuestion` at this step — the routing is deterministic per the table above. The user-answerable question accumulates in the queue file and surfaces at Step 2.4 gate (a) per the existing batched contract. Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary: routing is framework-resolved (mechanical); user input is preserved at the loop-end surface where it belongs.
|
|
480
480
|
|
|
481
|
-
**Compose-with**:
|
|
481
|
+
**Compose-with**: the ": JTBD + persona human-oversight marker + `/wr-jtbd:confirm-jobs-and-personas` drain (sibling of )" architecture rule (surface 3 single-artifact predicate — mirrored to orchestrator), the ": Confirm a decision's substance before building dependent work on it" architecture rule (substance-confirm-before-build — JTBD-as-driver symmetric sibling to ADR-as-driver), the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule (tier-first selection preserved by the loopback), the "Problem-ticket directory layout — per-state subdirectories under `docs/problems/`" architecture rule (degenerate adopter silent-pass when per-JTBD shim absent), the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule / the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule (PATH shim grammar + highest-version-wins wrapper), the "Governance Skills Commit Their Own Completed Work" architecture rule (no commit at this step — predicate is read-only). The sibling-class gap for ADRs cited as Decision Drivers (the ": Confirm a decision's substance before building dependent work on it" architecture rule master class) is the ": — `/wr-itil:work-problems` Step 3.5 JTBD ratification predicate-check (orchestrator-layer mirror of surface 3)" release design § Deferred item 1 — captured for follow-on after this Step 3.5 dogfoods.
|
|
482
482
|
|
|
483
|
-
### Step 3.6: Pre-dispatch relevance gate (per
|
|
483
|
+
### Step 3.6: Pre-dispatch relevance gate (per the "work-problems re-dispatches already-fixed tickets at full iter cost; add a cheap pre-dispatch relevance-close" problem)
|
|
484
484
|
|
|
485
485
|
After Step 3.5's JTBD predicate-check and before Step 4 classifies the selected ticket, run the cheap deterministic relevance evaluator on the **selected ticket only**. On a mature backlog a meaningful fraction of "open" / known-error tickets have already been fixed by later work but never transitioned (observed: 3 of 6 worked tickets in one session). A full Step 5 `manage-problem` dispatch (~$3-5 + 5-10 min) against such a ticket only rediscovers the shipped fix and transitions it — the conclusion is correct but the rediscovery is expensive. This step shifts that conclusion left to a millisecond shell check, exactly as Step 3.5 shifts the JTBD-ratification predicate left and Step 0c pre-flights the backlog-wide relevance-close.
|
|
486
486
|
|
|
@@ -491,29 +491,29 @@ wr-itil-evaluate-relevance "<selected-ticket-path>"
|
|
|
491
491
|
relevance_exit=$?
|
|
492
492
|
```
|
|
493
493
|
|
|
494
|
-
`wr-itil-evaluate-relevance` is the
|
|
494
|
+
`wr-itil-evaluate-relevance` is the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule `$PATH` shim dispatching `packages/itil/scripts/evaluate-relevance.sh` — the **same evaluator** `/wr-itil:review-problems` Step 4.6 uses for its relevance-close pass (the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule). It emits one verdict line and carries a built-in ≥7-day age gate (a freshly-reported ticket SKIPs and falls through to normal work — no self-close paradox). Behavioural coverage of the verdict shapes is the existing `packages/itil/scripts/test/evaluate-relevance.bats`; Step 3.6 adds no new computational surface, only routing, so it carries no separate behavioural script of its own (a SKILL.md-prose grep would be a structural test, rejected per the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem / the "Behavioural-tests-default for skill testing" architecture rule).
|
|
495
495
|
|
|
496
496
|
Exit-code routing:
|
|
497
497
|
|
|
498
498
|
| `relevance_exit` / verdict | Meaning | Action |
|
|
499
499
|
|---|---|---|
|
|
500
|
-
| `0` `CLOSE-CANDIDATE` (no caveat) | cited fix shipped — clean evidence per ADR-
|
|
501
|
-
| `0` `CLOSE-CANDIDATE-WITH-CAVEAT` | partial / mixed-phase evidence | Do **not** auto-close — a caveat is the maintainer's decision input, not a mechanical close (review-problems 4.6b/4.6d route AFK caveats to the next interactive confirm). Route to Step 4's user-answerable skip (`skip_reason_category: user-answerable`); queue an `outstanding_questions` entry (`category: "direction"`) carrying the **caveat short-tag + one-line verbatim** from the verdict (
|
|
500
|
+
| `0` `CLOSE-CANDIDATE` (no caveat) | cited fix shipped — clean evidence per the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule shapes | Do **not** dispatch a full iter. Dispatch ONE `/wr-itil:review-problems` relevance-close sweep reusing the Step 0c `claude -p` pre-flight shape (see Step 0c / Step 5). Its Step 4.6 batch-closes the selected ticket **and any sibling CLOSE-CANDIDATEs** in one the "Governance Skills Commit Their Own Completed Work" architecture rule commit. Set the once-per-session sweep sentinel. Loop back to **Step 1** (the sweep changed the backlog + refreshed the README — re-scan re-applies the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule tier partition from the refreshed rankings). |
|
|
501
|
+
| `0` `CLOSE-CANDIDATE-WITH-CAVEAT` | partial / mixed-phase evidence | Do **not** auto-close — a caveat is the maintainer's decision input, not a mechanical close (review-problems 4.6b/4.6d route AFK caveats to the next interactive confirm). Route to Step 4's user-answerable skip (`skip_reason_category: user-answerable`); queue an `outstanding_questions` entry (`category: "direction"`) carrying the **caveat short-tag + one-line verbatim** from the verdict (the "agent surfaces decisions to user using opaque IDs (P-numbers, ADR-numbers, JTBD-numbers) without explaining what they mean — empathy gap" problem brief-before-ID — surface the close-confirmation question, not a bare ID) + the remedy *"Run `/wr-itil:review-problems` to confirm/close this ticket."* Loop back to **Step 3** (minus the skipped ticket). **Same-session-adjudication carve-out (user direction 2026-07-15):** when the ticket's caveat verdict belongs to a caveat class + cohort ALREADY adjudicated as 0-closes by the maintainer at a same-day interactive `/wr-itil:review-problems` pass — verified from a DURABLE artefact (the review pass's the "Governance Skills Commit Their Own Completed Work" architecture rule commit or the `docs/problems/README.md` last-reviewed line recording the cohort adjudication AND the over-fire class, e.g. the #306 ADR-citation over-fire), never from agent recollection — treat the verdict as **resolved-KEEP** and proceed to Step 4 dispatch. The prior adjudication IS the maintainer decision input this routing exists to collect; re-skipping per-ticket re-asks a decided question (the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem inverse-trap) and can invert the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule tier selection under a known-broken evaluator signal. The carve-out is **class-bound**: a caveat whose short-tag/class was NOT covered by the recorded adjudication routes per the default (skip + queue). The carve-out resolves only toward KEEP/dispatch, never toward close (the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule constraint #1 untouched). Log one iter annotation per application: `Step 3.6 caveat carve-out: P<NNN> resolved-KEEP per <commit/README ref> same-day cohort adjudication`. |
|
|
502
502
|
| `1` `KEEP` / `KEEP-WITH-NOTE` | still relevant (paths present, or Phase-1 false-positive class) | Proceed to Step 4 — dispatch the full iter normally. |
|
|
503
503
|
| `2` `SKIP` | age gate (<7 d) OR no extractable evidence | Proceed to Step 4 — the evaluator gives no close signal; default to work. |
|
|
504
|
-
| `3` error | evaluator failed | Proceed to Step 4 — fail-soft, non-blocking (mirrors review-problems Step 4.6 exit-3 "do not abort the pass" + the Step 0
|
|
504
|
+
| `3` error | evaluator failed | Proceed to Step 4 — fail-soft, non-blocking (mirrors review-problems Step 4.6 exit-3 "do not abort the pass" + the Step 0 the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem pre-flight failure contract). |
|
|
505
505
|
|
|
506
|
-
**Why the sweep, not an inline close**: ADR-
|
|
506
|
+
**Why the sweep, not an inline close**: the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule constraint #1 forbids a standalone relevance-close — the close MUST run inside `/wr-itil:review-problems`. The orchestrator main turn holds no Edit/Write surface (allowed-tools), so it dispatches the sweep rather than closing inline; Step 3.6 must never grow an inline `git mv` to Closed. The dispatched sweep runs as a `claude -p` subprocess that is **AFK-by-construction** — the Step 5 dispatch constraint forbids `AskUserQuestion` in the worker, so review-problems Step 4.6's surface-batch-confirm flow takes the silent-close branch automatically, identical to the existing Step 0c side-effect path ("Step 0c dispatches `/wr-itil:review-problems` which includes Step 4.6 relevance-close"). The sweep is structurally a pre-flight subprocess (backlog refresh it owns end-to-end), so it inherits the **Step 0 pre-flight subprocess failure handling (the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem)** non-blocking revert-and-proceed contract — a failed sweep does NOT halt the loop; fall through to Step 4 normal dispatch and let the full iter rediscover-and-transition (status-quo correctness).
|
|
507
507
|
|
|
508
|
-
**Sweep sentinel (bounded re-dispatch)**: a single review-problems sweep closes every clean CLOSE-CANDIDATE ≥7 d in one pass, so after it commits no clean CLOSE-CANDIDATE should survive the Step 1 re-scan. If a clean CLOSE-CANDIDATE is selected again **after the sentinel is set** (the sweep failed to close it — e.g. review-problems errored), do NOT re-dispatch the sweep (avoids an unbounded sweep loop) and do NOT dispatch a full iter against the already-fixed ticket (the
|
|
508
|
+
**Sweep sentinel (bounded re-dispatch)**: a single review-problems sweep closes every clean CLOSE-CANDIDATE ≥7 d in one pass, so after it commits no clean CLOSE-CANDIDATE should survive the Step 1 re-scan. If a clean CLOSE-CANDIDATE is selected again **after the sentinel is set** (the sweep failed to close it — e.g. review-problems errored), do NOT re-dispatch the sweep (avoids an unbounded sweep loop) and do NOT dispatch a full iter against the already-fixed ticket (the "work-problems re-dispatches already-fixed tickets at full iter cost; add a cheap pre-dispatch relevance-close" problem anti-goal). Route it to Step 4's user-answerable skip + queue an `outstanding_questions` entry (`category: "direction"`) naming the ticket + *"clean CLOSE-CANDIDATE survived a relevance-close sweep — confirm/close manually"*, then loop back to Step 3. This keeps the higher-tier ticket visible (the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule) rather than silently re-worked or silently dropped.
|
|
509
509
|
|
|
510
|
-
**Loopback tier preservation**: the Step 1 re-scan (clean-close branch) and the Step 3 loopback (caveat / sentinel-survivor branches) both re-apply the
|
|
510
|
+
**Loopback tier preservation**: the Step 1 re-scan (clean-close branch) and the Step 3 loopback (caveat / sentinel-survivor branches) both re-apply the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule tier-first selection (Critical-bypass → Inbound-reported → Internal) and within-tier WSJF ladder over the remaining backlog. If every actionable ticket is filtered out, Step 2 stop-condition #1 fires naturally and the accumulated `outstanding_questions` surface at the Step 2.4 gate.
|
|
511
511
|
|
|
512
|
-
**AFK authorisation per
|
|
512
|
+
**AFK authorisation per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6**: the evaluator is read-only (no writes, no commits, no external comms); routing is deterministic per the table above — no `AskUserQuestion` at this step (the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary + the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem mechanical-stage carve-out, identical posture to Step 3.5). User input is preserved at the loop-end Step 2.4 surface where the caveat / survivor questions accumulate. The dispatched sweep's own commit grain is the "Governance Skills Commit Their Own Completed Work" architecture rule (the orchestrator main turn does not commit at Step 3.6).
|
|
513
513
|
|
|
514
|
-
**Compose-with**: ADR-
|
|
514
|
+
**Compose-with**: the "Evidence-based relevance-close pass for the problem backlog (Phase 1: file-no-longer-exists; Phase 2: ADR-shipped-confirmed + named-skill-exists + self-marker-in-body + driver-child-closed + Phase 1 false-positive fixes)" architecture rule (relevance-close evaluator + constraint #1 sweep-not-standalone), the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule (tier-first selection preserved on every loopback), the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule (evidence-grounded verdict + structured caveat field), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5/6 (silent-pass + AFK fail-safe), the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule cat 4 + the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem (mechanical-stage carve-out — no AskUserQuestion), the "Governance Skills Commit Their Own Completed Work" architecture rule (sweep owns its commit), the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule + the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem (subprocess isolation — AFK-by-construction silent-close), the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule (PATH shim), the "Behavioural-tests-default for skill testing" architecture rule / the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem (behavioural coverage via the reused evaluator's bats; no structural SKILL-prose test), the "`claude -p` subprocess dispatch fails with API "socket connection closed unexpectedly" — no staged work survives, salvage path does not apply" problem (pre-flight subprocess failure → non-blocking revert-and-proceed), the "`/wr-itil:review-problems` not auto-fired when needed — user has to remember to run it" problem / Step 0c (dispatch-shape reuse), the "`/wr-itil:work-problems` orchestrator should predicate-check the cited JTBDs of the selected ticket BEFORE dispatching the iter-worker — wasted-iter-dispatch class when JTBDs are unratified" problem / the ": — `/wr-itil:work-problems` Step 3.5 JTBD ratification predicate-check (orchestrator-layer mirror of surface 3)" release design / Step 3.5 (sibling shift-left orchestrator predicate), the "`/wr-itil:review-problems` has no path to close tickets that are no longer relevant (evidence-based, NOT age-based) — structural outflow gap drives monotonic backlog growth" problem / the "Phase 2 — extend `evaluate-relevance.sh` with 4 more evidence shapes + fix Phase 1 file-no-longer-exists false-positive class" problem (relevance-close drivers).
|
|
515
515
|
|
|
516
|
-
<!-- @jtbd
|
|
516
|
+
<!-- @jtbd the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away — pre-dispatch relevance gate closes already-shipped tickets cheaply instead of rediscovering the fix at full iter cost) -->
|
|
517
517
|
|
|
518
518
|
### Step 4: Classify each problem
|
|
519
519
|
|
|
@@ -521,15 +521,15 @@ Read the problem file and apply these deterministic rules:
|
|
|
521
521
|
|
|
522
522
|
| Problem state | Action | Skip-reason category |
|
|
523
523
|
|---|---|---|
|
|
524
|
-
| `.verifying.md` (Verification Pending, per
|
|
525
|
-
| Known Error with fix strategy documented | **Work it** — implement the fix (on release, transition to `.verifying.md` per
|
|
524
|
+
| `.verifying.md` (Verification Pending, per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule) | **Skip** — fix released, awaiting user verification | user-answerable (verification) |
|
|
525
|
+
| Known Error with fix strategy documented | **Work it** — implement the fix (on release, transition to `.verifying.md` per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule) | — |
|
|
526
526
|
| Known Error without fix strategy | **Work it** — produce a fix strategy, then implement | — |
|
|
527
527
|
| Open problem with preliminary hypothesis or investigation notes | **Work it** — continue the investigation | — |
|
|
528
528
|
| Open problem with no leads (empty Root Cause Analysis) | **Work it** — read the relevant code, form a hypothesis, document findings | — |
|
|
529
529
|
| Problem previously attempted twice without progress in this session | **Skip** — mark as stuck, needs interactive attention | user-answerable (direction) |
|
|
530
530
|
| Open problem with outstanding user-answerable design question (naming, direction, pacing, scope) | **Skip** — surface the question at stop (Step 2.5) | user-answerable (design) |
|
|
531
531
|
| Open problem needing architect design judgment (new-ADR-level question) | **Skip** — note the architect-design blocker; Step 2.5 may elevate via a pre-triggered architect call in `--deep-stop` mode | architect-design |
|
|
532
|
-
| Open problem blocked on upstream dependency or Claude Code capability gap | **Auto-invoke `/wr-itil:report-upstream` via the AFK fallback** (per
|
|
532
|
+
| Open problem blocked on upstream dependency or Claude Code capability gap | **Auto-invoke `/wr-itil:report-upstream` via the AFK fallback** (per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 (the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem) amendment — manage-problem Step 6 external-root-cause detection AFK fallback owns the actual invocation; this row routes through it). The report-upstream skill composes the draft then scores the prose via `wr-risk-scorer:external-comms` (the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule); below-appetite → sends; above-appetite → risk-reduces (open-ended LLM judgement per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 second-amendment leaf (a)) then re-scores → sends-or-queues. Security routing per leaf (b): upstream-with-`SECURITY.md` + below-appetite → files via declared channel; upstream-without-`SECURITY.md` → external-comms-gated impact assessment to (i) our repo, (ii) our reputation, (iii) reported party. Queued reports save to `## Queued Upstream Report` (renamed from `## Drafted Upstream Report` per leaf (c)). Queue does NOT halt — outstanding_question surfaces at Step 2.4 / Step 2.5b end-of-loop per the "AFK iter default when a skill needs to ask a question and AskUserQuestion is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem. Iter still classifies the ticket as `upstream-blocked` (the local ticket itself is still blocked on the upstream fix) and **skips work on it** after the report-upstream invocation completes — the report-upstream call is the action this row takes; classification stays `upstream-blocked` so Step 4 routes to skip-rather-than-work. Tickets already carrying `- **Upstream report pending** --` (or the legacy em-dash variant) from prior sessions are detected via the already-noted check and routed to the report-upstream invocation (the marker shape is retained as the detection substrate per the 2026-06-04 amendment; ASCII `--` is the canonical form per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem, em-dash is the legacy form, both matched). | upstream-blocked |
|
|
533
533
|
|
|
534
534
|
The default is to work the problem. Only skip when the rule explicitly says so. This is an AFK loop — forward progress matters more than avoiding dead ends, because dead ends are cheap (findings are saved) and interactive input is expensive (user is absent).
|
|
535
535
|
|
|
@@ -537,7 +537,7 @@ The default is to work the problem. Only skip when the rule explicitly says so.
|
|
|
537
537
|
|
|
538
538
|
- **user-answerable** — the user can answer directly (verification, naming, direction, pacing, scope). Step 2.5 surfaces these as questions (interactive) or in the Outstanding Design Questions table (non-interactive / AFK).
|
|
539
539
|
- **architect-design** — requires architect judgment first; may escalate to a new ADR. Step 2.5 can optionally pre-trigger the architect agent in `--deep-stop` mode to produce a concrete user-answerable question. Otherwise noted as "pending architect review".
|
|
540
|
-
- **upstream-blocked** — external dependency, Claude Code capability gap, or waiting on third-party fix. Truly terminal for this loop — no user question would change anything. Report the blocker (now via auto-invoke of `/wr-itil:report-upstream`, per
|
|
540
|
+
- **upstream-blocked** — external dependency, Claude Code capability gap, or waiting on third-party fix. Truly terminal for this loop — no user question would change anything. Report the blocker (now via auto-invoke of `/wr-itil:report-upstream`, per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 (the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem) amendment) and move on. **Before skipping, run the manage-problem external-root-cause detection AFK fallback** (per the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem amended 2026-06-04): the fallback now invokes `/wr-itil:report-upstream` rather than only appending the marker. The report-upstream skill scores the drafted prose via `wr-risk-scorer:external-comms` (the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule); below-appetite branches send (public-issue Step 5 / comment Step 5c / security Step 6 per classification); above-appetite branches risk-reduce + re-score; if-still-above queue an `outstanding_questions` entry per the "AFK iter default when a skill needs to ask a question and AskUserQuestion is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem queue-and-continue (orchestrator does NOT halt). Existing tickets carrying `- **Upstream report pending** --` (canonical ASCII per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem), `- **Upstream report pending** —` (legacy em-dash), or `- **Reported Upstream:**` / a `## Reported Upstream` section are detected via the already-noted check; the marker shape is retained for backward compatibility and as the detection substrate. The outbound audit trail across AFK iterations now reflects ACTUAL filings (or queued-for-review drafts), not just deferred intents.
|
|
541
541
|
|
|
542
542
|
Record the category alongside the skip reason in the iteration report so Step 2.5 can read the categories deterministically.
|
|
543
543
|
|
|
@@ -545,15 +545,15 @@ Record the category alongside the skip reason in the iteration report so Step 2.
|
|
|
545
545
|
|
|
546
546
|
If a problem is skipped by this step, add it to a "skipped" list with the reason and loop back to step 3 for the next one.
|
|
547
547
|
|
|
548
|
-
### Step 5: Work the problem (dispatch via `claude -p` subprocess, per
|
|
548
|
+
### Step 5: Work the problem (dispatch via `claude -p` subprocess, per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem)
|
|
549
549
|
|
|
550
550
|
**Dispatch each iteration to a fresh `claude -p` subprocess via Bash** — do NOT spawn via the Agent tool, do NOT invoke `/wr-itil:manage-problem` inline via the Skill tool.
|
|
551
551
|
|
|
552
|
-
- **Skill-tool inline invocation** expands manage-problem's SKILL.md (500+ lines) into the main orchestrator's context every iteration, accumulates across the AFK loop, and causes silent early-stop (`ALL_DONE` without a documented stop condition firing). This was the original pre-
|
|
553
|
-
- **Agent-tool dispatch to a `general-purpose` subagent** (the
|
|
554
|
-
- **`claude -p` subprocess dispatch** (this step, per
|
|
552
|
+
- **Skill-tool inline invocation** expands manage-problem's SKILL.md (500+ lines) into the main orchestrator's context every iteration, accumulates across the AFK loop, and causes silent early-stop (`ALL_DONE` without a documented stop condition firing). This was the original pre-the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem failure mode.
|
|
553
|
+
- **Agent-tool dispatch to a `general-purpose` subagent** (the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem amendment) works for context isolation but fails at the governance-gate layer: subagents spawned via the Agent tool do NOT have the Agent tool in their own surface (three-source evidence — ToolSearch probe, Claude Code docs at `code.claude.com/docs/en/subagents.md`, empirical runtime error `"No such tool available: Agent. Agent is not available inside subagents."`). Without Agent, the iteration worker cannot set architect + JTBD PreToolUse edit-gate markers (only settable via Agent-tool PostToolUse hook), cannot satisfy the risk-scorer commit gate, and silently halts on every gate-covered iteration. the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem diagnoses and closes this gap.
|
|
554
|
+
- **`claude -p` subprocess dispatch** (this step, per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem / the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule amendment): the subprocess is a full main Claude Code session with Agent available in its own surface. Governance review runs at full depth via the normal `wr-architect:agent` / `wr-jtbd:agent` / `wr-risk-scorer:pipeline` delegation path inside the subprocess; PostToolUse marker hooks fire correctly matching the subprocess's own `$CLAUDE_SESSION_ID`; the commit gate unlocks natively. Context isolation preserved by the process boundary (each subprocess is a distinct process with its own session state; orchestrator's main context only sees the stdout). This is the AFK iteration-isolation wrapper — subprocess-boundary variant under the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule.
|
|
555
555
|
|
|
556
|
-
**Dispatch command shape (Bash, backgrounded with idle-timeout poll loop per
|
|
556
|
+
**Dispatch command shape (Bash, backgrounded with idle-timeout poll loop per the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem):**
|
|
557
557
|
|
|
558
558
|
```bash
|
|
559
559
|
ITERATION_PROMPT=$(cat <<'PROMPT_EOF'
|
|
@@ -565,7 +565,7 @@ ITER_JSON=$(mktemp)
|
|
|
565
565
|
DISPATCH_START_EPOCH=$(date +%s)
|
|
566
566
|
IDLE_TIMEOUT_S="${WORK_PROBLEMS_IDLE_TIMEOUT_S:-3600}"
|
|
567
567
|
|
|
568
|
-
# AFK-iter cross-context-leak guard (
|
|
568
|
+
# AFK-iter cross-context-leak guard (the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule the "Ship pending-questions-surface hook — auto-surface accumulated `outstanding_questions` from `.afk-run-state/outstanding-questions.jsonl` at session start when user returns interactive" problem amendment, line 127):
|
|
569
569
|
# the orchestrator-session pending-questions queue at
|
|
570
570
|
# .afk-run-state/outstanding-questions.jsonl is for surfacing on the user's
|
|
571
571
|
# next interactive session — NOT inside iter subprocess contexts. The
|
|
@@ -574,34 +574,34 @@ IDLE_TIMEOUT_S="${WORK_PROBLEMS_IDLE_TIMEOUT_S:-3600}"
|
|
|
574
574
|
# into iter subprocesses' first turn.
|
|
575
575
|
export WR_SUPPRESS_PENDING_QUESTIONS=1
|
|
576
576
|
|
|
577
|
-
# AFK-iter oversight-nudge suppression (
|
|
577
|
+
# AFK-iter oversight-nudge suppression (the ": Human-oversight marker + `/wr-architect:review-decisions` drain for recorded decisions" architecture rule): the architect plugin's
|
|
578
578
|
# SessionStart oversight nudge ("N decisions lack human oversight — run
|
|
579
579
|
# /wr-architect:review-decisions") is an interactive batch-confirm prompt. It
|
|
580
580
|
# must NOT fire into an absent-user iter subprocess. architect-oversight-nudge.sh
|
|
581
581
|
# self-suppresses when this env var is set — same discipline as the
|
|
582
|
-
# pending-questions guard above (
|
|
582
|
+
# pending-questions guard above (the ": Progress the Backlog While I'm Away" user outcome friction guard).
|
|
583
583
|
export WR_SUPPRESS_OVERSIGHT_NUDGE=1
|
|
584
584
|
|
|
585
|
-
# AFK-iter correction-signal suppression (
|
|
585
|
+
# AFK-iter correction-signal suppression (the "itil-correction-detect UserPromptSubmit hook false-positives on orchestrator / AFK prompt text" problem / the ": Progress the Backlog While I'm Away" user outcome): the iteration prompt
|
|
586
586
|
# this loop writes is machine-authored, so an ordinary imperative in it ("DO NOT
|
|
587
587
|
# skip the gate") is not a user correcting anything, and no user is present to
|
|
588
588
|
# act on the capture nudge. itil-correction-detect.sh self-suppresses when this
|
|
589
589
|
# env var is set. A real correction is typed into the ORCHESTRATOR session,
|
|
590
|
-
# where this is unset, so
|
|
590
|
+
# where this is unset, so the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem is preserved. Distinct guard class from the
|
|
591
591
|
# oversight nudge above — that one means "cannot ratify", this one means
|
|
592
592
|
# "nobody authored a correction".
|
|
593
593
|
export WR_SUPPRESS_CORRECTION_DETECT=1
|
|
594
594
|
|
|
595
595
|
# Project-scoped governance plugins are NOT loaded by headless `claude -p`
|
|
596
|
-
# (
|
|
596
|
+
# (the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem): it activates only USER-scoped enabledPlugins, and project activation
|
|
597
597
|
# is trust-gated (headless skips trust), so `--setting-sources user,project`
|
|
598
598
|
# alone does not attach them. Without this, the iter subprocess has no
|
|
599
599
|
# windyroad architect/jtbd/risk-scorer/voice-tone agents or gate hooks — it
|
|
600
600
|
# commits ungated and cannot run retro-on-exit. Pass each governance plugin
|
|
601
601
|
# explicitly via `--plugin-dir`, resolved portably from the installed
|
|
602
|
-
# marketplace cache (highest-version-wins,
|
|
603
|
-
#
|
|
604
|
-
# skipped silently. <!-- @jtbd
|
|
602
|
+
# marketplace cache (highest-version-wins, the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule; adopter-safe via the
|
|
603
|
+
# the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule bin-on-PATH shim, NOT a repo-relative path). Unresolvable plugins are
|
|
604
|
+
# skipped silently. <!-- @jtbd the ": Enforce Governance Without Slowing Down" user outcome (iter commits ship gated) @jtbd the ": Progress the Backlog While I'm Away" user outcome (full governance surface inside AFK iters) -->
|
|
605
605
|
mapfile -t PLUGIN_DIR_ARGS < <(wr-itil-resolve-governance-plugin-dirs)
|
|
606
606
|
|
|
607
607
|
claude -p \
|
|
@@ -617,11 +617,11 @@ SIGTERM_SENT=0
|
|
|
617
617
|
LAST_POLL_EPOCH=$DISPATCH_START_EPOCH
|
|
618
618
|
SUSPEND_OFFSET_S=0
|
|
619
619
|
EXPECTED_POLL_DELTA_S=60 # matches `sleep 60` cadence below
|
|
620
|
-
SUSPEND_JITTER_S=120 # tolerance above expected before treating gap as suspend (
|
|
620
|
+
SUSPEND_JITTER_S=120 # tolerance above expected before treating gap as suspend (the "work-problems Step 5 idle-timeout SIGTERM uses wall-clock not active/monotonic time — machine-sleep falsely kills a completing iter and loses its commit + metadata" problem)
|
|
621
621
|
while kill -0 "$ITER_PID" 2>/dev/null; do
|
|
622
622
|
sleep "$EXPECTED_POLL_DELTA_S"
|
|
623
623
|
NOW=$(date +%s)
|
|
624
|
-
#
|
|
624
|
+
# the "work-problems Step 5 idle-timeout SIGTERM uses wall-clock not active/monotonic time — machine-sleep falsely kills a completing iter and loses its commit + metadata" problem machine-sleep false-kill: when the host suspends between polls,
|
|
625
625
|
# wall-clock advances while the iter subprocess is itself suspended (no
|
|
626
626
|
# actual idle work). Detect the wall-clock jump and accumulate it into
|
|
627
627
|
# SUSPEND_OFFSET_S so IDLE_SECONDS (computed against NOW - SUSPEND_OFFSET_S
|
|
@@ -662,56 +662,56 @@ rm -f "$ITER_JSON"
|
|
|
662
662
|
|
|
663
663
|
- `--permission-mode bypassPermissions` — handles non-interactive permission prompts. Without this, Bash/Edit/Write calls inside the subprocess halt on approval prompts (no TTY). Alternative modes (`acceptEdits`, `auto`, `dontAsk`) are acceptable if adopters need narrower permission scopes; `bypassPermissions` is the broadest and the empirically-verified path.
|
|
664
664
|
- `--output-format json` — deterministic structured output. The subprocess's final agent message lands in the JSON response's `.result` field; orchestrator extracts `ITERATION_SUMMARY` from that field. Plain-text output would require fragile scraping.
|
|
665
|
-
- `"${PLUGIN_DIR_ARGS[@]}"` — `--plugin-dir <root>` pairs for each governance plugin, emitted by `wr-itil-resolve-governance-plugin-dirs` (the `mapfile` line above). **Load-bearing (
|
|
666
|
-
- `< /dev/null` — explicit stdin-closed redirect (
|
|
665
|
+
- `"${PLUGIN_DIR_ARGS[@]}"` — `--plugin-dir <root>` pairs for each governance plugin, emitted by `wr-itil-resolve-governance-plugin-dirs` (the `mapfile` line above). **Load-bearing (the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem).** Headless `claude -p` activates only USER-scoped `enabledPlugins`; project-scoped plugins stay inactive because project-plugin activation is trust-gated and headless skips the trust prompt. Empirically (verified 2026-06-21) `--setting-sources user,project` does NOT fix this — only `--plugin-dir` makes a project-scoped plugin's agents/hooks/skills available. Without these args an iter in a project-scope adopter tree commits ungated (architect/jtbd/risk-scorer/voice-tone agents resolve to "not found") and cannot run retro-on-exit. The resolver derives each plugin's root from its `bin/` dir on `$PATH` (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule — present in adopter marketplace-cache trees and source-dev alike) and selects the highest-semver cached version (the "Highest-version-wins shim wrapper for plugin scaffold-template shims" architecture rule — `$PATH` order is frozen at session init and goes stale mid-session, so it is NOT trusted for version selection). Behavioural second-source: `packages/itil/scripts/test/resolve-governance-plugin-dirs.bats`. The expansion is empty (no-op) when no governance plugins resolve, so source-repo dev sessions and minimal adopters degrade gracefully.
|
|
666
|
+
- `< /dev/null` — explicit stdin-closed redirect (the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem Gap 1). Without this, `claude -p` waits up to 3s for stdin data in non-TTY contexts and then prints `Warning: no stdin data received in 3s, proceeding without it. If piping from a slow command, redirect stdin explicitly: < /dev/null to skip, or wait longer.` to stderr. The warning is on stderr — if the caller separates stderr and stdout streams, the warning is harmless. But the orchestrator captures via `2>&1` (required because the CLI emits progress prose on stderr that must not interleave between JSON responses when multiple invocations chain). Under the `2>&1` merge the stderr warning prefixes the stdout JSON and breaks `jq` / `json.load` / `JSON.parse` extraction at "line 1, column 1: Expecting value". The redirect suppresses the warning at source. First observed AFK-iter-7 iter 1 (2026-04-21); workaround is the Anthropic CLI help's own suggestion.
|
|
667
667
|
|
|
668
668
|
**No per-iteration budget cap.** The dispatch deliberately omits `--max-budget-usd`. Per user direction 2026-04-21: the natural stop condition for an AFK loop is quota exhaustion, not an arbitrary per-iteration dollar cap. A cap would halt iterations before quota is actually exhausted, wasting remaining budget. Runaway-iteration risk is bounded by quota + the orchestrator's Step 6.75 halt on unexpected dirty state + exit-code handling below.
|
|
669
669
|
|
|
670
|
-
**Idle-timeout SIGTERM (
|
|
670
|
+
**Idle-timeout SIGTERM (the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem).** The poll loop above is the orchestrator-side guard against stuck iteration subprocesses — iters that complete their semantic work (commits land, retro runs, `ITERATION_SUMMARY` is emitted into the agent output stream) but then sit waiting on a hook timeout, a backgrounded subagent that never resolved, or some other CLI-level idle behaviour before exiting. Without the guard the orchestrator polls indefinitely; the JSON file stays 0 bytes (the CLI only flushes on exit) and wall-clock burns for ~$8/hour of subprocess overhead with no API turns. The 2026-04-25 the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem iter 5 evidence: 121 min wall-clock; final commit at ~100 min; manual SIGTERM at 121 min produced a clean 5649-byte JSON response with `is_error: false`, full `## Session Retrospective` section, parseable `ITERATION_SUMMARY` block, and `duration_ms: 2992935` (49.9 min — the real-work portion). SIGTERM is therefore a safe recovery primitive for this stuck-state class — empirically a clean exit-flush, not a destructive interrupt. Behavioural confirmation lives in `test/work-problems-step-5-idle-timeout-sigterm.bats` (the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem ships with this fixture as the second-source the production observation needed). The default `IDLE_TIMEOUT_S=3600` (60 min) leaves headroom for genuinely long architectural iters; the `WORK_PROBLEMS_IDLE_TIMEOUT_S` env-var overrides per-environment for adopters who run very long iters or want a tighter guard. The orchestrator's Step 6 progress line SHOULD annotate `(SIGTERM_SENT)` when the branch fires so the user can distinguish a SIGTERM-recovered iter from a normal completion (per the ": Progress the Backlog While I'm Away" user outcome audit-trail expectation).
|
|
671
671
|
|
|
672
|
-
**SIGTERM exit-flush is conditional, not universal (
|
|
672
|
+
**SIGTERM exit-flush is conditional, not universal (the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem).** The "clean exit-flush" claim above is empirically true ONLY when the subprocess has already emitted `ITERATION_SUMMARY` through the agent stream before going idle (the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem shape: semantic work complete + retro complete, then idle-wait on some final hook). The 2026-04-29 the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem incident falsified the universal generalisation: an iteration deadlocked in a `bash until`-loop polling a backgrounded-task output file (commits had landed; ITERATION_SUMMARY had NEVER been emitted) and SIGTERM at 68m34s produced exit 143 with a **0-byte JSON file**. `claude -p --output-format json` writes the entire response as a single blob ON normal exit; the SIGTERM-handler (whatever it does inside the CLI) cannot synthesise a JSON response that the agent loop never produced. **Stuck-before-emit subclass: SIGTERM still recovers wall-clock, but loses metadata.** When the orchestrator observes exit 143 + 0-byte JSON, it MUST treat the iteration as a metadata-loss event: (1) verify work integrity from independent evidence (`git log` for commits + `git status --porcelain` for tree state); (2) halt the AFK loop per exit-code semantics rather than silently continue; (3) reconstruct cost from the Anthropic billing dashboard rather than from the missing JSON envelope. The behavioural second-source for the stuck-before-emit case lives in the same `test/work-problems-step-5-idle-timeout-sigterm.bats` fixture (a fake-shim that traps SIGTERM and exits without writing stdout, asserting `JSON_BYTES=0` after the orchestrator-shape harness fires SIGTERM). Cost-of-metadata-loss < cost-of-stuck-subprocess; SIGTERM remains the right recovery primitive — the conditional caveat is about what flushes after, not whether to fire.
|
|
673
673
|
|
|
674
674
|
**LAST_ACTIVITY_MARK signal trade-off.** The mark is `max(DISPATCH_START_EPOCH, last commit timestamp)`. The dispatch-start floor is intentional: skip-iterations that produce no commit (Step 4 routes a ticket to `action: skipped`) are bounded by `IDLE_TIMEOUT_S` since dispatch start, not by an arbitrarily-stale prior-commit timestamp. This protects against false-positive SIGTERM at iter T=0 when the most recent commit happens to be hours old. The trade-off is the inverse: a skip-iter that runs for `IDLE_TIMEOUT_S` (60 min default) will SIGTERM even though it never had a chance to commit. The 60-min default is well past the typical skip-iter wall-clock (a normal skip completes in seconds), so the trade-off rarely fires in practice; adopters who run unusually long skip-evaluation iters (e.g. deep architect-design probes) should raise `WORK_PROBLEMS_IDLE_TIMEOUT_S` accordingly. Alternative signals considered and rejected: `stat -f%m "$ITER_JSON"` (binary — file mtime only changes on subprocess exit, useless during the idle gap); subprocess RSS-change tracking (noisy; spikes during Agent-tool expansions confound the signal). The git-log signal is the cheapest reliable progress indicator the orchestrator already has.
|
|
675
675
|
|
|
676
|
-
**Machine-sleep false-kill — suspend-detect heuristic (
|
|
676
|
+
**Machine-sleep false-kill — suspend-detect heuristic (the "work-problems Step 5 idle-timeout SIGTERM uses wall-clock not active/monotonic time — machine-sleep falsely kills a completing iter and loses its commit + metadata" problem).** The IDLE_SECONDS computation above subtracts `SUSPEND_OFFSET_S` from wall-clock `NOW` so the orchestrator measures *active-elapsed* time rather than raw wall-clock between LAST_ACTIVITY_MARK and now. The offset accumulates whenever a poll observes `ACTUAL_POLL_DELTA > EXPECTED_POLL_DELTA_S + SUSPEND_JITTER_S` (default `60 + 120 = 180s`) — i.e., the gap between consecutive `sleep 60` polls vastly exceeds the cadence the loop scheduled. The driver is the 2026-05-26 iter 1 evidence: the iter's host suspended (lid-close mid-loop) and the next poll observed an idle of 5544s; the wall-clock-only computation tripped SIGTERM at 5544s > 3600s, exit 143 + 0-byte JSON (the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem stuck-before-emit metadata-loss class), losing a commit + cost metadata for an iter whose semantic work had completed. The suspend-detect heuristic converts that wall-clock-elapsed measure to "active-elapsed approximate" without needing monotonic clocks (which bash does not natively expose anyway). Alternatives considered and rejected: (a) monotonic / active-time clocks (POSIX `CLOCK_MONOTONIC` is not surfaced by `date` or `$EPOCHSECONDS`; would require a C helper or a Python-shim subprocess per poll); (b) iter-side heartbeat file the poll loop reads instead of wall-clock (works but adds an iter-side write contract; suspend-detect is purely orchestrator-side, no iter-prompt changes). The jitter buffer (`SUSPEND_JITTER_S=120`) is the load-bearing safety margin: it tolerates slow-hook / GC / brief-load-spike jitter (up to 180s total inter-poll delay) without falsely shifting; only genuine suspend / system-clock jumps cross the threshold. Adopters with unusually noisy hosts can raise `SUSPEND_JITTER_S` per environment; lowering it risks counting brief stalls as suspend. The heuristic is asymmetric — it can absorb a 5 min host hang into the offset and treat it as suspend, but the cost is at worst that one iter runs an extra 5 min before SIGTERM (cheaper than losing the iter's commit + metadata to a false-kill).
|
|
677
677
|
|
|
678
678
|
**Iteration prompt body (self-contained — the subprocess has no prior conversation context):**
|
|
679
679
|
|
|
680
|
-
**Re-ground per iter (
|
|
680
|
+
**Re-ground per iter (the "work-problems orchestrator carries prior-ticket Fix Strategy text into iter dispatch without re-grounding in design intent" problem — orchestrator-side construction invariant)**: each iter's prompt body MUST be re-grounded per iter against the CURRENT ticket's identity (ID + title) only. The orchestrator does NOT inline the target ticket's `## Fix Strategy` section verbatim into the dispatch prompt — the subprocess reads Fix Strategy from disk via `/wr-itil:manage-problem` inside its own context, where the design rationale travels with the ticket file and stays anchored to the correct ticket. Across iterations, no prior-iter content leaks into iter N's prompt body — specifically, prior ticket ID, prior Fix Strategy text, prior outcome reason, prior commit SHA, prior retro findings, and prior outstanding-question entries MUST NOT carry across the iter boundary into the new prompt. The construction is template-driven and reset per iter; no global accumulator carries from iter to iter. The "self-contained" opener above is a subprocess-side property (the subprocess has no prior conversation context); the re-grounding invariant is the symmetric orchestrator-side property (the orchestrator main turn does not carry prior-iter prompt content into the next iter's dispatch construction). the "work-problems orchestrator carries prior-ticket Fix Strategy text into iter dispatch without re-grounding in design intent" problem reported as inbound from downstream consumer bbstats as their the "ADRs accumulate forward-chronology evidence inline (Phase 2 dogfood evidence, amendment history, cross-iter cross-references) — `decisions` bucket dominates context at 41% / 1.3 MiB" problem — without this invariant, an iter inherits a stale design-rationale frame and may land fixes anchored on the wrong ticket's intent, degrading the ": Progress the Backlog While I'm Away" user outcome audit trail. **`@jtbd the ": Progress the Backlog While I'm Away" user outcome`** (load-bearing).
|
|
681
681
|
|
|
682
682
|
1. **Context**: this is one iteration of the AFK work-problems loop. The user is AFK. The orchestrator selected `P<NNN> (<title>)` as the highest-WSJF actionable ticket.
|
|
683
683
|
2. **Task**: apply the `/wr-itil:manage-problem` workflow for `work highest WSJF problem that can be progressed non-interactively as the user is AFK`. Follow manage-problem SKILL.md verbatim, including architect / jtbd / style-guide / voice-tone gate reviews and the commit gate (manage-problem Step 11). Because this subprocess has the Agent tool in its own surface, the normal review-via-subagent paths work — no inline-verdict fallback needed.
|
|
684
|
-
3. **Constraints**: commit the completed work per ADR-014. Do NOT push, do NOT run `push:watch`, do NOT run `release:watch` — the orchestrator's Step 6.5 owns release cadence. Do NOT invoke `capture-*` background skills mid-iter (AFK carve-out — ADR-032), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **P342 mechanical-stage carve-out** (see retro-on-exit constraint #4 below; same trust-boundary as `/wr-retrospective:run-retro` Step 4a verification close-on-evidence — P342); and (b) **the I13 fix-time row draw** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects a Known Error nothing yet proposes a fix for (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter **draws a release row on a story map that already covers the journey**, gives it at least one story card, and makes that card's story name the problem in its own `problems:` list — then proceeds. **A fix proposal is a release row; it is never a new document under `docs/rfcs/`.** Take the identity from the directive, which comes from `wr-itil-next-rfc-id` — the single rule that sees rows, documents and git history at once, and the only one that will not re-issue an identity a row already holds. **UNLESS** an existing vehicle cited in the ticket is already this ticket's fix and merely lacks the trace edge, in which case the iter **wires** that edge — a card on the existing row, or the `problems:` array of a legacy document — rather than drawing a duplicate that fragments the fix across two vehicles (P371; existing-vehicle-untraced sub-case; vehicle-vs-merely-related is a judgement read of citation context, structured-logged as `I13: wired P<NNN> trace edge into existing fix vehicle <ID>`; the load-bearing branch prose lives in the delegated `/wr-itil:manage-problem` I13 gate). This is NOT an aside-capture distraction: the row is the **mandatory vehicle for THIS iter’s own fix** (ADR-071), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, P132), and drawing a row onto a map a person has already approved inherits that approval rather than needing a fresh one. **Two things the iter must NOT do silently**: draw a row whose creation would change what the map’s approval covers — a new map, a new activity column, or a new job on the map’s traces, judged from `oversight_map_substance_keys()` in `lib/story-oversight.sh`, the one place those keys are enumerated — or pick a fix approach no existing decision record covers. Either of those queues ONE entry at `outstanding_questions` and the iter moves to the next problem; the loop is never stopped for it. The predicate can also refuse outright (exit 3), and the two refusals are handled differently: a map edited without being re-rendered is **mechanical** — re-render it with `wr-itil-render-story-map` and ask again, asking nobody — while a repository with no story maps at all queues ONE entry (draw a story map covering this work) and the iter carries on to the next problem rather than halting. Structured-log the draw event to the iter summary (`notes`) per JTBD-006 audit-trail. Do NOT use `ScheduleWakeup` under any circumstance (P083 — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (P135 / ADR-044): direction / deviation-approval / one-time-override / silent-framework observations queue at `ITERATION_SUMMARY.outstanding_questions` for loop-end batched presentation. **This includes the manage-problem substance-confirm-before-build guard (ADR-074 (Confirm a decision's substance before building dependent work)):** when the propose-fix step detects that the fix builds on a born-`proposed` decision whose substance is unconfirmed (via `wr-architect-is-decision-unconfirmed`), the iter does NOT implement on it and does NOT ask mid-loop — it queues a `category: "direction"` entry naming the unconfirmed ADR + its Decision Outcome for loop-end confirmation, and routes the ticket to `action: skipped`, `skip_reason_category: user-answerable`. Building on the unconfirmed substance instead (or guessing the choice) is the P315 failure this guard exists to prevent. The queued substance-confirm is a legitimate cat-1 direction ask — it is NOT counted as lazy in the Step 2d Ask Hygiene Pass (ADR-074 lazy-count exclusion). Per-iter `AskUserQuestion` calls are sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification). Non-interactive defaults apply per ADR-013 Rule 6 + ADR-044's framework-resolution boundary. **Treat the user as transient** (P130): even when observably present at orchestrator dispatch time, the user may answer one question and disappear for hours; presence is not a reliable signal and is not the goal. The iter's job is to progress the ticket and accumulate questions for batched surfacing — not to ask "is it OK to proceed?" at a mechanical-stage boundary. **Do NOT poll `bats` output with a bats-console-summary regex against TAP-format output** (P146 — bash until-loop-deadlock antipattern). The bats-console-summary line `<N> tests, <M> failures` is emitted ONLY by bats's *default* (non-TAP) formatter; `bats --tap` does not emit a console summary, so a polling loop of shape `until [ -f $OUT ] && grep -qE '^[0-9]+ tests?,' $OUT; do sleep 5; done` spins forever after bats completes (silent deadlock — no error, no exit; recovery requires manual SIGTERM with metadata loss per the P146/P147 stuck-before-emit subclass). When you need to wait on a backgrounded bats run, prefer `wait $bg_pid` (Unix idiom — completion signaled by process exit, no regex required) or, for the Bash tool, `run_in_background=true` + `BashOutput` polling on the tool's exit-state field rather than regex-poll on stdout. If you genuinely must regex-poll TAP output, anchor on the TAP plan line `^[0-9]+\.\.[0-9]+` (e.g. `1..1455`) — TAP's plan line is emitted on completion and is format-stable across bats versions; the bats-console-summary line is not. The console-summary vs TAP-format divergence is the load-bearing detail: `bats` and `bats --tap` produce structurally different stdout, and the antipattern assumes the former when iter dispatch typically uses the latter. **Do NOT poll subprocess completion with `pgrep -f '<pattern>'` inside an `until` / `while` loop** (P232 — self-referential pgrep deadlock; sibling variant of P146). `pgrep -f` matches against the FULL command line of every running process, so the polling loop's own `zsh -c` argument (which contains the literal `pgrep -f '<pattern>'` text) matches itself; with multiple concurrent polling loops, each loop matches the others and spins forever. Worked example of the antipattern: `until ! pgrep -f 'bats --recursive' > /dev/null 2>&1; do sleep 5; done` — the 2026-05-16 P232 deadlock witness; 4 concurrent polling loops each matched the others' command lines while no actual bats process ran; 45 min wall-clock + $20-30 wasted before manual SIGTERM. The same self-reference shape applies to `while pgrep -f ...; do sleep; done` and to `until ! pkill -0 -f '<pattern>'` / `while pkill -0 -f '<pattern>'` (signal-0 polling). The structural fix is the same as P146: prefer `wait $bg_pid` (Unix idiom — shell-native completion signal, no regex / no pgrep) or Bash-tool `run_in_background=true` + `BashOutput` polling (harness-tracked completion state). The hook `packages/itil/hooks/itil-bash-polling-antipattern-detect.sh` denies these shapes at PreToolUse:Bash, but the prompt rule belongs here too — structural enforcement + prompt discipline together close the class. **Do NOT leave a backgrounded task unreaped at turn-end** (`run_in_background: true` on an Agent or Bash tool call, or a `&`-detached shell job, whose completion you intend to observe in a *later* turn) inside iter dispatch contexts (P370 — turn-end-mid-background work-loss; sibling-class to P083 / P146 / P232). The iter subprocess is dispatched via `claude -p`, a single-shot CLI invocation with NO auto-resume affordance: its turn boundary IS its process boundary. A background task that outlives the turn never resumes — the iter exits at turn-end with the task incomplete and its own work staged but uncommitted (witnessed: iter 11 of a prior loop — $8.02 / 17 min / 8 staged files / 11 GREEN bats / ZERO commits; recovery required orchestrator main-turn salvage). **The prohibition is on the cross-turn / turn-end-survivor shape, NOT on backgrounding per se:** the P146/P232-sanctioned idiom of launching `run_in_background=true` + `BashOutput`-poll-then-`wait $bg_pid` (or plain `wait $bg_pid` on a `&` job) **within the same turn** is fine — it reaps the task before turn-end. Use foreground-synchronous invocation instead: the Agent tool WITHOUT `run_in_background: true` (the result returns in-turn, so the commit step is reached), or intra-turn background that you `wait` on before the turn closes. The distinction from the P146/P232 polling antipatterns: those forbid *how* you wait (regex / pgrep poll loops); this forbids *deferring a task's completion past the turn boundary*, where `claude -p` has no notification re-entry to bring you back. The interactive Claude Code session masks this hazard (notification-driven re-entry); the AFK iter subprocess does not. **If the fix changes shippable code or package behaviour** (any path under `packages/<plugin>/{src,bin,hooks,skills,scripts,lib,agents}` excluding test paths — `test/`, `hooks/test/`, `scripts/test/` — and excluding `README.md` + `docs/*.md`), **the iter MUST author a `.changeset/*.md` entry in the same single ADR-014-grain commit as the fix** (the changeset names the bumping plugin via the YAML frontmatter `"@windyroad/<plugin>": <patch|minor|major>` per the changesets-action contract). **Doc-only changes** (under `docs/`, `*.md`) **and test-only changes** (under any `test/` path) **that ship no behaviour MAY omit the changeset**. The orchestrator's Step 6.5 release-cadence drain runs `release:watch` only when `.changeset/` is non-empty after push — without an iter-authored changeset, code-shape fixes accumulate without ever shipping to npm (violating JTBD-006's audit-trail expectation + JTBD-007's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (P141) provides hook-level enforcement at `git commit` time as defence-in-depth — but plugin hook execution depends on the marketplace cache carrying the current hook version, so the prompt-time constraint here MUST land independently (composes-with the hook; does NOT rely on the hook being installed). Inbound-reported from downstream consumer bbstats as their P195 — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per ADR-076. **`@jtbd JTBD-006`** (load-bearing) **`@jtbd JTBD-007`** (closure-dependent).
|
|
685
|
-
4. **Retro-on-exit (
|
|
684
|
+
3. **Constraints**: commit the completed work per the "Governance Skills Commit Their Own Completed Work" architecture rule. Do NOT push, do NOT run `push:watch`, do NOT run `release:watch` — the orchestrator's Step 6.5 owns release cadence. Do NOT invoke `capture-*` background skills mid-iter (AFK carve-out — the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule), **EXCEPT** (a) **retro-surfaced observations of recurring class-of-behaviour** — those route to `/wr-itil:capture-problem` per the **the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem mechanical-stage carve-out** (see retro-on-exit constraint #4 below; same trust-boundary as `/wr-retrospective:run-retro` Step 4a verification close-on-evidence — the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem); and (b) **the I13 fix-time row draw** — when the propose-fix gate inside the delegated `/wr-itil:manage-problem` traversal detects a Known Error nothing yet proposes a fix for (`wr-itil-check-fix-rfc-trace` emits a `no-rfc-trace:` directive), the iter **draws a release row on a story map that already covers the journey**, gives it at least one story card, and makes that card's story name the problem in its own `problems:` list — then proceeds. **A fix proposal is a release row; it is never a new document under `docs/rfcs/`.** Take the identity from the directive, which comes from `wr-itil-next-rfc-id` — the single rule that sees rows, documents and git history at once, and the only one that will not re-issue an identity a row already holds. **UNLESS** an existing vehicle cited in the ticket is already this ticket's fix and merely lacks the trace edge, in which case the iter **wires** that edge — a card on the existing row, or the `problems:` array of a legacy document — rather than drawing a duplicate that fragments the fix across two vehicles (the "manage-problem I13 propose-fix gate auto-creates a new RFC instead of wiring an existing fix-vehicle's trace edge" problem; existing-vehicle-untraced sub-case; vehicle-vs-merely-related is a judgement read of citation context, structured-logged as `I13: wired P<NNN> trace edge into existing fix vehicle <ID>`; the load-bearing branch prose lives in the delegated `/wr-itil:manage-problem` I13 gate). This is NOT an aside-capture distraction: the row is the **mandatory vehicle for THIS iter’s own fix** (the "Every fix goes through an RFC" architecture rule), not a tangential observation — it is in-scope working of the current ticket, framework-mediated (NOT cat-1 direction-setting → NO `AskUserQuestion`, the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem), and drawing a row onto a map a person has already approved inherits that approval rather than needing a fresh one. **Two things the iter must NOT do silently**: draw a row whose creation would change what the map’s approval covers — a new map, a new activity column, or a new job on the map’s traces, judged from `oversight_map_substance_keys()` in `lib/story-oversight.sh`, the one place those keys are enumerated — or pick a fix approach no existing decision record covers. Either of those queues ONE entry at `outstanding_questions` and the iter moves to the next problem; the loop is never stopped for it. The predicate can also refuse outright (exit 3), and the two refusals are handled differently: a map edited without being re-rendered is **mechanical** — re-render it with `wr-itil-render-story-map` and ask again, asking nobody — while a repository with no story maps at all queues ONE entry (draw a story map covering this work) and the iter carries on to the next problem rather than halting. Structured-log the draw event to the iter summary (`notes`) per the ": Progress the Backlog While I'm Away" user outcome audit-trail. Do NOT use `ScheduleWakeup` under any circumstance (the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem — iteration workers must not self-reschedule). **NEVER call `AskUserQuestion` mid-loop in AFK** (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule): direction / deviation-approval / one-time-override / silent-framework observations queue at `ITERATION_SUMMARY.outstanding_questions` for loop-end batched presentation. **This includes the manage-problem substance-confirm-before-build guard (the ": Confirm a decision's substance before building dependent work on it" architecture rule (Confirm a decision's substance before building dependent work)):** when the propose-fix step detects that the fix builds on a born-`proposed` decision whose substance is unconfirmed (via `wr-architect-is-decision-unconfirmed`), the iter does NOT implement on it and does NOT ask mid-loop — it queues a `category: "direction"` entry naming the unconfirmed ADR + its Decision Outcome for loop-end confirmation, and routes the ticket to `action: skipped`, `skip_reason_category: user-answerable`. Building on the unconfirmed substance instead (or guessing the choice) is the "Agent implements dependent work on genuine new decisions before human-confirming their SUBSTANCE — surfaces only meta-questions" problem failure this guard exists to prevent. The queued substance-confirm is a legitimate cat-1 direction ask — it is NOT counted as lazy in the Step 2d Ask Hygiene Pass (the ": Confirm a decision's substance before building dependent work on it" architecture rule lazy-count exclusion). Per-iter `AskUserQuestion` calls are sub-contracting framework-resolved decisions back to the user (lazy deferral per Step 2d Ask Hygiene Pass classification). Non-interactive defaults apply per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's framework-resolution boundary. **Treat the user as transient** (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem): even when observably present at orchestrator dispatch time, the user may answer one question and disappear for hours; presence is not a reliable signal and is not the goal. The iter's job is to progress the ticket and accumulate questions for batched surfacing — not to ask "is it OK to proceed?" at a mechanical-stage boundary. **Do NOT poll `bats` output with a bats-console-summary regex against TAP-format output** (the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem — bash until-loop-deadlock antipattern). The bats-console-summary line `<N> tests, <M> failures` is emitted ONLY by bats's *default* (non-TAP) formatter; `bats --tap` does not emit a console summary, so a polling loop of shape `until [ -f $OUT ] && grep -qE '^[0-9]+ tests?,' $OUT; do sleep 5; done` spins forever after bats completes (silent deadlock — no error, no exit; recovery requires manual SIGTERM with metadata loss per the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem stuck-before-emit subclass). When you need to wait on a backgrounded bats run, prefer `wait $bg_pid` (Unix idiom — completion signaled by process exit, no regex required) or, for the Bash tool, `run_in_background=true` + `BashOutput` polling on the tool's exit-state field rather than regex-poll on stdout. If you genuinely must regex-poll TAP output, anchor on the TAP plan line `^[0-9]+\.\.[0-9]+` (e.g. `1..1455`) — TAP's plan line is emitted on completion and is format-stable across bats versions; the bats-console-summary line is not. The console-summary vs TAP-format divergence is the load-bearing detail: `bats` and `bats --tap` produce structurally different stdout, and the antipattern assumes the former when iter dispatch typically uses the latter. **Do NOT poll subprocess completion with `pgrep -f '<pattern>'` inside an `until` / `while` loop** (the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem — self-referential pgrep deadlock; sibling variant of the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem). `pgrep -f` matches against the FULL command line of every running process, so the polling loop's own `zsh -c` argument (which contains the literal `pgrep -f '<pattern>'` text) matches itself; with multiple concurrent polling loops, each loop matches the others and spins forever. Worked example of the antipattern: `until ! pgrep -f 'bats --recursive' > /dev/null 2>&1; do sleep 5; done` — the 2026-05-16 the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem deadlock witness; 4 concurrent polling loops each matched the others' command lines while no actual bats process ran; 45 min wall-clock + $20-30 wasted before manual SIGTERM. The same self-reference shape applies to `while pgrep -f ...; do sleep; done` and to `until ! pkill -0 -f '<pattern>'` / `while pkill -0 -f '<pattern>'` (signal-0 polling). The structural fix is the same as the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem: prefer `wait $bg_pid` (Unix idiom — shell-native completion signal, no regex / no pgrep) or Bash-tool `run_in_background=true` + `BashOutput` polling (harness-tracked completion state). The hook `packages/itil/hooks/itil-bash-polling-antipattern-detect.sh` denies these shapes at PreToolUse:Bash, but the prompt rule belongs here too — structural enforcement + prompt discipline together close the class. **Do NOT leave a backgrounded task unreaped at turn-end** (`run_in_background: true` on an Agent or Bash tool call, or a `&`-detached shell job, whose completion you intend to observe in a *later* turn) inside iter dispatch contexts (the "Iter subprocess ends its turn waiting on a backgrounded task and never resumes — `claude -p` has no auto-resume; commit-bearing work is lost" problem — turn-end-mid-background work-loss; sibling-class to the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem / the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem / the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem). The iter subprocess is dispatched via `claude -p`, a single-shot CLI invocation with NO auto-resume affordance: its turn boundary IS its process boundary. A background task that outlives the turn never resumes — the iter exits at turn-end with the task incomplete and its own work staged but uncommitted (witnessed: iter 11 of a prior loop — $8.02 / 17 min / 8 staged files / 11 GREEN bats / ZERO commits; recovery required orchestrator main-turn salvage). **The prohibition is on the cross-turn / turn-end-survivor shape, NOT on backgrounding per se:** the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem-sanctioned idiom of launching `run_in_background=true` + `BashOutput`-poll-then-`wait $bg_pid` (or plain `wait $bg_pid` on a `&` job) **within the same turn** is fine — it reaps the task before turn-end. Use foreground-synchronous invocation instead: the Agent tool WITHOUT `run_in_background: true` (the result returns in-turn, so the commit step is reached), or intra-turn background that you `wait` on before the turn closes. The distinction from the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem polling antipatterns: those forbid *how* you wait (regex / pgrep poll loops); this forbids *deferring a task's completion past the turn boundary*, where `claude -p` has no notification re-entry to bring you back. The interactive Claude Code session masks this hazard (notification-driven re-entry); the AFK iter subprocess does not. **If the fix changes shippable code or package behaviour** (any path under `packages/<plugin>/{src,bin,hooks,skills,scripts,lib,agents}` excluding test paths — `test/`, `hooks/test/`, `scripts/test/` — and excluding `README.md` + `docs/*.md`), **the iter MUST author a `.changeset/*.md` entry in the same single the "Governance Skills Commit Their Own Completed Work" architecture rule-grain commit as the fix** (the changeset names the bumping plugin via the YAML frontmatter `"@windyroad/<plugin>": <patch|minor|major>` per the changesets-action contract). **Doc-only changes** (under `docs/`, `*.md`) **and test-only changes** (under any `test/` path) **that ship no behaviour MAY omit the changeset**. The orchestrator's Step 6.5 release-cadence drain runs `release:watch` only when `.changeset/` is non-empty after push — without an iter-authored changeset, code-shape fixes accumulate without ever shipping to npm (violating the ": Progress the Backlog While I'm Away" user outcome's audit-trail expectation + the ": Keep Plugins Current Across Projects" user outcome's "Keep Plugins Current" closure dependency). Hook `packages/itil/hooks/itil-changeset-discipline.sh` (the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem) provides hook-level enforcement at `git commit` time as defence-in-depth — but plugin hook execution depends on the marketplace cache carrying the current hook version, so the prompt-time constraint here MUST land independently (composes-with the hook; does NOT rely on the hook being installed). Inbound-reported from downstream consumer bbstats as their the "Briefing Tier 3 rotation repeat-deferral — 13 of 14 topic files over budget with 2 in MUST_SPLIT (≥2× ceiling) branch" problem — see [Related](#related) for `**Origin**: inbound-reported (bbstats#195)` per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule. **`@jtbd the ": Progress the Backlog While I'm Away" user outcome`** (load-bearing) **`@jtbd the ": Keep Plugins Current Across Projects" user outcome`** (closure-dependent).
|
|
685
|
+
4. **Retro-on-exit (the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem) + retro-surfaced observation classification (the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem) + iter-owned BRIEFING commit (the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem)**: before emitting `ITERATION_SUMMARY`, invoke `/wr-retrospective:run-retro`. Retro runs INSIDE this subprocess so its Step 2b pipeline-instability scan has access to the iteration's rich tool-call history (hook misbehaviour, repeat-workaround patterns, subagent-delegation friction, release-path instability). Tickets retro creates ride a separate path: they delegate through `/wr-itil:manage-problem` which IS the "Governance Skills Commit Their Own Completed Work" architecture rule in-scope and self-commits each ticket per its own Step 11. Those commits land independently and the orchestrator picks them up on the next Step 1 scan.
|
|
686
686
|
|
|
687
|
-
**BRIEFING.md commit responsibility — iter owns, run-retro does not (
|
|
687
|
+
**BRIEFING.md commit responsibility — iter owns, run-retro does not (the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem).** run-retro is explicitly out-of-scope for self-commit per the "Governance Skills Commit Their Own Completed Work" architecture rule's Scope section (which lists `packages/retrospective/skills/run-retro/SKILL.md` under "Out of scope for now"). Retro therefore EDITS but DOES NOT COMMIT `docs/BRIEFING.md` / `docs/briefing/*.md`. The iter subprocess (NOT run-retro, NOT the orchestrator main turn) owns the BRIEFING commit. After retro completes, run `git status --porcelain docs/BRIEFING.md docs/briefing/`. If non-empty, the iter:
|
|
688
688
|
|
|
689
689
|
1. Stages the dirty BRIEFING paths (`git add docs/BRIEFING.md docs/briefing/`).
|
|
690
|
-
2. Delegates to `wr-risk-scorer:pipeline` per
|
|
690
|
+
2. Delegates to `wr-risk-scorer:pipeline` per the "Governance Skills Commit Their Own Completed Work" architecture rule's `work → score → commit` ordering. The BRIEFING refresh is mechanical chore-class (derived retro output, no source-of-truth change) — within-appetite by construction, same risk shape as the `chore(problems): reconcile README ...` and `chore(problems): check upstream responses` precedents in the "Governance Skills Commit Their Own Completed Work" architecture rule's commit-message convention table.
|
|
691
691
|
3. Commits as `chore(briefing): refresh from iter retro (P<NNN>)` where `P<NNN>` is the ticket the iter was working.
|
|
692
692
|
|
|
693
|
-
Pre-
|
|
693
|
+
Pre-the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem, the orchestrator's Step 6.75 absorbed this as `dirty-for-a-known-reason` and added the commit at orchestrator-main-turn cost, invoking `wr-risk-scorer:pipeline` twice per iter (once for the ticket commit, once for the orchestrator-side hand-off). Shifting the commit into the iter subprocess preserves the audit trail (the same `chore(briefing)` commit lands), eliminates the orchestrator-main-turn hand-off, and moves the second scoring call from expensive main-turn context to cheaper iter-subprocess context. Step 6.75's table is amended below to classify dirty BRIEFING-at-iter-exit as a bug class rather than an expected hand-off.
|
|
694
694
|
|
|
695
695
|
Proceed to `ITERATION_SUMMARY` emission regardless of retro findings — retro is non-blocking at the iter-subprocess layer (do not block on retro): if retro fails or surfaces findings, the iteration still returns a summary so the AFK loop does not silently halt on a flaky retro run. The iter MUST verify `git status` is clean (no remaining BRIEFING dirty state) before emitting `ITERATION_SUMMARY`. (Session-level retro at the orchestrator-main-turn layer per Step 2.4 gate (b) IS load-bearing — distinct surface; see Step 2.4 prose for the orchestrator-layer halt semantics.)
|
|
696
696
|
|
|
697
|
-
**
|
|
697
|
+
**the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem classification taxonomy — retro-surfaced observations.** When the iter-retro's Step 4b Stage 1 surfaces a ticketable observation, the routing depends on classification:
|
|
698
698
|
|
|
699
|
-
- **Recurring class-of-behaviour observation** (sibling iters hit same pattern; SKILL-contract drift; hook misbehaviour; framework-gap; pipeline instability with concrete fix path): **auto-ticket via `/wr-itil:capture-problem` with pre-resolved persona + JTBD flags** (or `/wr-itil:manage-problem` if capture-problem sibling not yet available). This is the **mechanical-stage carve-out per run-retro Step 4a precedent** — the retro IS the system designed to mechanically observe and surface recurring class-of-behaviour, so its output ticketing is policy-authorised silent proceed per
|
|
699
|
+
- **Recurring class-of-behaviour observation** (sibling iters hit same pattern; SKILL-contract drift; hook misbehaviour; framework-gap; pipeline instability with concrete fix path): **auto-ticket via `/wr-itil:capture-problem` with pre-resolved persona + JTBD flags** (or `/wr-itil:manage-problem` if capture-problem sibling not yet available). This is the **mechanical-stage carve-out per run-retro Step 4a precedent** — the retro IS the system designed to mechanically observe and surface recurring class-of-behaviour, so its output ticketing is policy-authorised silent proceed per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5. The capture-problem dispatch commits its own ticket per the "Governance Skills Commit Their Own Completed Work" architecture rule; the ticket enters the WSJF queue on the orchestrator's next Step 1 scan. This is the routing that closes the silent-queue-accumulation gap the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem names.
|
|
700
700
|
|
|
701
|
-
**Dispatch shape under the I12 derive-then-ratify contract (
|
|
701
|
+
**Dispatch shape under the I12 derive-then-ratify contract (the "Problem-RFC-Story framework with mandatory problem-trace and unified problem ontology" architecture rule Amendment 2026-06-02; the ": User-stated preconditions / paired-capability check" standing risk paired-capability gap)**: AFK callers MUST pre-resolve persona + JTBD via flags or capture-problem halts-with-stderr-directive (per capture-problem SKILL.md Step 1.5b AFK halt clause). The halt stderr is unobservable to the AFK user — silent loop-stall, violating the ": Progress the Backlog While I'm Away" user outcome's audit-trail guarantee. The iter subprocess derives both values from iter context BEFORE invoking capture-problem:
|
|
702
702
|
|
|
703
703
|
1. **Persona derivation from iter context**: the iter is dispatched against a specific ticket carrying Origin + RFC trace + story trace; derive persona from those signals. Default to `developer` when context is ambiguous — it is the dominant persona across this monorepo's JTBD corpus. **Validate the derived value against the persona enum `{developer | tech-lead | plugin-developer | plugin-user}` BEFORE dispatch** (capture-problem halts-with-directive on invalid `--persona=` per its SKILL.md Step 1.5b validation rule). On invalid-derivation, route to `outstanding_questions` (genuinely-ambiguous branch below) instead of dispatching with a bad value.
|
|
704
|
-
2. **JTBD derivation from iter context**: read the iter-prompt content. Cite `
|
|
705
|
-
3. **Dispatch shape**: `/wr-itil:capture-problem --no-prompt --persona=<derived> --jtbd=<derived-list> "<description>"`. The `--no-prompt` flag is the AFK-mode marker that suppresses the I12 derive-then-ratify `AskUserQuestion` fallback inside capture-problem (per its SKILL.md Step 1.5b AFK halt clause); combined with the pre-resolved `--persona` + `--jtbd` flags, the derive-success silent-proceed path fires per
|
|
704
|
+
2. **JTBD derivation from iter context**: read the iter-prompt content. Cite `the ": Progress the Backlog While I'm Away" user outcome` for AFK-loop-continuity / iter-dispatch / orchestrator-mechanic contexts; `the ": Enforce Governance Without Slowing Down" user outcome` for governance / ADR / decision-record contexts; `the "Extend the Suite with New Plugins" user outcome` for plugin-discoverability / plugin-developer / suite-extension contexts. Multi-JTBD entries are allowed (comma-separated, no spaces — per capture-problem's `--jtbd=` flag grammar).
|
|
705
|
+
3. **Dispatch shape**: `/wr-itil:capture-problem --no-prompt --persona=<derived> --jtbd=<derived-list> "<description>"`. The `--no-prompt` flag is the AFK-mode marker that suppresses the I12 derive-then-ratify `AskUserQuestion` fallback inside capture-problem (per its SKILL.md Step 1.5b AFK halt clause); combined with the pre-resolved `--persona` + `--jtbd` flags, the derive-success silent-proceed path fires per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule category 4 silent-framework.
|
|
706
706
|
4. **Genuinely-ambiguous derivation** (cannot pick persona/JTBD cleanly from iter context; signals contradict; derived persona fails enum validation): do NOT invoke capture-problem (would halt-with-stderr-directive into the iter subprocess's unobservable stderr; the observation is lost). Instead, queue the observation as an `outstanding_questions` entry with `category: "direction"`, naming the candidate-anchoring options for the orchestrator main-turn Step 2.5 surface. The orchestrator's `AskUserQuestion` on user return resolves the anchoring, then the user (or a future retro pass) creates the ticket.
|
|
707
707
|
|
|
708
708
|
- **Direction-setting observation** (genuine user-judgment-bound question — design choice, deviation-approval, framework boundary): route to `outstanding_questions` entry per the ITERATION_SUMMARY schema. Orchestrator-level Step 2.5 surfaces these at loop end per the existing batched `AskUserQuestion` flow. These observations preserve the user's authority surface and MUST NOT auto-ticket.
|
|
709
|
-
- **Ambiguous** (retro cannot cleanly distinguish recurring-class from direction-setting): **default to auto-ticket** per the
|
|
709
|
+
- **Ambiguous** (retro cannot cleanly distinguish recurring-class from direction-setting): **default to auto-ticket** per the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem trust-boundary asymmetry, using the same persona + JTBD derivation contract above. The ticket lifecycle (`/wr-itil:manage-problem` Step 9d / `/wr-itil:review-problems` Step 4) will surface any embedded direction-setting question through the standard problem-review flow. Defaulting to queue would re-introduce the silent-queue-accumulation hazard the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem closes; defaulting to ticket has zero observation-drop risk. If persona/JTBD derivation itself fails (the recurring-class derivation branch's step 4), fall through to `outstanding_questions` rather than dispatch a halt-bound capture-problem.
|
|
710
710
|
|
|
711
|
-
The classification is silent agent judgement (no `AskUserQuestion` per observation — that would re-route mechanical decisions back to the user, the lazy-deferral surface
|
|
711
|
+
The classification is silent agent judgement (no `AskUserQuestion` per observation — that would re-route mechanical decisions back to the user, the lazy-deferral surface the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule close). The mirror locus is run-retro `Step 4b` — same trust-boundary applies whether retro fires in iter context (this surface) OR standalone in main turn (run-retro Step 4b).
|
|
712
712
|
5. **Output**: end the final message with the `ITERATION_SUMMARY` block defined below — this is how the orchestrator consumes the iteration's result.
|
|
713
713
|
|
|
714
|
-
**Return-summary contract** (unchanged from the
|
|
714
|
+
**Return-summary contract** (unchanged from the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem amendment — the parse shape is dispatch-mechanism-agnostic). The subprocess's final message MUST end with this structured block, extracted by the orchestrator from the JSON `.result` field:
|
|
715
715
|
|
|
716
716
|
```
|
|
717
717
|
ITERATION_SUMMARY
|
|
@@ -723,12 +723,12 @@ committed: true | false | skipped
|
|
|
723
723
|
commit_sha: <sha> # required when committed=true
|
|
724
724
|
reason: <one-line> # required when committed=false or action=skipped
|
|
725
725
|
skip_reason_category: user-answerable | architect-design | upstream-blocked # required when action=skipped
|
|
726
|
-
outstanding_questions: [<entry per
|
|
726
|
+
outstanding_questions: [<entry per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule 6-class taxonomy — see schema below>] # mandatory non-empty when iter touched a direction / deviation-approval / one-time-override / silent-framework decision; otherwise empty array
|
|
727
727
|
remaining_backlog_count: <N>
|
|
728
728
|
notes: <one-line>
|
|
729
729
|
```
|
|
730
730
|
|
|
731
|
-
**`outstanding_questions` schema (
|
|
731
|
+
**`outstanding_questions` schema (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem Phase 3 / the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule)**: each entry is tagged with its category for loop-end Step 2.5 ranking. Two shapes:
|
|
732
732
|
|
|
733
733
|
```
|
|
734
734
|
# Standard direction / one-time-override / silent-framework / taste / correction-followup entry:
|
|
@@ -739,11 +739,11 @@ notes: <one-line>
|
|
|
739
739
|
ticket_id: "P<NNN>" # the iter's ticket; loop-end groups by ticket
|
|
740
740
|
}
|
|
741
741
|
|
|
742
|
-
# Deviation-candidate entry (the anti-BUFD-for-framework-evolution shape per
|
|
742
|
+
# Deviation-candidate entry (the anti-BUFD-for-framework-evolution shape per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule):
|
|
743
743
|
{
|
|
744
744
|
category: "deviation-approval"
|
|
745
745
|
existing_decision: "<ADR-NNN section / SKILL.md path:line / RISK-POLICY clause>"
|
|
746
|
-
contradicting_evidence: "<tool invocation + observable outcome per
|
|
746
|
+
contradicting_evidence: "<tool invocation + observable outcome per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding>"
|
|
747
747
|
proposed_shape: "amend" | "supersede" | "one-time"
|
|
748
748
|
rationale: "<one-line — why current evidence contradicts the existing decision>"
|
|
749
749
|
ticket_id: "P<NNN>"
|
|
@@ -754,9 +754,9 @@ When the iter encounters an existing decision (ADR / SKILL contract / WSJF rule
|
|
|
754
754
|
|
|
755
755
|
Architect review (R2) requires the commit state fields (`committed` / `commit_sha` / `reason`) so **Step 6.75's Dirty-for-known-reason branch stays evaluable** from the summary alone. JTBD review requires `ticket_id` / `action` / `skip_reason_category` / `outstanding_questions` so Step 2.5 and the Output Format's Completed / Skipped / Outstanding Design Questions tables can be populated deterministically without the orchestrator having to re-parse ticket files.
|
|
756
756
|
|
|
757
|
-
**Between-iter aggregation (
|
|
757
|
+
**Between-iter aggregation (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem Phase 3)**: orchestrator's main turn appends each iter's `outstanding_questions` entries to a session-level queue file at `.afk-run-state/outstanding-questions.jsonl` between Step 6 (report) and Step 6.5 (release-cadence check). Each line is one JSON-encoded entry per the schema above. Loop-end emit (Step 2.5) reads the queue file, de-duplicates, ranks (deviation-approval > direction > one-time-override > silent-framework > taste > correction-followup), and presents as batched `AskUserQuestion` per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 cap (≤4 per call, sequential if >4). Per the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule pending-questions artefact precedent.
|
|
758
758
|
|
|
759
|
-
**Mid-loop UserPromptSubmit handling (
|
|
759
|
+
**Mid-loop UserPromptSubmit handling (the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem Phase 3 / R4)**: when the orchestrator receives a user message DURING an iter (e.g. the user returns mid-loop and sends a new directive), the orchestrator MUST let the in-flight iter complete naturally to its `ITERATION_SUMMARY` emission BEFORE surfacing the new direction or the accumulated queue. Do NOT abort the iter mid-flight (no SIGTERM to the iter PID; no kill signal). The corrective for the 2026-04-27 iter-9-killed overcorrection: the user's correction was about future iter dispatch shape, not about the in-flight iter; killing wasted ~$5 + 25 min in-flight work. The handler waits for the natural exit, surfaces the queue + the new direction together, then routes per the user's response.
|
|
760
760
|
|
|
761
761
|
**Per-iteration cost metadata.** Alongside `.result`, the `claude -p --output-format json` response carries cost + usage fields in the same JSON blob. The orchestrator MUST extract these **named fields only** into per-iteration totals and session aggregates — nothing else from the JSON should be surfaced to the user or logged (PII guard: the response also carries `session_id`, `model`, `stop_reason`, and other envelope fields; the extraction is **scoped to the named fields** below so future contributors do not unconsciously broaden it).
|
|
762
762
|
|
|
@@ -787,32 +787,32 @@ SESSION_CACHE_READ_TOKENS=$(( ${SESSION_CACHE_READ_TOKENS:-0} + ITER_CACHE_READ
|
|
|
787
787
|
|
|
788
788
|
Do NOT extract `session_id`, `model`, `stop_reason`, `permission_denials`, `uuid`, or any other field from the JSON response. Those are subprocess-envelope fields that serve no user-visible purpose and risk leaking subprocess-internal identifiers into orchestrator output.
|
|
789
789
|
|
|
790
|
-
**Authority hierarchy (
|
|
790
|
+
**Authority hierarchy (the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem Gap 2).** `total_cost_usd` and `usage.*` do NOT have the same reliability envelope — treat them accordingly when aggregating:
|
|
791
791
|
|
|
792
792
|
- `.total_cost_usd` is **authoritative for dollar cost** — cumulative across the subprocess's entire lifetime by contract. Use it as the sole source of truth for the Session Cost "Total cost (USD)" column and any cost-based stop condition.
|
|
793
793
|
- `.usage.*` token fields are **best-effort approximate** — the Anthropic CLI returns the final API response envelope, which is per-turn by construction. When the subprocess exits on a normal final turn the fields accumulate real usage; when the subprocess exits via a background-task completion-notification ack (a closing turn that only acknowledges a backgrounded task finished), the fields reflect ONLY that final ack turn and undercount dramatically. Detectable anomaly shape: the subprocess reports a final-turn-sized usage (handful of input tokens, hundreds of output tokens) alongside a wall-clock duration from the Bash wrapper's own timer that is orders of magnitude larger than the JSON's `duration_ms` field — the cumulative dollar cost still matches real spend, so the mismatch is self-evident on inspection.
|
|
794
794
|
|
|
795
795
|
Aggregation rule: sum `.total_cost_usd` into the session total and trust it; sum `.usage.*` into the session totals for cache-reuse ratio reasoning but label them best-effort in the Session Cost table. This asymmetry is correct-by-CLI-contract (cost is a session cumulative; usage is a per-response envelope); the orchestrator documents the asymmetry so adopters do not silently under-count tokens. First observed AFK-iter-7 iter 5 (2026-04-21): 1071s wall-clock / 60+ tool-use subprocess returned `duration_ms: 8546, num_turns: 1, usage.* ≈ 137K tokens, total_cost_usd: 6.08` — cost cumulative and correct, tokens reflecting only the final ack turn.
|
|
796
796
|
|
|
797
|
-
**Exit-code semantics — ordered check (
|
|
797
|
+
**Exit-code semantics — ordered check (the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem amendment to the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem carve-out).** `claude -p` exits non-zero when the subprocess fails hard — subprocess crash, auth failure, unresolvable permission denial, API/quota exhaustion. Orthogonally, the `--output-format json` envelope carries an `is_error` field that fires `true` on transient API failures (529 Overloaded / 429 rate-limit / 401 auth-expired) where the subprocess exits 0 with `total_cost_usd: 0` — the API call never landed; no work was done; no `ITERATION_SUMMARY` was emitted. Before the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem, the prose presented the exit-code rule first and the `is_error` carve-out as "orthogonal", which let an implementer silently route exit 0 + `is_error: true` to the `ITERATION_SUMMARY` parse path and miscount the failure as success. The orchestrator MUST instead read both fields in this explicit order, BEFORE parsing `.result`:
|
|
798
798
|
|
|
799
799
|
1. **Read the exit code.** Non-zero → halt the loop; report the exit code, stderr, and any partial `.result` in the final summary. Do NOT spawn the next iteration. The user returns to a stopped loop with a clear failure reason (e.g. "quota exhausted — resume when quota resets"). Exit-code check fires FIRST in the ordered sequence — non-zero exit takes precedence over the `is_error` branch below.
|
|
800
|
-
2. **Parse `is_error` from the JSON stdout BEFORE attempting to parse `ITERATION_SUMMARY`.** When `is_error: true`, route to the SALVAGE-vs-HALT decision contract below (the existing
|
|
800
|
+
2. **Parse `is_error` from the JSON stdout BEFORE attempting to parse `ITERATION_SUMMARY`.** When `is_error: true`, route to the SALVAGE-vs-HALT decision contract below (the existing the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem carve-out, extended by the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem with the transient-API-error HALT advisory). The check MUST happen before the Exit-0 → `ITERATION_SUMMARY` parse path — the load-bearing the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem invariant is that `is_error: true` never silently falls through to the parse path.
|
|
801
801
|
3. **Exit 0 AND `is_error: false`** → parse `ITERATION_SUMMARY` from `.result` field; proceed to Step 6.
|
|
802
802
|
|
|
803
|
-
**`is_error: true` class taxonomy (
|
|
803
|
+
**`is_error: true` class taxonomy (the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem SALVAGE branch + the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem HALT branch).** Two sub-classes of `is_error: true` route differently inside the ordered check above. Deterministic SALVAGE-vs-HALT decision contract:
|
|
804
804
|
|
|
805
|
-
- **SALVAGE branch (
|
|
806
|
-
- **HALT branch (
|
|
805
|
+
- **SALVAGE branch (the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem — stream-timeout class).** **IF** `is_error: true` AND staged files exist in the working tree (`git diff --cached --name-only` non-empty) AND any iter-authored bats fixtures pass → the orchestrator MAY apply the documented **4-step salvage path**: (1) run the iter's bats as a structural sanity check; (2) inspect the changeset + diffs for quality; (3) commit the staged work from the orchestrator main turn with explicit iter-attribution in the message (e.g. "iter hit API stream timeout before commit — committed staged work from orchestrator main turn"); (4) **the commit gate fires fresh** on the salvage commit, so architect / JTBD / risk-scorer validate the work cleanly on the orchestrator's own SESSION_ID (never reusing the dead subprocess's gate markers, per the "Gate Marker Lifecycle: TTL + Drift, Not Stop-Hook Reset" architecture rule line 89). The salvage commit IS the iteration's one commit per the "Governance Skills Commit Their Own Completed Work" architecture rule (amend-folding is inapplicable — no iter commit exists to amend). Production shape: `API Error: Stream idle timeout - partial response received` in `.result` after staging coherent work but before `git commit` — staged files survive; JSON metadata preserved (unlike the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem stuck-before-emit class).
|
|
806
|
+
- **HALT branch (the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem — transient-API-error class).** **ELSE IF** `is_error: true` AND nothing staged (`git diff --cached --name-only` empty) → halt the loop with a class-appropriate advisory line in the final summary. The transient-API-error class fires when the API call never landed; `total_cost_usd: 0`; no work was done. Map `.result` substrings to the advisory:
|
|
807
807
|
- `529` / `Overloaded` → `"API overloaded; retry when service recovers"`
|
|
808
808
|
- `429` / `rate limit` → `"API rate-limited; retry when limit window resets"`
|
|
809
809
|
- `401` / `Authentication` / `auth expired` → `"API auth expired; refresh credentials before resuming"`
|
|
810
810
|
- any other `is_error: true` shape → `"transient API error; inspect .result and resume manually"`
|
|
811
811
|
|
|
812
|
-
Do NOT spawn the next iteration; the loop has no recoverable state to advance from. Retry policy for the transient classes (e.g. exponential backoff on 529 Overloaded, max-N attempts) is deferred to a Phase 2 amendment per
|
|
812
|
+
Do NOT spawn the next iteration; the loop has no recoverable state to advance from. Retry policy for the transient classes (e.g. exponential backoff on 529 Overloaded, max-N attempts) is deferred to a Phase 2 amendment per the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem's Investigation Tasks — Phase 1 is HALT-with-advisory only.
|
|
813
813
|
- **ELSE** (staged work incoherent / bats fail) → halt per the SALVAGE branch's fall-through contract.
|
|
814
814
|
|
|
815
|
-
The decision is deterministic and non-interactive — no `AskUserQuestion` (Rule 6, mirroring the
|
|
815
|
+
The decision is deterministic and non-interactive — no `AskUserQuestion` (Rule 6, mirroring the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem SIGTERM precedent at line 154 of the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule). **Distinct classes** within the `is_error: true` taxonomy: the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem SALVAGE (stream-timeout — staged work survives) vs the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem HALT (transient API error — nothing staged). **Distinct from** sibling subprocess-failure classes: the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem (SIGTERM idle-timeout — `is_error: false` clean exit-flush; subprocess HAD committed before going idle), the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem (SIGTERM stuck-before-emit — exit 143 + 0-byte JSON, metadata lost), and the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem (bash-polling antipattern — the deadlock mechanism behind the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem). Here the iter exits on its own with `is_error: true`; no SIGTERM involved; metadata survives in the JSON envelope. Full contract: the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule § "is_error:true stream-timeout salvage (the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem amendment)" + § the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem transient-API-error HALT extension. Behavioural fixtures: `test/work-problems-step-5-stream-timeout-salvage.bats` (SALVAGE branch — the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem), `test/work-problems-step-5-is-error-transient-halt.bats` (HALT branch — the "work-problems Step 5 exit-code rule does not handle is_error:true transient API failures (529 Overloaded)" problem).
|
|
816
816
|
|
|
817
817
|
**Quota as the natural stop.** The AFK loop runs until quota is exhausted or a stop-condition from Step 2 fires. There is no per-iteration dollar cap; running iterations until quota is actually exhausted maximises backlog progress per quota cycle. Quota-exhaust on a `claude -p` invocation surfaces as a non-zero exit and the orchestrator halts cleanly per the rule above.
|
|
818
818
|
|
|
@@ -826,7 +826,7 @@ The manage-problem skill (running inside the iteration subprocess) will:
|
|
|
826
826
|
- Select and work the highest-WSJF problem.
|
|
827
827
|
- Use its built-in non-interactive fallbacks (auto-split multi-concern problems, auto-commit when risk is within appetite).
|
|
828
828
|
- Delegate architect / JTBD / risk-scorer reviews via the Agent tool (available in the subprocess's surface) at the depth defined in each review skill's SKILL.md.
|
|
829
|
-
- Commit completed work per
|
|
829
|
+
- Commit completed work per the "Governance Skills Commit Their Own Completed Work" architecture rule (the iteration subprocess's commit inside its own session — the orchestrator does NOT commit from its main turn, EXCEPT the one bounded `is_error: true` stream-timeout salvage carve-out per the Step 5 exit-code semantics above + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule the "iter subprocess API stream timeout class — orchestrator salvage path for stuck-before-commit needs documentation" problem amendment, where the orchestrator main turn commits an iter's staged-but-uncommitted work after a fresh commit-gate validation).
|
|
830
830
|
|
|
831
831
|
### Step 6: Report progress
|
|
832
832
|
|
|
@@ -836,123 +836,123 @@ After each iteration, report:
|
|
|
836
836
|
- The outcome (success, partially progressed, skipped, scope expanded)
|
|
837
837
|
- How many problems remain in the backlog
|
|
838
838
|
- The iteration's cost metadata — format: `($<cost>, <duration_s>s, <total_tokens_K>K tokens)`. Cost comes from the `.total_cost_usd` field extracted in Step 5; duration from `.duration_ms`; total tokens is the sum of `.usage.input_tokens + .usage.output_tokens + .usage.cache_creation_input_tokens + .usage.cache_read_input_tokens`.
|
|
839
|
-
- Risk-register scaffold line when Step 6.4 drained ≥1 entry — format: `Risk register: <N> entries scaffolded (pending review)` per
|
|
839
|
+
- Risk-register scaffold line when Step 6.4 drained ≥1 entry — format: `Risk register: <N> entries scaffolded (pending review)` per the ": Progress the Backlog While I'm Away" user outcome outcome 4 (auditability of AI-assisted work). Omit the line when the drain was a no-op.
|
|
840
840
|
|
|
841
841
|
Format as a brief status line, not a wall of text. The user will read these when they return.
|
|
842
842
|
|
|
843
843
|
**Example:**
|
|
844
844
|
```
|
|
845
|
-
[Iteration 1] Worked
|
|
846
|
-
[Iteration 2] Worked
|
|
847
|
-
[Iteration 3] Skipped
|
|
845
|
+
[Iteration 1] Worked the "Problem 029: Edit gate overhead disproportionate for governance documentation changes" problem (Edit gate overhead for governance docs) — implemented fix, closed. 8 problems remain. ($0.32, 23s, 171K tokens)
|
|
846
|
+
[Iteration 2] Worked the "Problem 021: Governance-skill decision prompts must be structured (AskUserQuestion + plan mode), not prose — silent below appetite" problem (Governance skill structured prompts) — investigated root cause, transitioned to known-error. 7 problems remain. Risk register: 1 entry scaffolded (pending review). ($0.85, 47s, 432K tokens)
|
|
847
|
+
[Iteration 3] Skipped the "Problem 016: `manage-problem` skill does not flag or split multi-concern tickets" problem (Multi-concern ticket splitting) — fix released, awaiting user verification. Worked the "Problem 024: Risk-scorer WIP mode should flag uncommitted completed work and encourage commits" problem (Risk scorer WIP flag) — implemented fix, closed. 6 problems remain. ($1.12, 62s, 541K tokens)
|
|
848
848
|
```
|
|
849
849
|
|
|
850
|
-
### Step 6.4: Drain risk-register queue (per
|
|
850
|
+
### Step 6.4: Drain risk-register queue (per the "Risk Register Back-Channel Write Contract — agent emits, hook queues, calling skill drains" architecture rule Phase 2b)
|
|
851
851
|
|
|
852
|
-
After the iteration's commit lands and before the release-cadence check, drain any `RISK_REGISTER_HINT` entries that the iteration's pipeline runs enqueued to `.afk-run-state/risk-register-queue.jsonl`. The hook (Phase 2a) writes the queue silently; this step (Phase 2b) materialises queued hints into `docs/risks/R<NNN>-<slug>.active.md` register entries. Per-iter cadence keeps the queue bounded and attaches the resulting `docs(risks): scaffold ...` commit to the iter that produced the hint (preserves
|
|
852
|
+
After the iteration's commit lands and before the release-cadence check, drain any `RISK_REGISTER_HINT` entries that the iteration's pipeline runs enqueued to `.afk-run-state/risk-register-queue.jsonl`. The hook (Phase 2a) writes the queue silently; this step (Phase 2b) materialises queued hints into `docs/risks/R<NNN>-<slug>.active.md` register entries. Per-iter cadence keeps the queue bounded and attaches the resulting `docs(risks): scaffold ...` commit to the iter that produced the hint (preserves the "Governance Skills Commit Their Own Completed Work" architecture rule single-ticket-unit-of-work grain).
|
|
853
853
|
|
|
854
854
|
**Mechanism — invoke the shared drain script:**
|
|
855
855
|
|
|
856
|
-
1. Run the shim: `wr-risk-scorer-drain-register-queue` (resolves to `packages/risk-scorer/scripts/drain-register-queue.sh` per
|
|
856
|
+
1. Run the shim: `wr-risk-scorer-drain-register-queue` (resolves to `packages/risk-scorer/scripts/drain-register-queue.sh` per the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule naming grammar). The script:
|
|
857
857
|
- Skips silently if `.afk-run-state/risk-register-queue.jsonl` is empty or absent (no-op exit 0).
|
|
858
858
|
- Skips silently if `docs/risks/` has not been scaffolded (Phase 1 / install-updates Step 6.5 has not fired in this project yet — preserves the queue for the next drain).
|
|
859
859
|
- Dedupes by `risk_slug`: N hints for the same slug → one register file with N Evidence Log entries (per the user direction "for each risk in `.risk-reports` there should be something in the register").
|
|
860
|
-
- Mints new R<NNN> IDs via local-max + origin-max +1 (
|
|
861
|
-
- Writes each new entry from a fixed shape with `Status: Active (auto-scaffolded — pending review)`,
|
|
862
|
-
- Updates `docs/risks/README.md` Register table with one row per new risk (em-dash for stub scoring per
|
|
860
|
+
- Mints new R<NNN> IDs via local-max + origin-max +1 (the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule dual-source ID for ticket-creator surfaces).
|
|
861
|
+
- Writes each new entry from a fixed shape with `Status: Active (auto-scaffolded — pending review)`, the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule sentinel `not estimated — no prior data` for ungrounded scoring fields, and a `Curation: pending review` field for downstream review tooling.
|
|
862
|
+
- Updates `docs/risks/README.md` Register table with one row per new risk (em-dash for stub scoring per the "Risk Register Back-Channel Write Contract — agent emits, hook queues, calling skill drains" architecture rule §pending-review).
|
|
863
863
|
- Stages all writes via `git add docs/risks` and truncates the queue file on success.
|
|
864
864
|
|
|
865
865
|
2. Parse stdout key=value output:
|
|
866
866
|
- `entries_drained=N` — total queue lines processed.
|
|
867
867
|
- `new_risks_created=N` — new register files written.
|
|
868
868
|
- `evidence_appended=N` — slug-matched existing files updated.
|
|
869
|
-
- `next_action=commit-staged|none` — when `commit-staged`, run a dedicated `docs(risks): scaffold` commit through the standard
|
|
869
|
+
- `next_action=commit-staged|none` — when `commit-staged`, run a dedicated `docs(risks): scaffold` commit through the standard the "Governance Skills Commit Their Own Completed Work" architecture rule commit-gate flow.
|
|
870
870
|
|
|
871
871
|
3. **Commit (when `next_action=commit-staged`)**: stage is already done; commit message:
|
|
872
872
|
```
|
|
873
873
|
docs(risks): scaffold R<NNN>... (<N> entries from queue)
|
|
874
874
|
|
|
875
|
-
Drained .afk-run-state/risk-register-queue.jsonl per
|
|
875
|
+
Drained .afk-run-state/risk-register-queue.jsonl per the "Risk Register Back-Channel Write Contract — agent emits, hook queues, calling skill drains" architecture rule Phase 2b.
|
|
876
876
|
<new_risks_created> new register entries; <evidence_appended> existing
|
|
877
877
|
entries gained Evidence Log lines. All entries marked Active
|
|
878
|
-
(auto-scaffolded — pending review) with
|
|
878
|
+
(auto-scaffolded — pending review) with the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule sentinels for
|
|
879
879
|
ungrounded scoring fields.
|
|
880
880
|
```
|
|
881
|
-
The commit goes through architect / JTBD / risk-scorer review per
|
|
881
|
+
The commit goes through architect / JTBD / risk-scorer review per the "Governance Skills Commit Their Own Completed Work" architecture rule. Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5, the drain action itself is policy-authorised silent proceed — no `AskUserQuestion` round-trip needed; the shape is mechanical and the "Risk Register Back-Channel Write Contract — agent emits, hook queues, calling skill drains" architecture rule supplies the authority.
|
|
882
882
|
|
|
883
|
-
4. Pass the `new_risks_created + evidence_appended` count into Step 6's progress report so the AFK summary surfaces register population per
|
|
883
|
+
4. Pass the `new_risks_created + evidence_appended` count into Step 6's progress report so the AFK summary surfaces register population per the ": Progress the Backlog While I'm Away" user outcome outcome 4. When `entries_drained=0`, omit the register line entirely.
|
|
884
884
|
|
|
885
885
|
**Idempotency**: safe to invoke when queue is empty / missing. The script's no-op path is the steady state in projects without active above-appetite events.
|
|
886
886
|
|
|
887
887
|
**Failure handling**: if the drain script exits non-zero (template missing, write error, git failure), do NOT halt the loop — log the failure in the iter report and proceed to Step 6.5. The queue retains entries for next drain; Phase 3 backfill recovers any persistent loss.
|
|
888
888
|
|
|
889
|
-
### Step 6.5: Release-cadence check (per
|
|
889
|
+
### Step 6.5: Release-cadence check (per the "Inter-iteration release cadence for AFK loops" architecture rule, above-appetite branch per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule)
|
|
890
890
|
|
|
891
|
-
After the iteration's commit lands but before starting the next iteration, check whether there is releasable material to drain. This prevents silent accumulation of unreleased changesets across AFK iterations (
|
|
891
|
+
After the iteration's commit lands but before starting the next iteration, check whether there is releasable material to drain. This prevents silent accumulation of unreleased changesets across AFK iterations (the "Problem 041: work-problems does not enforce release cadence" problem, the "work-problems Step 6.5 "≤3 within appetite — no drain" clause defers low-risk releases, encoding accumulation" problem) — accumulation costs audit fidelity and increases future drain risk with no governance benefit when residual stays within appetite. **The orchestrator MUST NOT release above appetite under any circumstance** — above-appetite states route to the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule auto-apply loop or halt.
|
|
892
892
|
|
|
893
893
|
**Mechanism — delegate, do not re-implement scoring:**
|
|
894
894
|
|
|
895
|
-
1. Invoke the risk scorer to score cumulative pipeline state. Two paths are valid (per
|
|
895
|
+
1. Invoke the risk scorer to score cumulative pipeline state. Two paths are valid (per the "On-Demand Assessment Skills for Governance Plugins" architecture rule):
|
|
896
896
|
- **Primary**: delegate to subagent type `wr-risk-scorer:pipeline` via the Agent tool.
|
|
897
897
|
- **Fallback**: if that subagent type is not available, invoke skill `/wr-risk-scorer:assess-release` via the Skill tool. The skill wraps the same pipeline subagent.
|
|
898
898
|
2. Read the returned `RISK_SCORES: commit=X push=Y release=Z` line and the `RISK_REMEDIATIONS:` block (if present).
|
|
899
|
-
3. **Classify the residual + queue state (
|
|
899
|
+
3. **Classify the residual + queue state (the "work-problems Step 6.5 "≤3 within appetite — no drain" clause defers low-risk releases, encoding accumulation" problem)**:
|
|
900
900
|
- **Above appetite (≥ 5/25)** — route to the **Above-appetite branch** below. Do NOT drain. Do NOT proceed to Step 6.75 until either (a) the auto-apply loop re-converges within appetite and drain succeeds, or (b) Rule 5 halt fires.
|
|
901
|
-
- **Within appetite (≤ 4/25) AND there is releasable material** (any unpushed commits on `HEAD..origin/<base>` OR any entries in `.changeset/`) — drain the queue per the Drain action below, then proceed to Step 6.75. The release-action threshold is "is there something to release?", NOT "has accumulated risk reached the safety band?" Per user direction 2026-05-17 (
|
|
901
|
+
- **Within appetite (≤ 4/25) AND there is releasable material** (any unpushed commits on `HEAD..origin/<base>` OR any entries in `.changeset/`) — drain the queue per the Drain action below, then proceed to Step 6.75. The release-action threshold is "is there something to release?", NOT "has accumulated risk reached the safety band?" Per user direction 2026-05-17 (the "work-problems Step 6.5 "≤3 within appetite — no drain" clause defers low-risk releases, encoding accumulation" problem Description): *"If it's low risk, you should release."* Low cost to release + low residual risk = release now; never accumulate.
|
|
902
902
|
- **Within appetite (≤ 4/25) AND empty queue** (no unpushed commits AND no `.changeset/` entries) — no drain (literally nothing to release). Proceed to Step 6.75. This is the genuine no-op fast-path; the gate is *absence of releasable material*, not residual band.
|
|
903
903
|
|
|
904
|
-
**Drain action (non-interactive, policy-authorised per
|
|
904
|
+
**Drain action (non-interactive, policy-authorised per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6):**
|
|
905
905
|
|
|
906
906
|
1. Run `npm run push:watch` (push + wait for CI to pass).
|
|
907
907
|
2. If `.changeset/` is non-empty after push, run `npm run release:watch` (merge the release PR + wait for npm publish).
|
|
908
908
|
3. Resume the loop only after the release lands on npm.
|
|
909
|
-
4. **Post-release K→V auto-transition (
|
|
910
|
-
5. **Post-release cache refresh (
|
|
909
|
+
4. **Post-release K→V auto-transition (the ".known-error.md → .verifying.md transition not happening consistently at release time" problem)**: if step 2 actually ran AND succeeded (a release shipped to npm), fire the K→V auto-transition callback for `.known-error.md` tickets whose Release-vehicle citation matches a just-shipped changeset. See the **Post-release K→V auto-transition** subsection below for the full contract.
|
|
910
|
+
5. **Post-release cache refresh (the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem)**: if step 2 actually ran AND succeeded (a release shipped to npm), chain `/install-updates` to refresh the plugin cache before the next iter dispatches. Skipped when step 2 was a no-op (empty `.changeset/` after push; no new plugin version exists). See the **Post-release cache refresh** subsection below for the full contract.
|
|
911
911
|
|
|
912
|
-
**Post-release K→V auto-transition (
|
|
912
|
+
**Post-release K→V auto-transition (the ".known-error.md → .verifying.md transition not happening consistently at release time" problem) — fires only after within-appetite Drain action step 2 (release:watch) succeeded:**
|
|
913
913
|
|
|
914
|
-
|
|
914
|
+
the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule prescribes that Known Error tickets transition to Verification Pending on release, but until the ".known-error.md → .verifying.md transition not happening consistently at release time" problem there was no auto-fire surface to back-fill the transition once a fix ships. Iter subprocesses MUST NOT release (the orchestrator owns Step 6.5 per the iter dispatch constraints), so a fix that lands in iter N stays in `.known-error.md` until the orchestrator drains release in Step 6.5 — and prior to this callback, the K→V transition was silently deferred to "the next session" citing a misapplied the "`release-watch.sh` race condition — `gh pr list` queries before changesets/action GitHub workflow has created the release PR" problem amendment. The 2026-06-08 the "manage-problem has no cadence for checking upstream-bound tickets" problem empirical witness — `## Fix Released` populated with no K→V transition — confirmed the gap.
|
|
915
915
|
|
|
916
916
|
**Mechanism:**
|
|
917
917
|
|
|
918
|
-
1. Invoke `wr-itil-enumerate-postrelease-kv-candidates` (
|
|
918
|
+
1. Invoke `wr-itil-enumerate-postrelease-kv-candidates` (the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule PATH shim resolving to `packages/itil/scripts/run-enumerate-postrelease-kv-candidates.sh` / `packages/itil/lib/enumerate-postrelease-kv-candidates.sh`). The helper walks `docs/problems/known-error/*.md`, invokes `wr-itil-derive-release-vehicle <NNN>` per ticket, and emits one `KV_CANDIDATE: P<NNN> | <changeset>` line per ticket whose changeset has been shipped (derive exit 0). Tickets with no `**Release vehicle**: .changeset/<name>.md` reference (derive exit 2 — legacy pre-the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem) and tickets whose changeset is still in the working tree (derive exit 3 — unreleased) are skipped silently. Final line: `KV_CANDIDATES_SUMMARY: total=<N>`.
|
|
919
919
|
2. Parse `KV_CANDIDATE:` lines from stdout.
|
|
920
|
-
3. For each candidate `P<NNN>`, dispatch `/wr-itil:transition-problem <NNN> verifying` via the Skill tool. The dispatched transition-problem skill is the authoritative executor for K→V per
|
|
920
|
+
3. For each candidate `P<NNN>`, dispatch `/wr-itil:transition-problem <NNN> verifying` via the Skill tool. The dispatched transition-problem skill is the authoritative executor for K→V per the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended "Split-skill execution ownership" (the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem) — orchestrator dispatch is the documented forwarder pattern, NOT a round-trip. The dispatched skill rides its OWN the "Governance Skills Commit Their Own Completed Work" architecture rule commit through architect / JTBD / risk-scorer gates per its existing Step 8 contract (rename + Status edit + `## Fix Released` write + README refresh + commit). The orchestrator does NOT re-implement the transition mechanics; it dispatches and reads the outcome.
|
|
921
921
|
4. After all candidates dispatched: emit one per-ticket transition outcome line to the iter summary in the form `K→V: P<NNN> | commit=<sha> | release=<vehicle>` (read from the dispatched transition-problem's `RELEASE_VEHICLE` block or Report-the-outcome stdout per Step 9 of transition-problem).
|
|
922
922
|
5. Push the resulting K→V commits via `git push` (the release itself has already shipped — these are post-release audit-trail commits and do NOT require a second release:watch round-trip).
|
|
923
923
|
|
|
924
924
|
**Conditional on actual release**: only fires when `release:watch` actually published (step 2 of the Drain action above ran AND returned success). Skipped when `push:watch` ran alone (empty `.changeset/`; no new plugin version). Without this guard, the enumerator would scan `.known-error/` on every iter with no shipped changeset to match — wasted reads.
|
|
925
925
|
|
|
926
|
-
**Non-blocking on individual transition failure**: if a dispatched `/wr-itil:transition-problem` fails (pre-flight reject, gate rejection,
|
|
926
|
+
**Non-blocking on individual transition failure**: if a dispatched `/wr-itil:transition-problem` fails (pre-flight reject, gate rejection, the "Problem 057: `git mv` + Edit + `git add` staging-ordering trap drops content edits from the commit" problem staging trap, derive helper transient error), the orchestrator logs the failure for that ticket and continues to the next candidate. A single transition failure MUST NOT halt the loop or block siblings in the same cohort. Persistent failures across multiple iters surface as accumulated `outstanding_questions` entries per the standard Step 2.5b discipline.
|
|
927
927
|
|
|
928
|
-
**Policy authorisation (
|
|
928
|
+
**Policy authorisation (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5)**: rides the same Rule 5 silent-proceed that already covers `push:watch` / `release:watch` / `/install-updates` in the drain — the K→V auto-transition is mechanically downstream of release and shares its authorisation. The derive-helper-citation match against the just-shipped changeset is deterministic (filename equality), not a judgment call — squarely in the safe-default tier per the ": Progress the Backlog While I'm Away" user outcome "Decisions that would normally require my input are resolved using safe defaults".
|
|
929
929
|
|
|
930
|
-
**Mid-loop ask discipline (
|
|
930
|
+
**Mid-loop ask discipline (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem) preserved**: the dispatched transition-problem skill is wired to skip `AskUserQuestion` when invoked under AFK orchestrator context per its own the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 fail-safe (transition-problem SKILL.md Step 8 risk-above-appetite branch). The orchestrator MUST NOT introduce any `AskUserQuestion` call at the callback site — the per-candidate routing is framework-resolved per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule, and the callback fires in a mechanical-stage transition between drain step 2 and step 5 (cache refresh).
|
|
931
931
|
|
|
932
|
-
**V→C remains the maintainer's surface (persona constraint per
|
|
932
|
+
**V→C remains the maintainer's surface (persona constraint per the ": Progress the Backlog While I'm Away" user outcome)**: this callback fires ONLY for K→V (`known-error → verifying` — "fix released, awaiting verification"). It explicitly does NOT auto-fire V→C — the maintainer's judgment-reserved "fix actually works" closure remains untouched and continues to require their return per the existing transition-problem Step 4 `Verification Pending → Closed` precondition ("the user has explicitly confirmed the fix works in production").
|
|
933
933
|
|
|
934
934
|
**Composition with the Above-appetite branch (below)**: the K→V callback is anchored to the within-appetite Drain action step 4 — it does NOT fire after the above-appetite Rule 5 halt (no release shipped → nothing to match) and it does NOT fire mid-loop in the above-appetite auto-apply loop. When the auto-apply loop converges and re-enters the within-appetite Drain action, the K→V callback fires there per step 4.
|
|
935
935
|
|
|
936
|
-
Per
|
|
936
|
+
Per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule (Verifying lifecycle) + the "Inter-iteration release cadence for AFK loops" architecture rule (release-cadence host) + the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem (transition-problem authoritative executor) + the "Governance Skills Commit Their Own Completed Work" architecture rule (per-transition commit grain) + the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 (policy-authorised silent-proceed) + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule (framework-resolution boundary) + the ".known-error.md → .verifying.md transition not happening consistently at release time" problem (this ticket) + the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem (sibling callback) + the "Codify `derive-release-vehicle.sh` helper for K→V release-cycle citation" problem (derive-release-vehicle composed helper) + the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem (Release vehicle seed reference — input signal).
|
|
937
937
|
|
|
938
|
-
**Post-release cache refresh (
|
|
938
|
+
**Post-release cache refresh (the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem) — fires only after within-appetite Drain action step 5 (above):**
|
|
939
939
|
|
|
940
|
-
After a successful release-cadence drain has shipped a new plugin version to npm, the orchestrator chains `/install-updates` to refresh the plugin cache before the next iter dispatches. Empirical evidence in `docs/briefing/afk-subprocess.md` ("Just-shipped gate-class hooks DON'T protect the immediate-next iter" entry) confirms iter subprocesses re-resolve plugin cache on spawn — so a just-shipped gate-class hook is inactive in the next iter unless the cache is refreshed first. The orchestrator IS the "restart" boundary for the next iter subprocess (each subprocess is a fresh `claude -p` per
|
|
940
|
+
After a successful release-cadence drain has shipped a new plugin version to npm, the orchestrator chains `/install-updates` to refresh the plugin cache before the next iter dispatches. Empirical evidence in `docs/briefing/afk-subprocess.md` ("Just-shipped gate-class hooks DON'T protect the immediate-next iter" entry) confirms iter subprocesses re-resolve plugin cache on spawn — so a just-shipped gate-class hook is inactive in the next iter unless the cache is refreshed first. The orchestrator IS the "restart" boundary for the next iter subprocess (each subprocess is a fresh `claude -p` per the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule + `afk-subprocess-mechanics.md`); the cache refresh between release:watch and next-iter dispatch is the load-bearing step.
|
|
941
941
|
|
|
942
942
|
- **Conditional on actual release**: only fires when `release:watch` actually published (step 2 of the Drain action above ran AND returned success). Skipped when `push:watch` ran alone (empty `.changeset/`; no new plugin version). Without this guard, every iter burns wall-clock + npm-API noise on a no-op cache refresh.
|
|
943
|
-
- **Non-blocking on /install-updates failure**: if `/install-updates` fails (transient marketplace fetch error,
|
|
944
|
-
- **Policy authorisation (
|
|
945
|
-
- **Mid-loop ask discipline (
|
|
943
|
+
- **Non-blocking on /install-updates failure**: if `/install-updates` fails (transient marketplace fetch error, the "`/install-updates` Step 7 uses `claude plugin install` which silently no-ops when a plugin is already installed — updates never actually land" problem-class quirk re-emergence, cache-miss + Non-interactive fallback dry-run), the orchestrator logs the failure and continues the loop. Degrades to current behaviour — cache stays stale; next iter may recur the just-shipped issue, equivalent to pre-amendment behaviour. The cache-refresh chain MUST NOT halt the loop on `/install-updates` failure under any circumstance.
|
|
944
|
+
- **Policy authorisation (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5)**: rides the same Rule 5 silent-proceed that already covers `push:watch` / `release:watch` in the drain — the post-release cache refresh is mechanically downstream of release and shares its authorisation. Composes with the "`/install-updates` Step 7 uses `claude plugin install` which silently no-ops when a plugin is already installed — updates never actually land" problem's claude-plugin-install no-op-when-already-installed factor (the chained `/install-updates` handles the uninstall+install dance per the "`/install-updates` Step 7 uses `claude plugin install` which silently no-ops when a plugin is already installed — updates never actually land" problem).
|
|
945
|
+
- **Mid-loop ask discipline (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem) preserved**: if `/install-updates` Step 5b/5c consent gate fires (cache miss / scope delta / `INSTALL_UPDATES_RECONFIRM=1`), the orchestrator main turn treats this AS the **Non-interactive fallback** documented in `scripts/repo-local-skills/install-updates/SKILL.md` "Non-interactive fallback" subsection — log the dry-run output, do not interrupt the loop. The orchestrator's `.claude/.install-updates-consent` is normally present (install-updates Step 5a cache hit) so the gate fires silently. **the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary** authorises this AskUserQuestion-available-but-forbidden routing: invocation between iters is a mechanical-stage transition the framework has resolved; surfacing it to the user would dilute the Step 2.5b accumulated-question discipline.
|
|
946
946
|
|
|
947
947
|
**Composition with the Above-appetite branch (below)**: the cache refresh is anchored to the within-appetite Drain action step 5 — it does NOT fire after the above-appetite Rule 5 halt (no release shipped → nothing to refresh) and it does NOT fire mid-loop in the above-appetite auto-apply loop. When the auto-apply loop converges and re-enters the within-appetite Drain action, the cache refresh fires there per step 5. The chain's site is the Drain action only.
|
|
948
948
|
|
|
949
|
-
**Failure handling (
|
|
949
|
+
**Failure handling (the "`/wr-itil:work-problems` Step 6.5 halt-on-CI-failure direction should be fix-and-continue when failure is mechanically fixable (-class stale assertions)" problem)**: When `push:watch` or `release:watch` reports a CI failure or publish failure, the orchestrator follows a diagnose-then-classify routing — fix-and-continue for the documented mechanically-fixable allow-list, halt for everything else. The previous uniform halt rule converted mechanically-fixable failures (1-line stale-grep-string updates, transient flakes) into ~45min queue stalls, regressing the ": Progress the Backlog While I'm Away" user outcome "Progress the Backlog While I'm Away" without any governance benefit.
|
|
950
950
|
|
|
951
|
-
**Diagnostic preamble (
|
|
951
|
+
**Diagnostic preamble (the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding)**: orchestrator MUST first fetch the failed CI log via `gh run view <run-id> --log-failed` (or `gh run view --log-failed` against the most recent failure). Read the failure output and classify into ONE of the buckets below. Cite the failed test output verbatim in the fix-and-continue commit message or halt summary so future readers can audit the classification.
|
|
952
952
|
|
|
953
|
-
**Fixable-in-iter allow-list (closed)**: the following classes are policy-authorised silent fix-and-continue per
|
|
953
|
+
**Fixable-in-iter allow-list (closed)**: the following classes are policy-authorised silent fix-and-continue per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5. The list is **closed** — adding a new class is itself a deviation-candidate per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's framework-resolution boundary (surface to user via Step 2.5b's AskUserQuestion-default branch; do NOT auto-extend at agent discretion).
|
|
954
954
|
|
|
955
|
-
- **
|
|
955
|
+
- **the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem-class stale-grep-string** — structural test runs `grep -F '<literal>'` (or `grep -nE '<pattern>'`) against a SKILL.md / ADR / source file; non-zero return because source was edited and the test's grep string was not. Fix: update the grep string to current source phrasing. Composes with the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem (structural-tests-are-wasteful root cause); fix-and-continue is the stop-gap, the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem's full retrofit is the structural elimination.
|
|
956
956
|
- **Hook stub mismatch** — test's mock-stdin field doesn't match current hook expectation (e.g. renamed JSON key, renamed event type). Fix: update the stub.
|
|
957
957
|
- **Test ID drift** — assertion message grep doesn't match a recently-renamed function or symbol. Fix: sed in the test.
|
|
958
958
|
- **Environmental flake** — CI runner intermittent issue (npm registry timeout, GitHub API rate limit, transient infra). Fix: re-trigger the workflow.
|
|
@@ -962,7 +962,7 @@ After a successful release-cadence drain has shipped a new plugin version to npm
|
|
|
962
962
|
**Fix-and-continue branch**: for a fixable class:
|
|
963
963
|
|
|
964
964
|
1. Apply the fix (typically a single `Edit` change).
|
|
965
|
-
2. Commit the fix through the **standard
|
|
965
|
+
2. Commit the fix through the **standard the "Governance Skills Commit Their Own Completed Work" architecture rule commit gate flow** — architect / JTBD / risk-scorer review per retry. A gate rejection routes to the halt branch (no retry budget restoration). Each fix-and-continue commit is its own discrete unit of work and rides its own commit through gates per the "Governance Skills Commit Their Own Completed Work" architecture rule + the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 3 precedent (retries each ride their own commit).
|
|
966
966
|
3. `git push` and re-run `npm run push:watch` (or `release:watch` if the failure was on the release-PR side) to wait for CI re-trigger.
|
|
967
967
|
4. If CI passes, resume the loop (Step 6.75).
|
|
968
968
|
5. If CI fails again, increment the per-iteration retry counter and return to step 1.
|
|
@@ -971,26 +971,26 @@ After a successful release-cadence drain has shipped a new plugin version to npm
|
|
|
971
971
|
|
|
972
972
|
**Halt branch (genuinely unrecoverable)**: halt the loop and report the failure in the AFK summary. Do not retry non-interactively. Genuinely-unrecoverable classes include: auth failure (npm token, GitHub credentials), npm publish rejection (version conflict, package access denied), semantic test failure requiring user judgment (not literal-string drift), repeated transient failures (3+ retries, per the cap above), and any failure outside the fixable-in-iter allow-list.
|
|
973
973
|
|
|
974
|
-
**Step 2.5b cross-reference (
|
|
974
|
+
**Step 2.5b cross-reference (the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)**: before emitting the final AFK summary for a Failure handling / CI failure / release:watch halt, run Step 2.5b's surfacing routine. The routine is gated on ≥1 accumulated user-answerable skip; this halt path empirically frequently has accumulated skips from prior iters (the original the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem surface), so the gate is normally satisfied and Step 2.5b's AskUserQuestion-default branch fires (`halt-paths-must-route-design-questions-through-Step-2.5b`). The CI-failure cause itself remains a halt with bug-signal — Step 2.5b surfaces *prior-iter accumulated user-answerable skips only*; it does NOT ask the user how to remediate the CI failure (that requires the user to inspect the failing CI run on return).
|
|
975
975
|
|
|
976
|
-
`push:watch` and `release:watch` are policy-authorised actions when residual risk is within appetite per RISK-POLICY.md, so no `AskUserQuestion` is required for the drain itself (
|
|
976
|
+
`push:watch` and `release:watch` are policy-authorised actions when residual risk is within appetite per RISK-POLICY.md, so no `AskUserQuestion` is required for the drain itself (the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5). The fix-and-continue branch is itself policy-authorised by the closed allow-list above, satisfying the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 without an `AskUserQuestion` round-trip.
|
|
977
977
|
|
|
978
|
-
**Composition notes**: fix-and-continue is the inverse of
|
|
978
|
+
**Composition notes**: fix-and-continue is the inverse of the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem (over-ask in interactive sessions) on the failure-handling surface — both arise from over-defensive uniform routing where a documented class-policy would empower silent action. Composes with the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem (orchestrator main-turn ask discipline — fix-and-continue does NOT introduce mid-iter asks; the closed allow-list resolves the decision per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule). Cross-references: the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem (stop-gap composition — most fixables are the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem-class), the "Decision-delegation contract — agents over-apply Rule 1's interactive default to framework-resolved decisions; codify the framework-resolution boundary + AFK loop's batched-questions-as-deliverable + lazy-AskUserQuestion measurement" problem (decision-delegation contract — the closed allow-list IS the framework-resolved policy).
|
|
979
979
|
|
|
980
|
-
#### Above-appetite branch (per
|
|
980
|
+
#### Above-appetite branch (per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule)
|
|
981
981
|
|
|
982
982
|
**Invariant**: the orchestrator MUST NOT release above appetite. There is no code path in Step 6.5 that releases at residual push/release ≥ 5/25. The orchestrator MUST NOT call `AskUserQuestion` as a shortcut out of the auto-apply loop — the scorer is the decision surface, not the user. The branch terminates in either a within-appetite drain or a Rule 5 halt.
|
|
983
983
|
|
|
984
|
-
**Auto-apply loop (
|
|
984
|
+
**Auto-apply loop (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2):**
|
|
985
985
|
|
|
986
|
-
1. Parse the scorer's `RISK_REMEDIATIONS:` block. Expected shape per
|
|
986
|
+
1. Parse the scorer's `RISK_REMEDIATIONS:` block. Expected shape per the "On-Demand Assessment Skills for Governance Plugins" architecture rule / the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2a (5 columns):
|
|
987
987
|
```
|
|
988
988
|
RISK_REMEDIATIONS:
|
|
989
989
|
- R1 | <description> | <effort S/M/L> | <risk_delta -N> | <files affected>
|
|
990
990
|
- R2 | ...
|
|
991
991
|
```
|
|
992
992
|
2. Read the descriptions. Decide what to do. The agent MAY follow a scorer suggestion, adapt it, or do something else entirely. There is no requirement to rank all suggestions upfront or iterate through them in order. The selected action and the branch report MUST name how actual shipped risk changes (for example: split the change, add a control, disable the risky behaviour, or revert it); generic "apply remediation" wording is not enough.
|
|
993
|
-
3. **Verification Pending carve-out (
|
|
993
|
+
3. **Verification Pending carve-out (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2b)**: if a remediation targets a commit attached to a `.verifying.md` ticket, do NOT auto-revert it. Skip that suggestion and decide on the next one.
|
|
994
994
|
4. Apply the chosen action using standard primitives (git, Edit, Bash). Example actions the agent might take:
|
|
995
995
|
- `revert-commit`: `git revert --no-edit <sha>`. The scorer SHOULD supply the target commit SHA in the `description` column (e.g., "Revert commit 9a1f96c that introduced the risky gate"). Before executing, verify the SHA is NOT attached to a `.verifying.md` ticket (Rule 2b carve-out). After revert, amend the iteration's commit to fold the revert. If `git revert` produces merge conflicts, route to Rule 5 halt with the conflict detail — do not attempt non-interactive conflict resolution.
|
|
996
996
|
- `split-change`: split the iteration into independently releasable, within-appetite commits and re-score each slice.
|
|
@@ -1001,7 +1001,7 @@ After a successful release-cadence drain has shipped a new plugin version to npm
|
|
|
1001
1001
|
- **Re-score still above appetite (≥ 5/25)** — continue working to reduce risk. The agent reads the new remediations and decides what to do next. Loop.
|
|
1002
1002
|
- **No remediations remain** or **the agent has exhausted its own ideas** — Rule 5 halt.
|
|
1003
1003
|
|
|
1004
|
-
**Governance gates per auto-apply (
|
|
1004
|
+
**Governance gates per auto-apply (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 3):** each auto-apply that requires a commit (the amend in step 4 above) goes through the standard the "Governance Skills Commit Their Own Completed Work" architecture rule commit flow — architect review, JTBD review, risk-scorer gate. A gate rejection falls through to Rule 5 halt. The scorer's suggestions do NOT bypass gates.
|
|
1005
1005
|
|
|
1006
1006
|
**Rule 5 halt (exhaustion):** when the auto-apply loop exhausts without convergence, or any gate/operation fails, halt the loop. Do NOT proceed to Step 6.75. Do NOT spawn the next iteration. Emit the iteration summary with:
|
|
1007
1007
|
|
|
@@ -1009,17 +1009,17 @@ After a successful release-cadence drain has shipped a new plugin version to npm
|
|
|
1009
1009
|
- The final `RISK_SCORES:` line
|
|
1010
1010
|
- An "Auto-apply trail" subsection listing each remediation attempted with outcome
|
|
1011
1011
|
- Any Verification Pending ticket IDs implicated per Rule 2b
|
|
1012
|
-
- A one-line scorer-gap note (e.g., "available remediations did not reduce residual risk below 5/25 — extend scorer vocabulary per
|
|
1012
|
+
- A one-line scorer-gap note (e.g., "available remediations did not reduce residual risk below 5/25 — extend scorer vocabulary per the "Scorer `RISK_REMEDIATIONS:` block is free-form prose — agent must parse descriptions to decide what to do" problem")
|
|
1013
1013
|
|
|
1014
|
-
**Step 2.5b cross-reference (
|
|
1014
|
+
**Step 2.5b cross-reference (the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)**: before emitting the Rule 5 halt iteration summary, run Step 2.5b's surfacing routine. The routine is gated on ≥1 accumulated user-answerable skip; Rule 5 halts that fire late in a long AFK loop frequently have accumulated skips from prior iters, so Step 2.5b's AskUserQuestion-default branch typically fires (`halt-paths-must-route-design-questions-through-Step-2.5b`). **Critical guard (architect FLAG)**: Step 2.5b surfaces *prior-iter accumulated user-answerable skips only* — it does NOT ask the user how to remediate the above-appetite state itself; the halt-causing scorer-gap remains a halt-with-bug-signal per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5 invariant ("never release above appetite", scorer is the decision surface, not the user). Surfacing prior-iter skips does not retry the above-appetite remediation, does not bypass the never-release-above-appetite invariant, and does not convert the halt into a non-halt — it just takes the existing prior-iter user-input round-trip with it.
|
|
1015
1015
|
|
|
1016
|
-
Halt is a **bug signal** — the scorer should always have progressively more aggressive remediations available once
|
|
1016
|
+
Halt is a **bug signal** — the scorer should always have progressively more aggressive remediations available once the "Scorer `RISK_REMEDIATIONS:` block is free-form prose — agent must parse descriptions to decide what to do" problem lands.
|
|
1017
1017
|
|
|
1018
|
-
**Audit trail (
|
|
1018
|
+
**Audit trail (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 6):** append one line per auto-apply to the iteration summary's Auto-apply trail subsection, including remediation ID, action class, pre/post scores, action taken, and description citation.
|
|
1019
1019
|
|
|
1020
|
-
### Step 6.75: Inter-iteration verification (
|
|
1020
|
+
### Step 6.75: Inter-iteration verification (the "Problem 036: work-problems orchestrator does not verify commit-landing between iterations" problem)
|
|
1021
1021
|
|
|
1022
|
-
Before spawning the next iteration's subagent, verify the working tree state against the expected outcome of the iteration that just completed. This is defence-in-depth:
|
|
1022
|
+
Before spawning the next iteration's subagent, verify the working tree state against the expected outcome of the iteration that just completed. This is defence-in-depth: the "Problem 035: manage-problem commit gate has no fallback when subagent delegation is unavailable" problem closed the most-likely commit-gate failure path, but a subagent could still fail to commit for reasons the fallback does not cover (a failure inside `/wr-risk-scorer:assess-release`, a git conflict, a malformed commit message). Without this check, silent failures accumulate across iterations and the final summary reports commits that did not land.
|
|
1023
1023
|
|
|
1024
1024
|
**Mechanism:**
|
|
1025
1025
|
|
|
@@ -1030,32 +1030,32 @@ Before spawning the next iteration's subagent, verify the working tree state aga
|
|
|
1030
1030
|
|---|---|---|
|
|
1031
1031
|
| Clean (empty output) | The subagent committed successfully (the default happy path) | Proceed to Step 7 |
|
|
1032
1032
|
| Dirty for a known reason | A deliberate hand-off to the next iteration (e.g. the subagent chose to skip the commit and report "uncommitted state" because risk was above appetite — per the Non-Interactive Decision Making table above). Reason MUST be stated in the iteration report. | Include the dirty state in the next iteration's subagent context and proceed to Step 7 |
|
|
1033
|
-
| Dirty for an unknown reason | Neither of the above — the subagent reported success but the tree is not clean, or the tree is dirty without a documented reason in the iteration report. **
|
|
1033
|
+
| Dirty for an unknown reason | Neither of the above — the subagent reported success but the tree is not clean, or the tree is dirty without a documented reason in the iteration report. **the "work-problems iteration boundary leaves run-retro BRIEFING.md edits uncommitted" problem case (no longer a hand-off)**: dirty `docs/BRIEFING.md` / `docs/briefing/*.md` at iter exit is a bug class — Step 5 retro-on-exit clause #4 now requires the iter to commit retro's BRIEFING edits as `chore(briefing): refresh from iter retro (P<NNN>)` before emitting `ITERATION_SUMMARY`. A dirty BRIEFING-at-iter-exit means the iter's retro-on-exit clause did not run to completion (retro hook failure, scoring failure, commit-gate rejection) and the orchestrator must NOT silently absorb it via a main-turn hand-off commit. | **Halt the loop.** Report the `git status --porcelain` output, the last subagent's reported outcome, and the divergence. Do NOT spawn the next iteration. |
|
|
1034
1034
|
|
|
1035
1035
|
**Rationale**: the orchestrator previously treated the subagent's reported outcome as truth. Any lie, partial write, or silent failure in the subagent propagated into the summary. The `git status --porcelain` check is the cheapest possible independent verification — policy-authorised, no network, no judgement required — and it catches exactly the class of failure the subagent cannot self-report.
|
|
1036
1036
|
|
|
1037
|
-
**Step 2.5b cross-reference (
|
|
1037
|
+
**Step 2.5b cross-reference (the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem)**: before emitting the final AFK summary for a Step 6.75 dirty-for-unknown-reason halt, run Step 2.5b's surfacing routine. The routine is gated on ≥1 accumulated user-answerable skip; Step 6.75 halts fire between iters and frequently have accumulated skips from prior iters, so Step 2.5b's AskUserQuestion-default branch typically fires (`halt-paths-must-route-design-questions-through-Step-2.5b`). The dirty-for-unknown-reason halt itself remains a halt with bug-signal — Step 2.5b surfaces *prior-iter accumulated user-answerable skips only*; it does NOT ask the user how to recover the dirty state (that remains a Rule 6 user-input requirement on return).
|
|
1038
1038
|
|
|
1039
|
-
**Out of scope for this step**: attempting recovery from an unknown-reason dirty state. Per
|
|
1039
|
+
**Out of scope for this step**: attempting recovery from an unknown-reason dirty state. Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6, conflict resolution and ambiguous state require user input; non-interactive recovery would mask the bug this check is meant to surface.
|
|
1040
1040
|
|
|
1041
|
-
**Verify-iter-claims sub-step (
|
|
1041
|
+
**Verify-iter-claims sub-step (the "AFK iter subprocesses can over-claim completion in their ITERATION_SUMMARY — orchestrator trusts the claim but on-disk state contradicts it" problem).** The clean/dirty-known/dirty-unknown classification catches the *commit-didn't-land* failure class but not the *commit-landed-with-false-claim* class — both the commit message and the `ITERATION_SUMMARY.notes` field are written by the same iter subprocess from the same model state, so they can agree with each other while disagreeing with the on-disk artefacts the claim names (the "AFK iter subprocesses can over-claim completion in their ITERATION_SUMMARY — orchestrator trusts the claim but on-disk state contradicts it" problem session 8 iter 1 witness: commit message stated "all (a)–(j) Confirmation items green at source" + notes restated it + the cited ADR's 10 boxes were all `[ ]`). When the classification above returns Clean AND the iter reported `committed: true`, run the verify-iter-claims check:
|
|
1042
1042
|
|
|
1043
1043
|
1. Dump the iter's `ITERATION_SUMMARY.notes` field to a temp file (`/tmp/iter-notes-$$.txt`).
|
|
1044
|
-
2. Invoke `wr-itil-verify-iter-summary <commit_sha> <notes_file>` (the PATH shim per
|
|
1044
|
+
2. Invoke `wr-itil-verify-iter-summary <commit_sha> <notes_file>` (the PATH shim per the "Plugin-bundled scripts invoked from SKILL.md resolve via `bin/` on `$PATH`" architecture rule; never invoke the repo-relative `packages/itil/scripts/verify-iter-summary.sh` path from SKILL prose — adopter installs resolve the shim, not the source-monorepo path).
|
|
1045
1045
|
3. Read the exit code:
|
|
1046
1046
|
- **Exit 0** → no over-claim detected (no ADR referenced, OR no completion-claim signal, OR signal-and-all-Confirmation-items-checked). Proceed to Step 7.
|
|
1047
1047
|
- **Exit 1** → OVER-CLAIM detected (at least one cited ADR has unchecked `- [ ]` Confirmation items while the iter's commit message or notes contains completion-claim language like "all green at source", "all Confirmation items complete", "(a)-(j) green"). **Halt the loop** with `outcome: halted-iter-over-claim`. Include the verifier's stdout (the `OVER-CLAIM: ADR-NNN has N unchecked Confirmation item(s)...` lines) as the divergence detail in the halt summary. Route through Step 2.5b's surfacing routine before emitting the halt summary (`halt-paths-must-route-design-questions-through-Step-2.5b`); the over-claim halt itself remains a halt-with-bug-signal — the iter's self-contradicting output IS the bug, and the user must adjudicate on return (re-dispatch the work / accept partial state / amend the commit).
|
|
1048
1048
|
- **Exit 2** → verifier invocation error (missing args, unreadable notes file, bad sha). Halt the loop with `outcome: halted-iter-verifier-error` and the verifier's stderr. This shape is itself an orchestrator-side bug; surfacing it loudly is preferable to silently proceeding.
|
|
1049
1049
|
|
|
1050
|
-
**Detection class boundary.** Verify-iter-claims is the *emit-but-over-claim* class detector — distinct from the *stuck-before-emit* class (
|
|
1050
|
+
**Detection class boundary.** Verify-iter-claims is the *emit-but-over-claim* class detector — distinct from the *stuck-before-emit* class (the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem, exit 143 + 0-byte JSON) which is already covered by the Step 5 idle-timeout SIGTERM handling + this step's existing dirty/clean check (working tree dirty after a missing-summary iter halts the loop). The verifier is intentionally narrow (ADR `## Confirmation` checkboxes) — it catches the load-bearing recurring shape where an iter ships an invariant gate (CI drift, README pairing) in the same commit as the work the gate is meant to test. Other over-claim shapes (claimed commits with no diff hunks; claimed file edits not in `git show --stat`) can be added incrementally as further witnesses surface; option (d) iter-local drift-bats (running the verifier inside the iter subprocess before `ITERATION_SUMMARY` emission) is deferred pending evidence that orchestrator-side (a) is insufficient — evidence-based, not BUFD (same shape as the "Agent waits on calendar trigger for held-cohort graduation — violates symmetric balance principle" problem/the "run-retro Step 3 Tier 3 Branch B "leave-as-is" encodes fictional defer — sibling to evidence-based criterion" problem).
|
|
1051
1051
|
|
|
1052
|
-
**Auto-correction is out of scope.** The orchestrator cannot retroactively make a false claim true; halt-with-bug-signal is the correct stance per
|
|
1052
|
+
**Auto-correction is out of scope.** The orchestrator cannot retroactively make a false claim true; halt-with-bug-signal is the correct stance per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6.
|
|
1053
1053
|
|
|
1054
1054
|
### Step 7: Loop
|
|
1055
1055
|
|
|
1056
1056
|
Go back to step 1. The backlog may have changed — new problems may have been created during fixes, priorities may have shifted, and the README.md cache will be stale.
|
|
1057
1057
|
|
|
1058
|
-
Natural-language modifiers in the invocation args (`just`, `only`, `first`, `merely`, `simply` paired with a ticket reference — e.g. `/wr-itil:work-problems just work
|
|
1058
|
+
Natural-language modifiers in the invocation args (`just`, `only`, `first`, `merely`, `simply` paired with a ticket reference — e.g. `/wr-itil:work-problems just work the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem`) are **SCOPE FILTERS** that override Step 1's WSJF selection; they do NOT alter Step 7's loop-back semantics. See **Mid-loop ask discipline → Scope-pin-word semantics (the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem)** below for the load-bearing prose.
|
|
1059
1059
|
|
|
1060
1060
|
## Non-Interactive Decision Making
|
|
1061
1061
|
|
|
@@ -1063,65 +1063,65 @@ When `AskUserQuestion` is unavailable or the user is AFK, the skill (and the del
|
|
|
1063
1063
|
|
|
1064
1064
|
| Decision Point | Non-Interactive Default |
|
|
1065
1065
|
|---|---|
|
|
1066
|
-
| How each iteration runs (iteration delegation) | Dispatch to a fresh `claude -p --permission-mode bypassPermissions --output-format json` subprocess via Bash per Step 5 — NOT Agent-tool dispatch (the Agent-tool-spawned subagent has no Agent in its own surface, so governance gates cannot be satisfied —
|
|
1067
|
-
| Retro at iteration end (per-iteration lessons captured) | Iteration subprocess invokes `/wr-retrospective:run-retro` before emitting `ITERATION_SUMMARY` so Step 2b pipeline-instability scan runs inside the subprocess's tool-call history. Retro commits its own work per
|
|
1066
|
+
| How each iteration runs (iteration delegation) | Dispatch to a fresh `claude -p --permission-mode bypassPermissions --output-format json` subprocess via Bash per Step 5 — NOT Agent-tool dispatch (the Agent-tool-spawned subagent has no Agent in its own surface, so governance gates cannot be satisfied — the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem), and NOT inline Skill-tool invocation (expands manage-problem into the orchestrator's context and burns turns — the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem). The subprocess is a full main Claude Code session with Agent available, so architect / JTBD / risk-scorer reviews run at full depth; the orchestrator consumes the `ITERATION_SUMMARY` return-shape from the subprocess's JSON stdout. No per-iteration budget cap — natural stop is quota exhaustion. This is the AFK iteration-isolation wrapper — subprocess-boundary variant under the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule. Per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule. |
|
|
1067
|
+
| Retro at iteration end (per-iteration lessons captured) | Iteration subprocess invokes `/wr-retrospective:run-retro` before emitting `ITERATION_SUMMARY` so Step 2b pipeline-instability scan runs inside the subprocess's tool-call history. Retro commits its own work per the "Governance Skills Commit Their Own Completed Work" architecture rule; orchestrator picks up retro-created tickets on next Step 1 scan. Non-blocking: if retro fails or surfaces findings, iteration still emits summary — do not halt the AFK loop on a flaky retro. Per the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess-boundary retro-on-exit clause. |
|
|
1068
1068
|
| Which problem to work | Highest WSJF, no prompt needed |
|
|
1069
1069
|
| Multi-concern split | Auto-split (manage-problem step 4b fallback) |
|
|
1070
1070
|
| Scope expansion during work | Update problem file, re-score WSJF, move to next problem instead of continuing |
|
|
1071
1071
|
| Commit when risk within appetite | Auto-commit (manage-problem step 9e fallback) |
|
|
1072
1072
|
| Commit when risk above appetite | Skip commit, report uncommitted state |
|
|
1073
|
-
| Pipeline risk within appetite (≤ 4/25) with releasable material (any unpushed commits OR any `.changeset/` entries) | Drain release queue (`push:watch` then, if releasable changesets exist, `release:watch`) before next iteration — per
|
|
1074
|
-
| Pipeline risk within appetite (≤ 4/25) AND empty queue (no unpushed commits AND no `.changeset/`) | No drain — literally nothing to release. Proceed directly to Step 6.75. The genuine no-op fast-path per
|
|
1075
|
-
| Post-release K→V auto-transition between iters (
|
|
1076
|
-
| Post-release plugin cache refresh between iters (
|
|
1077
|
-
| CI failure during Step 6.5 drain (within-appetite branch) | Diagnose via `gh run view --log-failed`, classify against the closed fixable-in-iter allow-list (
|
|
1078
|
-
| Pipeline risk above appetite (push or release >= 5/25) | Auto-apply scorer remediations incrementally (
|
|
1079
|
-
| Origin diverged before start (Branch 1) | Pull `--ff-only` if trivial; route to Branch 3 (stop with `git log HEAD..origin/<base>` and reverse report) if non-fast-forward — per
|
|
1080
|
-
| Pre-existing uncommitted work attributable to prior iter's in-flight flow (Branch 2 — DEFERRED) | Per
|
|
1081
|
-
| Prior-session partial work detected at start (Branch 3 detection — session-continuity dirty: untracked `docs/decisions/*.proposed.md` / `docs/problems/*.md`, `.afk-run-state/iter-*.json` with `is_error: true` or `api_error_status >= 400`, stale `.claude/worktrees/*`, uncommitted SKILL.md/source/ADR edits) | Halt the loop with a structured Prior-Session State report in the AFK summary — deliberate carve-out from the 2026-06-06 Rule 6 queue-and-continue default (ambiguous state would mask the bug this preflight surfaces). Do NOT attempt non-interactive resume. Interactive invocations prompt via `AskUserQuestion` with 4 options (resume / discard / leave-and-lower-priority / halt). Per
|
|
1073
|
+
| Pipeline risk within appetite (≤ 4/25) with releasable material (any unpushed commits OR any `.changeset/` entries) | Drain release queue (`push:watch` then, if releasable changesets exist, `release:watch`) before next iteration — per the "Inter-iteration release cadence for AFK loops" architecture rule (Step 6.5) as amended by the "work-problems Step 6.5 "≤3 within appetite — no drain" clause defers low-risk releases, encoding accumulation" problem. Trigger is *presence of releasable material*, not residual band reaching appetite. User direction 2026-05-17: "If it's low risk, you should release." |
|
|
1074
|
+
| Pipeline risk within appetite (≤ 4/25) AND empty queue (no unpushed commits AND no `.changeset/`) | No drain — literally nothing to release. Proceed directly to Step 6.75. The genuine no-op fast-path per the "work-problems Step 6.5 "≤3 within appetite — no drain" clause defers low-risk releases, encoding accumulation" problem. |
|
|
1075
|
+
| Post-release K→V auto-transition between iters (the ".known-error.md → .verifying.md transition not happening consistently at release time" problem) | After a successful within-appetite Drain action shipped a release to npm, invoke `wr-itil-enumerate-postrelease-kv-candidates` to enumerate `.known-error.md` tickets whose `**Release vehicle**: .changeset/<name>.md` citation matches a just-shipped (deleted-from-tree) changeset, and dispatch `/wr-itil:transition-problem <NNN> verifying` per emitted `KV_CANDIDATE` line. Conditional on actual release (skipped when `push:watch` ran alone with no changeset); non-blocking on individual transition failure (logs per-ticket, continues to next candidate; persistent failures route to Step 2.5b accumulated questions). V→C remains a maintainer-only surface — this callback fires K→V only. Per the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule + the "Inter-iteration release cadence for AFK loops" architecture rule + the "Rename `wr-problem` Plugin to `wr-itil`" architecture rule amended the "Problem 093: `/wr-itil:transition-problem` ↔ `/wr-itil:manage-problem` circular delegation for `<NNN> <status>` args" problem + the "Governance Skills Commit Their Own Completed Work" architecture rule + the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule + the ".known-error.md → .verifying.md transition not happening consistently at release time" problem + the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem + the "Codify `derive-release-vehicle.sh` helper for K→V release-cycle citation" problem + the "derive-release-vehicle helper requires pre-edit of ticket changeset reference — three-touch when one-touch would suffice" problem (Step 6.5 Post-release K→V auto-transition subsection). |
|
|
1076
|
+
| Post-release plugin cache refresh between iters (the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem) | After a successful within-appetite Drain action shipped a release to npm, chain `/install-updates` to refresh the plugin cache before the next iter dispatches. Conditional on actual release (skipped when `push:watch` ran alone with no changeset); non-blocking on `/install-updates` failure (degrades to cache-stays-stale, equivalent to pre-amendment behaviour). Mid-loop ask discipline preserved by treating any `/install-updates` AskUserQuestion surface AS the Non-interactive fallback dry-run path. Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule + the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem + the "`/install-updates` Step 7 uses `claude plugin install` which silently no-ops when a plugin is already installed — updates never actually land" problem + the "AFK iter subprocess plugin cache stale after release — just-shipped hook does not protect the next iter" problem (Step 6.5 Post-release cache refresh subsection). |
|
|
1077
|
+
| CI failure during Step 6.5 drain (within-appetite branch) | Diagnose via `gh run view --log-failed`, classify against the closed fixable-in-iter allow-list (the "Problem 081: Structural source-content tests are wasteful — TDD agent should reject them and require behavioural tests (+ framework / stub enhancements)" problem-class stale-grep-string, hook stub mismatch, test ID drift, environmental flake), fix-and-continue for fixable classes (each retry rides its own the "Governance Skills Commit Their Own Completed Work" architecture rule commit gate), 3-retry cap per iteration, halt for unrecoverable classes. Ambiguous classification defaults to halt. the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 policy-authorised. Per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding + the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary + the "`/wr-itil:work-problems` Step 6.5 halt-on-CI-failure direction should be fix-and-continue when failure is mechanically fixable (-class stale assertions)" problem (Step 6.5 Failure handling). |
|
|
1078
|
+
| Pipeline risk above appetite (push or release >= 5/25) | Auto-apply scorer remediations incrementally (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 2). The agent reads suggestions and decides what to do. Re-score after each apply; drain when within appetite. **Never release above appetite** (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 1) — no AskUserQuestion shortcut. Halt the loop with `outcome: halted-above-appetite` if the loop exhausts without convergence (the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5). Verification Pending commits excluded from auto-revert (Rule 2b). Per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule (Step 6.5 Above-appetite branch). |
|
|
1079
|
+
| Origin diverged before start (Branch 1) | Pull `--ff-only` if trivial; route to Branch 3 (stop with `git log HEAD..origin/<base>` and reverse report) if non-fast-forward — per the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule (Step 0 Branch 1 / Branch 3). |
|
|
1080
|
+
| Pre-existing uncommitted work attributable to prior iter's in-flight flow (Branch 2 — DEFERRED) | Per the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule Branch 2 (currently routes → Branch 3 until follow-up lands the auto-commit mechanism + the ": Enforce Governance Without Slowing Down" user outcome gate composition + bats). Auto-commit criteria when shipped: (a) provenance unambiguous AND (b) risk within appetite per the "Inter-iteration release cadence for AFK loops" architecture rule. Commit subject convention: `chore(preflight): recover prior-session in-flight work — <ticket-ref>` (the ": Progress the Backlog While I'm Away" user outcome audit trail). |
|
|
1081
|
+
| Prior-session partial work detected at start (Branch 3 detection — session-continuity dirty: untracked `docs/decisions/*.proposed.md` / `docs/problems/*.md`, `.afk-run-state/iter-*.json` with `is_error: true` or `api_error_status >= 400`, stale `.claude/worktrees/*`, uncommitted SKILL.md/source/ADR edits) | Halt the loop with a structured Prior-Session State report in the AFK summary — deliberate carve-out from the 2026-06-06 Rule 6 queue-and-continue default (ambiguous state would mask the bug this preflight surfaces). Do NOT attempt non-interactive resume. Interactive invocations prompt via `AskUserQuestion` with 4 options (resume / discard / leave-and-lower-priority / halt). Per the "`/wr-itil:work-problems` preflight Step 0 does not detect prior-session partial-work state (untracked ADRs, `.afk-run-state/iter-*.json` with 429/error statuses, existing `.claude/worktrees/*` branches)" problem + the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule (Step 0 Branch 3 detection mechanism). |
|
|
1082
1082
|
| Fix verification needed | Skip problem, add to "needs verification" list |
|
|
1083
|
-
| Stop-condition #2 with user-answerable skip-reasons | Default: call AskUserQuestion (batched, ≤4 per call, sequential when >4) — the orchestrator's main turn is interactive by construction per
|
|
1084
|
-
| Pre-`ALL_DONE` gate sequence at any loop end (every stop-condition + every halt-path that emits a final summary + quota-exhaustion natural end) | Run Step 2.4 sequence UNCONDITIONALLY before `ALL_DONE` emit: gate (a) outstanding-questions surface via Step 2.5b; gate (b) session-level retro via `/wr-retrospective:run-retro`; gate (c) emit `ALL_DONE` only after (a) AND (b) complete. Hard-fail mode: if either gate cannot complete cleanly, halt with directive instead of emit `ALL_DONE` — recovery is the user satisfying the gate and re-invoking the skill. Per
|
|
1085
|
-
| Halt-path final summary with accumulated user-answerable skips (CI failure / Rule 5 above-appetite / dirty-unknown / session-continuity / fetch failure) | Run Step 2.5b's surfacing routine before emitting the halt path's final AFK summary. Step 2.5b is gated on ≥1 accumulated user-answerable skip — empty-skip halts skip the routine. Step 2.5b surfaces *prior-iter accumulated user-answerable skips only*; it does NOT ask the user how to remediate the halt cause itself (CI failure / above-appetite state / dirty-unknown state remain halt-with-bug-signal). Per
|
|
1086
|
-
| Unexpected dirty state between iterations | Halt the loop. Report the `git status --porcelain` output, the last iteration's reported outcome, and the divergence — per
|
|
1087
|
-
| Iter committed cleanly + claim contradicts on-disk ADR Confirmation state (
|
|
1088
|
-
| External root cause detected at Open → Known Error, or at park with `upstream-blocked` reason | **Auto-invoke `/wr-itil:report-upstream`** via the manage-problem Step 6 external-root-cause detection AFK fallback (per
|
|
1089
|
-
| Mid-loop ask between iters in the orchestrator's main turn | Forbidden except at framework-prescribed user-interaction points (Step 0 session-continuity / fetch-failure halt; Step 2.5 / 2.5b loop-end emit; Step 6.5 above-appetite Rule 5 halt; Step 6.5 CI-failure / release:watch halt; Step 6.75 dirty-for-unknown-reason halt). The loop's purpose is **progress + accumulation**; mechanical-stage transitions between iters are framework-resolved and MUST NOT prompt the user. Per
|
|
1083
|
+
| Stop-condition #2 with user-answerable skip-reasons | Default: call AskUserQuestion (batched, ≤4 per call, sequential when >4) — the orchestrator's main turn is interactive by construction per the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess-boundary; user is presumed at the keyboard. Fallback: emit Outstanding Design Questions table when AskUserQuestion is unavailable (Rule 6 fail-safe). Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 + the "`/wr-itil:work-problems` stop-condition #2 defaults to the AFK Outstanding Design Questions table when AskUserQuestion is available — interactive users get no questions" problem (Step 2.5). |
|
|
1084
|
+
| Pre-`ALL_DONE` gate sequence at any loop end (every stop-condition + every halt-path that emits a final summary + quota-exhaustion natural end) | Run Step 2.4 sequence UNCONDITIONALLY before `ALL_DONE` emit: gate (a) outstanding-questions surface via Step 2.5b; gate (b) session-level retro via `/wr-retrospective:run-retro`; gate (c) emit `ALL_DONE` only after (a) AND (b) complete. Hard-fail mode: if either gate cannot complete cleanly, halt with directive instead of emit `ALL_DONE` — recovery is the user satisfying the gate and re-invoking the skill. Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary + the "Structured User Interaction for Governance-Skill Decisions" architecture rule + the "Governance Skills Commit Their Own Completed Work" architecture rule (retro commits its own work) + the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem (extends iter-level retro to orchestrator-level) + the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem (Step 2.4). |
|
|
1085
|
+
| Halt-path final summary with accumulated user-answerable skips (CI failure / Rule 5 above-appetite / dirty-unknown / session-continuity / fetch failure) | Run Step 2.5b's surfacing routine before emitting the halt path's final AFK summary. Step 2.5b is gated on ≥1 accumulated user-answerable skip — empty-skip halts skip the routine. Step 2.5b surfaces *prior-iter accumulated user-answerable skips only*; it does NOT ask the user how to remediate the halt cause itself (CI failure / above-appetite state / dirty-unknown state remain halt-with-bug-signal). Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule + the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem (`halt-paths-must-route-design-questions-through-Step-2.5b`). |
|
|
1086
|
+
| Unexpected dirty state between iterations | Halt the loop. Report the `git status --porcelain` output, the last iteration's reported outcome, and the divergence — per the "Problem 036: work-problems orchestrator does not verify commit-landing between iterations" problem (Step 6.75). Run Step 2.5b before emitting the halt summary if ≥1 accumulated user-answerable skip from prior iters (the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem). Do NOT attempt non-interactive recovery of the dirty state itself. |
|
|
1087
|
+
| Iter committed cleanly + claim contradicts on-disk ADR Confirmation state (the "AFK iter subprocesses can over-claim completion in their ITERATION_SUMMARY — orchestrator trusts the claim but on-disk state contradicts it" problem) | Halt the loop with `outcome: halted-iter-over-claim`. Include the `wr-itil-verify-iter-summary` stdout (the `OVER-CLAIM: ADR-NNN has N unchecked Confirmation item(s)...` lines) as the divergence detail. Run Step 2.5b before emitting the halt summary if ≥1 accumulated user-answerable skip from prior iters. Do NOT auto-correct the iter's claim — the orchestrator cannot retroactively make a false claim true; the user adjudicates on return (re-dispatch / accept partial / amend). Per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6 + the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule subprocess-boundary trust contract + the "AFK iter subprocesses can over-claim completion in their ITERATION_SUMMARY — orchestrator trusts the claim but on-disk state contradicts it" problem (Step 6.75 verify-iter-claims sub-step). |
|
|
1088
|
+
| External root cause detected at Open → Known Error, or at park with `upstream-blocked` reason | **Auto-invoke `/wr-itil:report-upstream`** via the manage-problem Step 6 external-root-cause detection AFK fallback (per the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 (the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem) amendment). The report-upstream skill composes the draft then scores the prose via `wr-risk-scorer:external-comms` (the "External-comms gate — voice-tone + risk/leak evaluators on shared PreToolUse surface" architecture rule); below-appetite → sends (public-issue Step 5 / comment Step 5c / security Step 6 per classification); above-appetite → risk-reduces (open-ended LLM judgement per leaf (a)) then re-scores → sends-or-queues to `## Queued Upstream Report` (leaf (c)). Security routing per leaf (b): upstream-with-`SECURITY.md` + below-appetite → files via declared channel; upstream-without-`SECURITY.md` → external-comms-gated impact assessment. Queue does NOT halt (the "AFK iter default when a skill needs to ask a question and AskUserQuestion is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem). Tickets already carrying the stable `- **Upstream report pending** -- external dependency identified; invoke /wr-itil:report-upstream when ready` marker from prior sessions are detected via the already-noted grep check and routed to the report-upstream invocation; the marker shape is retained as the detection substrate (ASCII `--` per the "work-problems SKILL.md AFK-fallback marker wording uses em-dash, forces consumer-side whitespace surgery" problem — em-dash variant is the legacy form, still matched by the already-noted check for backward compatibility). Per the "Problem 063: manage-problem does not trigger /wr-itil:report-upstream when root cause is external" problem (amended 2026-06-04) + the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem + the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6. |
|
|
1089
|
+
| Mid-loop ask between iters in the orchestrator's main turn | Forbidden except at framework-prescribed user-interaction points (Step 0 session-continuity / fetch-failure halt; Step 2.5 / 2.5b loop-end emit; Step 6.5 above-appetite Rule 5 halt; Step 6.5 CI-failure / release:watch halt; Step 6.75 dirty-for-unknown-reason halt). The loop's purpose is **progress + accumulation**; mechanical-stage transitions between iters are framework-resolved and MUST NOT prompt the user. Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary + the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 (as amended by the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule) + the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem. |
|
|
1090
1090
|
|
|
1091
|
-
### Mid-loop ask discipline (orchestrator main turn) —
|
|
1091
|
+
### Mid-loop ask discipline (orchestrator main turn) — the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem
|
|
1092
1092
|
|
|
1093
1093
|
The orchestrator MUST NOT call `AskUserQuestion` between iterations except at the framework-prescribed user-interaction halt points listed below. The loop's purpose is **progress + accumulation** — progress every ticket the agent can advance autonomously, accumulate user-answerable questions as a side-effect, and surface the accumulated batch only at a halt point. This rule applies whether the user is observably present or not, because **presence-detection is unreliable** and is not the goal — the user may answer one question and disappear for hours; the orchestrator's job is to keep advancing the backlog and stage the user-interaction surface for whenever the user actually returns. Treat the user as transient.
|
|
1094
1094
|
|
|
1095
1095
|
**Framework-prescribed halt points (the only orchestrator-main-turn surfaces where `AskUserQuestion` is permitted):**
|
|
1096
1096
|
|
|
1097
|
-
- **Step 0 session-continuity halt** — Prior-Session State report; user routes resume / discard / leave-and-lower / halt (interactive branch only; AFK branch halts with the structured report per
|
|
1097
|
+
- **Step 0 session-continuity halt** — Prior-Session State report; user routes resume / discard / leave-and-lower / halt (interactive branch only; AFK branch halts with the structured report per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6).
|
|
1098
1098
|
- **Step 0 fetch-failure halt** — `git fetch origin` network failure; halt-with-report so the user retries on return.
|
|
1099
|
-
- **Step 2.5 / Step 2.5b loop-end emit** — accumulated `outstanding_questions` queue presented as batched `AskUserQuestion` (or fallback Outstanding Design Questions table per
|
|
1100
|
-
- **Step 6.5 above-appetite Rule 5 halt** — auto-apply loop exhausted without convergence; halt-with-batched-questions per the Step 2.5b cross-reference (Step 2.5b surfaces *prior-iter accumulated user-answerable skips only* — the halt-causing scorer-gap remains a halt-with-bug-signal per
|
|
1101
|
-
- **Step 6.5 CI-failure / `release:watch` failure halt** — push:watch or release:watch failed AND the failure is genuinely-unrecoverable (outside the fixable-in-iter allow-list, or 3-retry cap reached); halt-with-batched-questions per the Step 2.5b cross-reference. Failures inside the closed allow-list route to fix-and-continue per Step 6.5 Failure handling (
|
|
1099
|
+
- **Step 2.5 / Step 2.5b loop-end emit** — accumulated `outstanding_questions` queue presented as batched `AskUserQuestion` (or fallback Outstanding Design Questions table per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6). This is the framework's prescribed user-interaction point; do NOT dilute it by asking earlier.
|
|
1100
|
+
- **Step 6.5 above-appetite Rule 5 halt** — auto-apply loop exhausted without convergence; halt-with-batched-questions per the Step 2.5b cross-reference (Step 2.5b surfaces *prior-iter accumulated user-answerable skips only* — the halt-causing scorer-gap remains a halt-with-bug-signal per the "Auto-apply scorer remediations to reach within appetite — open action-class vocabulary" architecture rule Rule 5).
|
|
1101
|
+
- **Step 6.5 CI-failure / `release:watch` failure halt** — push:watch or release:watch failed AND the failure is genuinely-unrecoverable (outside the fixable-in-iter allow-list, or 3-retry cap reached); halt-with-batched-questions per the Step 2.5b cross-reference. Failures inside the closed allow-list route to fix-and-continue per Step 6.5 Failure handling (the "`/wr-itil:work-problems` Step 6.5 halt-on-CI-failure direction should be fix-and-continue when failure is mechanically fixable (-class stale assertions)" problem), not this halt point.
|
|
1102
1102
|
- **Step 6.75 dirty-for-unknown-reason halt** — `git status --porcelain` divergence; halt-with-batched-questions per the Step 2.5b cross-reference.
|
|
1103
|
-
- **Step 6.75 iter-over-claim halt (
|
|
1103
|
+
- **Step 6.75 iter-over-claim halt (the "AFK iter subprocesses can over-claim completion in their ITERATION_SUMMARY — orchestrator trusts the claim but on-disk state contradicts it" problem)** — `wr-itil-verify-iter-summary` detected the iter's commit message or `ITERATION_SUMMARY.notes` contains completion-claim language for an ADR whose `## Confirmation` section still has unchecked `- [ ]` items; halt-with-batched-questions per the Step 2.5b cross-reference. The over-claim itself remains a halt-with-bug-signal — Step 2.5b surfaces *prior-iter accumulated user-answerable skips only*; it does NOT ask the user how to remediate the false claim (re-dispatch / accept partial / amend the commit remains a user decision on return).
|
|
1104
1104
|
|
|
1105
1105
|
**No mid-iter ask points.** Every other point in the orchestrator's main turn (between Step 5 dispatch completing and Step 6.5 release-cadence check; between Step 6.75 verification and Step 7 loop-back; between Step 7 and Step 1 next-iteration; between consecutive iters generally) is a mechanical-stage transition that the framework has already resolved. Do NOT introduce ad-hoc `AskUserQuestion` calls at those points to confirm "is it OK to proceed?" or "want me to start the next iter?" — proceeding IS the framework-resolved default. Continue iterating until quota or stop-condition #1/#2/#3 fires.
|
|
1106
1106
|
|
|
1107
|
-
<!-- @jtbd
|
|
1108
|
-
<!-- @jtbd
|
|
1109
|
-
<!-- @problem
|
|
1110
|
-
**Scope-pin-word semantics (
|
|
1107
|
+
<!-- @jtbd the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away — scope-pin invocation does not trigger agent-inferred premature halt; loop advances pinned-ticket work until framework-prescribed stop fires) -->
|
|
1108
|
+
<!-- @jtbd the ": Enforce Governance Without Slowing Down" user outcome (Enforce Governance Without Slowing Down — the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary for loop control codified in skill prose; no re-prompt round-trip after scope-pin invocation) -->
|
|
1109
|
+
<!-- @problem the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem -->
|
|
1110
|
+
**Scope-pin-word semantics (the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem).** Natural-language modifiers in the invocation args — `just`, `only`, `first`, `merely`, `simply` paired with a ticket reference (e.g. `/wr-itil:work-problems just work the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem`) — are **SCOPE FILTERS** over Step 1's WSJF selection: they pin the loop to the named ticket instead of letting Step 3's tier + tie-break ladder select. They are NOT count constraints. The Step 7 → Step 1 loop-back contract is unchanged; iterations continue on the pinned ticket until a framework-prescribed stop condition fires (Step 2 #1 no actionable / #2 all interactive / #3 all blocked; Step 2.4 gate (a)/(b) pre-`ALL_DONE` sequence; quota exhaustion; Step 6.5 / Step 6.75 / Step 0 halt paths). The orchestrator MUST NOT emit `ALL_DONE` from natural-language modifier interpretation alone — `ALL_DONE` is reserved for the framework-resolved stop surface per Step 2.4 gate (c). Concretely: if iter 1 on the pinned ticket returns `outcome: partial-progress` with `outstanding_questions` queued and remaining slices named in `notes`, the orchestrator dispatches iter 2 on the same pinned ticket; the loop only stops when the ticket's actionable work is exhausted (Step 2 #1 then fires for the pinned-scope view) OR a halt path fires. This is the **inverse-direction** failure mode of the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem's inverse-presence pattern — both stem from agent over-inferring loop-control semantics the framework already resolved (per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule framework-resolution boundary's "Continue / stop loops" mediation; loop control is framework-resolved, agents do not invent halt criteria from natural-language modifiers). When the user invokes the orchestrator with a scope-pin word, treat that word as a **selection override** only, not a loop-control directive.
|
|
1111
1111
|
|
|
1112
|
-
**Accumulated-question discipline at surface time** (per
|
|
1112
|
+
**Accumulated-question discipline at surface time** (per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's six-class authority taxonomy — questions that reach the user must be load-bearing):
|
|
1113
1113
|
|
|
1114
1114
|
- **Direction-setting only** — questions that ONLY the user can answer because they reflect goals, intent, or trade-offs the framework has not yet captured. Other accumulated observations (deviation-approval, one-time-override, silent-framework, taste, correction-followup) follow the same shape as the deviation-candidate schema in Step 5's `outstanding_questions` contract.
|
|
1115
|
-
- **No BUFD** — don't pre-judge architectural decisions before evidence accumulates. Small, actionable questions; not galaxy-brain ones. The deviation-candidate surface (per
|
|
1115
|
+
- **No BUFD** — don't pre-judge architectural decisions before evidence accumulates. Small, actionable questions; not galaxy-brain ones. The deviation-candidate surface (per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule's anti-BUFD-for-framework-evolution clause) is the place where iter-discovered misfits accumulate; the user resolves with full context at loop end.
|
|
1116
1116
|
- **No questions answerable by research / exploration / experimentation** — the agent should prototype, read code, run experiments to answer those itself rather than sub-contracting routine investigative work back to the user. The user is the source for genuine direction-setting decisions, not for "what does this hook do" or "which file holds X" — those are research questions the agent owns.
|
|
1117
1117
|
|
|
1118
1118
|
**Cross-references:**
|
|
1119
1119
|
|
|
1120
1120
|
- **Step 5's iteration-prompt body** carries the per-subprocess "Do not call `AskUserQuestion`" constraint; this subsection carries the orchestrator-main-turn equivalent. Together they enforce the same discipline at both the subprocess layer and the main-turn layer end-to-end.
|
|
1121
|
-
- **
|
|
1122
|
-
- **
|
|
1123
|
-
- **
|
|
1124
|
-
- **
|
|
1121
|
+
- **the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule** is the parent decision narrowing the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1 to framework-unresolved decisions; this subsection is one of its load-bearing implementation surfaces.
|
|
1122
|
+
- **the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 1** (as amended by the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule) restricts `AskUserQuestion` to framework-unresolved decisions; the framework-prescribed halt enumeration above is the orchestrator-layer interpretation of that narrowing.
|
|
1123
|
+
- **the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6** is the non-interactive fail-safe — when `AskUserQuestion` is unavailable (restricted permission mode, hook-disabled tool surface), the framework-prescribed halts fall back to structured-summary table emission rather than skipping the user-interaction.
|
|
1124
|
+
- **the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule** subprocess-boundary contract is unchanged — this subsection is orchestrator-main-turn discipline; the iteration-subprocess dispatch shape (the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem + the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem + the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem + the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem) is untouched.
|
|
1125
1125
|
|
|
1126
1126
|
## Edge Cases
|
|
1127
1127
|
|
|
@@ -1143,44 +1143,44 @@ The skill should produce a final summary when the loop ends:
|
|
|
1143
1143
|
### Completed
|
|
1144
1144
|
| # | Problem | Action | Result |
|
|
1145
1145
|
|---|---------|--------|--------|
|
|
1146
|
-
| 1 |
|
|
1147
|
-
| 2 |
|
|
1146
|
+
| 1 | the "Problem 029: Edit gate overhead disproportionate for governance documentation changes" problem (Edit gate overhead) | Implemented fix | Closed |
|
|
1147
|
+
| 2 | the "Problem 021: Governance-skill decision prompts must be structured (AskUserQuestion + plan mode), not prose — silent below appetite" problem (Structured prompts) | Investigated root cause | Transitioned to Known Error |
|
|
1148
1148
|
|
|
1149
1149
|
### Skipped
|
|
1150
1150
|
| Problem | Skip-reason category | Reason |
|
|
1151
1151
|
|---------|---------------------|--------|
|
|
1152
|
-
|
|
|
1152
|
+
| the "Problem 016: `manage-problem` skill does not flag or split multi-concern tickets" problem (Multi-concern splitting) | user-answerable (verification) | Awaiting user verification |
|
|
1153
1153
|
|
|
1154
1154
|
### Reported Upstream
|
|
1155
1155
|
|
|
1156
|
-
<!-- @jtbd
|
|
1156
|
+
<!-- @jtbd the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away — the summary reports ACTUAL upstream filings so the AFK audit trail is honest, never a re-run-to-file checklist) -->
|
|
1157
1157
|
|
|
1158
1158
|
(Renders when ≥1 upstream-blocked ticket was auto-filed or queued this loop by the Step 4 `upstream-blocked` row's per-iter auto-invoke of `/wr-itil:report-upstream`. Reports ACTUAL filings and queued drafts — never a to-do list of "re-run to file". Omitted entirely when no ticket was upstream-reported this loop.)
|
|
1159
1159
|
|
|
1160
1160
|
| Ticket | Upstream action | Result |
|
|
1161
1161
|
|--------|-----------------|--------|
|
|
1162
|
-
|
|
|
1163
|
-
|
|
|
1162
|
+
| the "Problem 067: /wr-itil:report-upstream classifier is not problem-first — picks bug / feature / question and emits a bug-shaped default" problem (adopter hook path bug) | Filed to windyroad/agent-plugins#142 | Sent (below appetite) |
|
|
1163
|
+
| the "Problem 071: Argument-based skill subcommands are not discoverable in Claude Code autocomplete" problem (security-classified regression) | Queued to `## Queued Upstream Report` | Above appetite — surfaced as outstanding question |
|
|
1164
1164
|
|
|
1165
1165
|
### Outstanding Design Questions
|
|
1166
1166
|
|
|
1167
|
-
(Emitted only when stop-condition #2 fires AND at least one skipped ticket has a `user-answerable (design/direction/pacing/scope)` skip-reason. Populated by Step 2.5 in non-interactive / AFK mode per
|
|
1167
|
+
(Emitted only when stop-condition #2 fires AND at least one skipped ticket has a `user-answerable (design/direction/pacing/scope)` skip-reason. Populated by Step 2.5 in non-interactive / AFK mode per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6.)
|
|
1168
1168
|
|
|
1169
1169
|
| Ticket | Question | Context |
|
|
1170
1170
|
|--------|----------|---------|
|
|
1171
|
-
|
|
|
1172
|
-
|
|
|
1171
|
+
| the "Problem 049: Known Error status is overloaded — "fix released, awaiting verification" deserves its own explicit status" problem (Known Error overloaded) | What should the new status be called, and what file suffix? | Decide so the rename/migration commit can land unambiguously. |
|
|
1172
|
+
| the "Problem 051: run-retro does not recommend improvements to existing skills, agents, hooks, or other codifiables" problem (run-retro improvement axis) | Ship in this AFK loop or next? | the "Problem 050: run-retro does not recommend new agents, hooks, or other codifiable outputs (generalises )" problem is still fresh; rewriting Step 2/4b/5 twice in one session may churn. |
|
|
1173
1173
|
|
|
1174
1174
|
### Remaining Backlog
|
|
1175
1175
|
| WSJF | Problem | Status |
|
|
1176
1176
|
|------|---------|--------|
|
|
1177
|
-
| 9.0 |
|
|
1177
|
+
| 9.0 | the "Problem 012: Skill Testing Harness Scope Undefined" problem (Skill testing harness) | Open |
|
|
1178
1178
|
|
|
1179
1179
|
### Session Cost
|
|
1180
1180
|
|
|
1181
|
-
Extracted from each iteration subprocess's `claude -p --output-format json` response (source: measured-actual, not estimated — per
|
|
1181
|
+
Extracted from each iteration subprocess's `claude -p --output-format json` response (source: measured-actual, not estimated — per the "Agent output grounding — no fabricated quantitative estimates, cite + persist + uncertainty" architecture rule grounding). Renders identically in interactive and AFK modes; no decision branch, so output-side only. Cache-read column surfaces the warm-cache-reuse signal observed across subsequent subprocess invocations in the same Bash session.
|
|
1182
1182
|
|
|
1183
|
-
**Authority note (per
|
|
1183
|
+
**Authority note (per the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem Gap 2 — see Step 5 Authority hierarchy):** the "Total cost (USD)" column is authoritative (CLI reports `.total_cost_usd` as a session cumulative). The token columns are **best-effort** — they accumulate each iteration's `.usage.*` response fields, which reflect only the final-turn API envelope and can undercount when a subprocess exits via a background-task completion-notification ack. Cost-based reasoning trusts the cost column; token-based reasoning (cache-reuse ratios, cost-envelope calibration) reads the token columns with that caveat in mind.
|
|
1184
1184
|
|
|
1185
1185
|
| Metric | Value |
|
|
1186
1186
|
|--------|-------|
|
|
@@ -1198,44 +1198,44 @@ Extracted from each iteration subprocess's `claude -p --output-format json` resp
|
|
|
1198
1198
|
ALL_DONE
|
|
1199
1199
|
```
|
|
1200
1200
|
|
|
1201
|
-
**`ALL_DONE` position (
|
|
1201
|
+
**`ALL_DONE` position (the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem Step 2.4).** The `ALL_DONE` sentinel is the FINAL line of the rendered summary, emitted at Step 2.4 gate (c) — AFTER Step 2.4 gate (a) (outstanding-questions surface via Step 2.5b) AND AFTER Step 2.4 gate (b) (session-level retro via `/wr-retrospective:run-retro`) BOTH complete cleanly. The session-level retro's own commit + any tickets it creates land BEFORE the `ALL_DONE` emit. External scripts watching for AFK-loop completion can rely on `ALL_DONE` as an honest sentinel: when it appears, both gates have completed. Hard-fail mode (halt with directive) replaces `ALL_DONE` when either gate cannot complete — adopters should treat the absence of `ALL_DONE` paired with a halt-directive line as the recoverable-pause shape (user satisfies the gate on return; re-invocation emits `ALL_DONE` cleanly).
|
|
1202
1202
|
|
|
1203
1203
|
When every skipped ticket is in the `upstream-blocked` category (stop-condition #3) or there are no skipped tickets (stop-condition #1), omit the Outstanding Design Questions section entirely rather than rendering an empty heading. The Session Cost section always renders when at least one iteration ran.
|
|
1204
1204
|
|
|
1205
|
-
**Upstream reports are auto-filed per-iter, never deferred to a wrap-time batch choice (
|
|
1205
|
+
**Upstream reports are auto-filed per-iter, never deferred to a wrap-time batch choice (the "work-problems defers upstream reporting as a manual "batch-report upstream" choice instead of auto-filing upstream-blocked tickets" problem).** The `### Reported Upstream` section reports ACTUAL filings and queued drafts produced by the Step 4 `upstream-blocked` row's per-iter auto-invoke of `/wr-itil:report-upstream` (below-appetite → sent during the loop; above-appetite → risk-reduced then sent-or-queued per the "AFK iter default when a skill needs to ask a question and AskUserQuestion is unavailable — should queue the question and move to the next iteration (not halt, not silently skip)" problem). There is **no "batch-report upstream" mode** and no wrap-time reporting decision: the summary MUST NOT emit a "N upstream-blocked tickets are unreported — re-run `/wr-itil:work-problems` and choose batch-report upstream" nudge. That nudge is an agent-invented permission gate the framework did not authorise — the same class as the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem / the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem / the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem (agent-invented loop-control the framework already resolved per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule), and it directly contradicts the "Cross-project problem-reporting contract — `report-upstream` skill in `@windyroad/itil`" architecture rule 2026-06-04 (the "Agent waits for human to initiate upstream report instead of filing on detect — feedback delay class" problem) auto-fire contract the Step 4 row (lines 503 / 511) and decision table (line 1077) mandate. A below-appetite report just sends during the loop; an above-appetite report queues to `## Queued Upstream Report` and surfaces at Step 2.4 gate (a) as an `outstanding_questions` entry — never as a "re-run to report" instruction the user must action. If the loop ends with upstream-blocked tickets that were NOT reported, that is a bug (the auto-fire did not fire), not a batch the user should be asked to trigger.
|
|
1206
1206
|
|
|
1207
1207
|
## Related
|
|
1208
1208
|
|
|
1209
|
-
- **
|
|
1210
|
-
- **
|
|
1211
|
-
- **
|
|
1212
|
-
- **
|
|
1213
|
-
- **
|
|
1214
|
-
- **
|
|
1215
|
-
- **
|
|
1216
|
-
- **
|
|
1217
|
-
- **
|
|
1218
|
-
- **
|
|
1219
|
-
- **
|
|
1220
|
-
- **
|
|
1221
|
-
- **
|
|
1222
|
-
- **
|
|
1223
|
-
- **
|
|
1224
|
-
- **
|
|
1225
|
-
- **
|
|
1226
|
-
- **
|
|
1227
|
-
- **
|
|
1228
|
-
- **
|
|
1229
|
-
- **
|
|
1230
|
-
- **
|
|
1231
|
-
- **
|
|
1232
|
-
- **
|
|
1233
|
-
- **
|
|
1234
|
-
- **
|
|
1235
|
-
- **
|
|
1236
|
-
- **
|
|
1237
|
-
- **
|
|
1238
|
-
- **
|
|
1239
|
-
- **
|
|
1240
|
-
- **
|
|
1241
|
-
- **
|
|
1209
|
+
- **the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem** (`docs/problems/open/341-work-problems-skill-must-surface-outstanding-questions-then-run-retro-before-emitting-all-done.md`) — driver for Step 2.4 Pre-`ALL_DONE` gate sequence (UNCONDITIONAL fire of outstanding-questions surface + session-level retro before `ALL_DONE` emit). 2026-05-31 user direction (verbatim in ticket Description): *"The work-problems skill MUST surface the outstanding questions at the end before emitting ALL_DONE. It MUST then run a retro. Only then should it emit ALL_DONE."* Closes the structural gap that allowed `ALL_DONE` to emit while direction-class observations remained queued AND without a session-level retro running. Behavioural second-source: `test/work-problems-p341-pre-all-done-gate.bats`. Composes with the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem (extends iter-level retro-on-exit to orchestrator-level), the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem (preserves `halt-paths-must-route-design-questions-through-Step-2.5b` principle), the "Governance Skills Commit Their Own Completed Work" architecture rule (retro commits its own work), the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule (framework-resolution boundary for when to surface — now framework-resolved as unconditional pre-`ALL_DONE`).
|
|
1210
|
+
- **the "agent ends the work-problems loop (emits ALL_DONE) prematurely while actionable Tier-2 backlog remains, by rationalising the remainder as out-of-scope / interactive-gated" problem** (`docs/problems/known-error/390-agent-declares-all-done-prematurely-while-actionable-backlog-remains.md`) — driver for Step 2.4 **Gate (0) — Objective backlog-empty assertion** (prepended ahead of gate (a)). Bug shape: the orchestrator emitted `ALL_DONE` while a dispatchable Tier-2 backlog remained, by generalising "the *salient* remainder is interactive-gated" to "Step 2 stop-condition #2 holds" — a subjective stop the framework did not authorise; it also skipped the "work-problems `claude -p` iter subprocesses miss project-scoped governance plugins (need `--plugin-dir` in dispatch)" problem (Tier-1 sev-16) entirely. Fix: before `ALL_DONE`, gate (0) re-scans the live open/known-error backlog (fresh dual-tolerant glob, not the Step 1 cache) and classifies each ticket dispatchable/non-dispatchable OBJECTIVELY by recorded marker (verifying / `## Fix Released`; upstream-blocked; blocked dead-end; Step 3.5/3.6 durable per-session skip record). ≥1 dispatchable ticket FORBIDS `ALL_DONE` and loops back to Step 3 tier-first selection (loopback, not halt); a user-directed pivot does not discharge the Tier-exhaustion obligation. Sibling loop-control-stop class: the "run-retro skips Step 1.5 / Step 3 / Step 4b Stage 1 under session-length rationalization — recurrence of anti-pattern class on the run-retro meta-surface" problem (run-retro skip rationalisation), the "Agent defers ticket creation to retro summary "Tickets Deferred" section instead of immediately invoking `/wr-itil:manage-problem` — observations could be lost if user is in a rush" problem (Stage-1 ticketing skip), the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem (scope-pin loop-control inference); hardens the "`/wr-itil:work-problems` SKILL must surface outstanding questions FIRST, then run a retro, THEN emit `ALL_DONE` — current SKILL contract allows `ALL_DONE` to fire without one or both gates" problem's precondition. Behavioural second-source: `eval/promptfooconfig.yaml` Tier-A regex + Tier-B llm-rubric asserting the orchestrator does NOT emit `ALL_DONE` when ≥1 dispatchable ticket remains. Per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule "Continue / stop loops" framework-resolution (the natural stop is concrete — `ALL_DONE` conditions objectively met). **Reopened fix (2026-07-05 → 2026-07-06, the "AFK loops anchor completion with the native `/goal` external evaluator" architecture rule / the ": AFK loop `/goal` anchor — external evaluator judges the stop" release design / the ": AFK loop anchored with the native `/goal` external evaluator" delivery story)**: Gate (0) alone proved insufficient (self-assessment — the same actor decides "should I stop" and "is stopping justified"); Step 0e anchors the loop with the native `/goal` external evaluator (per-turn small-fast-model judgement of the printed gate (0) table), gate (0)'s classification MUST be printed in turn output as the evaluator's evidence, and the headless launch shape `claude -p "/goal <canonical condition>"` is the anchor-guaranteed path (interactive starts get a nudge-and-proceed fallback).
|
|
1211
|
+
- **the "Iter retros queue their own observations as `outstanding-questions.jsonl` entries for user-direction triage instead of auto-ticketing — same trust-boundary as `/wr-retrospective:run-retro` Step 4a" problem** (`docs/problems/open/342-iter-retros-queue-observations-as-outstanding-questions-instead-of-auto-ticketing-same-trust-boundary-as-step-4a.md`) — driver for Step 5 iter-prompt body's retro-surfaced observation classification taxonomy and capture-* carve-out. Iter retros' observations of recurring class-of-behaviour now route to `/wr-itil:capture-problem` (mechanical-stage carve-out per run-retro Step 4a precedent); only direction-setting observations queue at `outstanding_questions`; ambiguous defaults to auto-ticket per the trust-boundary asymmetry. The "no `capture-*` siblings mid-loop" rule is preserved for non-retro mid-iter capture (the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem-class spam); the carve-out is bounded to the retro path. Sibling locus: `packages/retrospective/skills/run-retro/SKILL.md` Step 4b carries the symmetric mirror (same trust-boundary fires whether retro runs in iter context OR standalone in main turn). Behavioural second-source: `test/work-problems-p342-retro-auto-ticket-carveout.bats` + `packages/retrospective/skills/run-retro/test/run-retro-step-4b-retro-auto-ticket-carveout.bats`. Composes with run-retro Step 4a (precedent), the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 5 (policy-authorised silent proceed), the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule (foreground-spawns-N-background fanout already documented for Stage 1 in run-retro Step 4b), the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule (mechanical-stage carve-out), the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem (mid-loop AskUserQuestion ban unchanged), the "Problem 078: Assistant does not offer to capture a problem ticket when the user delivers strong-signal correction" problem (capture-on-correction — distinct trigger surface; both end in capture but for different signals).
|
|
1212
|
+
- **the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem** (`docs/problems/121-afk-orchestrator-should-sigterm-stuck-subprocesses-after-idle-timeout.verifying.md`) — driver for Step 5's backgrounded-poll-loop dispatch shape (replacing the prior foreground-synchronous form) and the idle-timeout SIGTERM branch. The 2026-04-25 the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem iter 5 evidence: an iteration subprocess sat idle ~70 min after its final commit, then SIGTERM produced a clean JSON exit-flush. Fix: orchestrator backgrounds the subprocess, polls every 60s, computes `LAST_ACTIVITY_MARK = max(DISPATCH_START_EPOCH, git log -1 --format=%at HEAD)`, and sends SIGTERM when `now - LAST_ACTIVITY_MARK > WORK_PROBLEMS_IDLE_TIMEOUT_S` (default 3600s = 60 min). Behavioural second-source: `test/work-problems-step-5-idle-timeout-sigterm.bats` exercises a fake `claude -p` shim that sleeps past the threshold and asserts SIGTERM, JSON exit-flush, env-var override, and within-threshold no-fire. Step 6's per-iter progress line SHOULD annotate `(SIGTERM_SENT)` when the branch fires so users can distinguish recovered iters from natural completions. the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule's subprocess-boundary variant amended 2026-04-26 with the backgrounded-poll-loop refinement.
|
|
1213
|
+
- **the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem** (`docs/problems/146-afk-iteration-subprocess-bash-until-loop-polls-bats-output-with-bats-console-regex-against-tap-format.verifying.md`) — driver for Step 5 iteration prompt body's bats-output-polling-discipline clause. The 2026-04-29 incident (iter 1, PID 23580 child PID 16408) saw a `bash until`-loop poll a backgrounded bats output file with regex `^[0-9]+ tests?,` (bats's *default* console-summary format) against `bats --tap` output that never emits that line — silent infinite spin after bats completed; manual SIGTERM at 68m34s wall-clock; metadata loss per the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem stuck-before-emit subclass. The polling idiom is NOT taught by any SKILL.md (audit confirmed via repo grep) — it is agent-learned from training data. Fix: prompt-discipline rule in the iteration prompt body's Constraints list explicitly forbidding the antipattern, naming `wait $bg_pid` (or Bash-tool `run_in_background=true` + `BashOutput`) as the safe substitute, and citing the TAP-vs-console-summary divergence so future contributors don't "fix" the rule incorrectly. Behavioural second-source: `test/work-problems-step-5-bats-polling-discipline.bats` asserts the prohibition phrase, the safe-substitute pointer, the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem cite, the divergence explanation, and the Related-section cite.
|
|
1214
|
+
- **the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem** (`docs/problems/verifying/232-bash-until-loop-pgrep-self-referential-deadlock-new-variant-of-p146.md`) — sibling variant of the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem; driver for the second clause in Step 5 iter prompt's polling-discipline rule plus the structural PreToolUse:Bash hook at `packages/itil/hooks/itil-bash-polling-antipattern-detect.sh`. The 2026-05-16 incident (iter 4, the "Agents over-ask in interactive sessions — conflating mechanical-stages with user-interactive-stages of multi-stage skill contracts (inverse-)" problem Phase 2a-iii-B) saw 4 concurrent `until ! pgrep -f 'bats --recursive'` polling loops each match the OTHER loops' command lines and spin forever after the main commit landed; 45 min wall-clock + $20-30 wasted before manual SIGTERM. Two-layer fix: prompt-discipline clause naming the self-reference failure mode with worked-example syntax (`until ! pgrep -f ...`), PLUS PreToolUse:Bash hook denying `(until|while)[[:space:]]+!?[[:space:]]*(pgrep|pkill[[:space:]]+-0)` shapes with a deny message citing the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem and naming both recovery alternatives (`wait $bg_pid` shell-native, Bash-tool `BashOutput` harness-native). Behavioural second-source: `packages/itil/hooks/test/itil-bash-polling-antipattern-detect.bats` (positive cases — until/while pgrep, until/while pkill -0, heredoc; negative cases — one-shot pgrep, non-`-0` pkill, unrelated until/while, `wait $!`; advisory-message content cite). the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem prompt-only enforcement failed empirically in iter 4 of the very loop that ships it; the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem closes the class with structural enforcement.
|
|
1215
|
+
- **the "Iter subprocess ends its turn waiting on a backgrounded task and never resumes — `claude -p` has no auto-resume; commit-bearing work is lost" problem** (`docs/problems/open/370-iter-subprocess-ends-turn-waiting-on-background-task-no-auto-resume-lost-work.md`) — sibling-class to the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem/the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem; driver for the Step 5 iter prompt's turn-end-survivor background-task prohibition clause. The iter subprocess is dispatched via `claude -p` (single-shot CLI, no auto-resume): its turn boundary IS its process boundary, so a backgrounded task whose completion is deferred to a later turn never resumes and the iter exits at turn-end with staged-but-uncommitted work. Witnessed: iter 11 of a prior loop — $8.02 / 17 min / 8 staged files / 11 GREEN bats / ZERO commits; recovery required orchestrator main-turn salvage. The clause is scoped to the cross-turn / turn-end-survivor shape and explicitly carves out the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem/the "bash until-loop with `pgrep -f 'bats --recursive'` self-references the polling loop's own command line — new variant of stuck-before-emit deadlock; SKILL.md prompt warning insufficient" problem-sanctioned *intra-turn* `run_in_background=true` + `BashOutput`-poll-then-`wait $bg_pid` idiom (which reaps before turn-end). RFC vehicle: the ": Forbid backgrounded-task launches inside `claude -p` AFK iter dispatch contexts" release design (`docs/rfcs/the ": Forbid backgrounded-task launches inside `claude -p` AFK iter dispatch contexts" release design-p370-forbid-backgrounded-task-launch-in-iter-dispatch.proposed.md`). Behavioural second-source: a promptfoo eval case in `eval/promptfooconfig.yaml` (`@problem the "Iter subprocess ends its turn waiting on a backgrounded task and never resumes — `claude -p` has no auto-resume; commit-bearing work is lost" problem`) asserting an iter-shape proposes no turn-end-survivor background fan-out — the "Behavioural-tests-default for skill testing" architecture rule behavioural-only (no structural bats), also discharges the ": Functional defects in shipped plugin behaviour" standing risk prose floor. Deferred follow-on (per the ": Forbid backgrounded-task launches inside `claude -p` AFK iter dispatch contexts" release design): codify the orchestrator main-turn salvage/recovery protocol as a mechanical sub-step.
|
|
1216
|
+
- **the "SIGTERM-clean-flush guarantee is conditional on subprocess having emitted ITERATION_SUMMARY before going idle — needs SKILL.md caveat + behavioural-test second-source for stuck-before-emit subclass" problem** (`docs/problems/147-p121-sigterm-clean-flush-guarantee-conditional-needs-skill-md-caveat-for-stuck-before-emit-subclass.verifying.md`) — refinement to the "AFK orchestrator should SIGTERM stuck `claude -p` subprocesses after idle-timeout — and SIGTERM appears to flush a clean JSON" problem's "clean exit-flush" claim. the "`docs/problems/README.md` drifts from filesystem truth across sessions despite (refresh-on-create) and (refresh-on-transition) both Closed" problem's evidence held only for subprocesses that had already emitted `ITERATION_SUMMARY` before going idle; the 2026-04-29 the "AFK iteration subprocess `bash until`-loop polls bats-output file with bats-console regex against TAP-format output — deadlocks indefinitely, manual SIGTERM required, JSON metadata lost" problem incident produced exit 143 + 0-byte JSON when SIGTERM fired before `ITERATION_SUMMARY` emission. Fix: SKILL.md prose now carries the conditional caveat (Step 5 "SIGTERM exit-flush is conditional, not universal" subsection) and adopters reading the prose are directed to treat exit 143 + 0-byte JSON as a metadata-loss event — verify work integrity from `git log` + `git status --porcelain`, halt the AFK loop, and reconstruct cost from the Anthropic billing dashboard. Behavioural second-source extends `test/work-problems-step-5-idle-timeout-sigterm.bats` with a stuck-before-emit fake-shim asserting `JSON_BYTES=0` after SIGTERM. Mechanism unchanged (SIGTERM remains the right recovery primitive); the refinement is documentation accuracy + the metadata-loss-event handling shape.
|
|
1217
|
+
- **the "Problem 089: work-problems Step 5 dispatch has two robustness gaps — stdin warning pollutes JSON output, and cost metadata undercounts when subprocess exits via background-task-notification ack" problem** (`docs/problems/089-work-problems-step-5-dispatch-robustness-stdin-warning-and-cost-metadata-edge-case.verifying.md`) — driver for Step 5's `< /dev/null` dispatch redirect and the Per-iteration cost metadata "Authority hierarchy" paragraph. Gap 1: stdin warning contaminated stderr-merged JSON captures; closed by adding `< /dev/null` to the canonical dispatch command. Gap 2: `.usage.*` undercounts when subprocess exits via a background-task completion ack while `.total_cost_usd` stays cumulative-authoritative; closed by documenting the authority hierarchy in Step 5 and the Session Cost output section so adopters trust cost and label token totals best-effort.
|
|
1218
|
+
- **the "Problem 086: AFK iteration subprocess does not run retro before returning — per-iteration lessons learnt are lost when the subprocess exits" problem** (`docs/problems/086-afk-iteration-subprocess-does-not-run-retro-before-returning.verifying.md`) — driver for Step 5's retro-on-exit clause. Iteration subprocesses exit without running retro, so per-iteration friction (hook misbehaviour, repeat-workaround patterns, pipeline instability) evaporates on exit. Fix: iteration prompt body names `/wr-retrospective:run-retro` as a closing step before `ITERATION_SUMMARY` emission; retro runs inside the subprocess so Step 2b pipeline-instability scan has the full tool-call history; run-retro commits its own work per the "Governance Skills Commit Their Own Completed Work" architecture rule; orchestrator picks up retro-created tickets on the next Step 1 scan.
|
|
1219
|
+
- **the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem** (`docs/problems/084-work-problems-iteration-worker-has-no-agent-tool-so-architect-jtbd-gates-block.open.md`) — driver for Step 5's subprocess-boundary dispatch. Supersedes the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem's Agent-tool dispatch on the same Step 5 surface because Agent-tool-spawned subagents cannot themselves invoke Agent (platform restriction), which prevents governance gate markers from being set inside the iteration worker.
|
|
1220
|
+
- **the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem** (`docs/problems/077-work-problems-step-5-does-not-delegate-to-subagent.verifying.md`) — parent amendment. Established the AFK iteration-isolation wrapper sub-pattern and the `ITERATION_SUMMARY` return contract. the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem is the refinement that swaps the spawn mechanism; the isolation intent and return contract are preserved verbatim.
|
|
1221
|
+
- **the "Problem 083: work-problems Step 5 iteration-worker prompt does not forbid ScheduleWakeup / time-deferring primitives — subagent can abandon synchronous-completion contract" problem** (`docs/problems/083-work-problems-iteration-worker-prompt-does-not-forbid-schedulewakeup.open.md`) — iteration prompt body forbids `ScheduleWakeup`. Applies equally to subprocess-dispatched iterations.
|
|
1222
|
+
- **the "Problem 036: work-problems orchestrator does not verify commit-landing between iterations" problem** — inter-iteration verification (Step 6.75); remains in the orchestrator's main turn.
|
|
1223
|
+
- **the "Problem 040: work-problems does not fetch origin before starting" problem** — origin-fetch preflight (Step 0); unchanged.
|
|
1224
|
+
- **the "`/wr-itil:work-problems` preflight Step 0 does not detect prior-session partial-work state (untracked ADRs, `.afk-run-state/iter-*.json` with 429/error statuses, existing `.claude/worktrees/*` branches)" problem** — session-continuity detection pass added to Step 0 after the fetch/divergence check. Enumerates five signals (untracked `docs/decisions/*.proposed.md`, untracked `docs/problems/*.md`, `.afk-run-state/iter-*.json` error markers, stale `.claude/worktrees/*` dirs, uncommitted SKILL.md/source/ADR edits). Routes interactive via `AskUserQuestion` with 4 options, AFK via halt-with-report per the "Structured User Interaction for Governance-Skill Decisions" architecture rule Rule 6.
|
|
1225
|
+
- **the "Problem 041: work-problems does not enforce release cadence" problem** — release-cadence drain (Step 6.5); remains in the orchestrator's main turn.
|
|
1226
|
+
- **the "Problem 053: work-problems does not surface outstanding design questions at stop-condition #2" problem** — Outstanding Design Questions surfacing at stop-condition #2 (Step 2.5); fed by the iteration subagent's `outstanding_questions` field.
|
|
1227
|
+
- **the "`/wr-itil:work-problems` stop-condition #2 defaults to the AFK Outstanding Design Questions table when AskUserQuestion is available — interactive users get no questions" problem** (`docs/problems/122-work-problems-stop-condition-2-defaults-to-afk-table-instead-of-asking-interactively.verifying.md`) — established the AskUserQuestion-default-when-available routing at Step 2.5. The routing prose (default branch, Rule 6 fallback, cross-skill principle, user-answerable scoping) was originally landed under Step 2.5; the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem moved it into the reusable Step 2.5b sub-step.
|
|
1228
|
+
- **the "`/wr-itil:work-problems` failure-handling halt paths bypass Step 2.5's interactive-default routing for accumulated user-answerable design questions" problem** (`docs/problems/126-work-problems-failure-handling-halt-bypasses-step-2-5-routing.known-error.md`) — extended the principle to every halt path that emits a final AFK summary. Step 2.5b is the single source of truth that Step 2.5, Step 0 (session-continuity + fetch-failure), Step 6.5 (Failure handling + Rule 5 above-appetite), and Step 6.75 (dirty-for-unknown-reason) all cross-reference. The principle: `halt-paths-must-route-design-questions-through-Step-2.5b`. Behavioural second-source: `test/work-problems-step-2-5b-cross-halt-routing.bats`.
|
|
1229
|
+
- **the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem** (`docs/problems/open/175-agent-over-narrows-scope-pin-words-into-count-constraints-halts-loop-on-agent-inferred-scope.md`) — driver for the **Scope-pin-word semantics** paragraph in the "Mid-loop ask discipline" subsection plus a brief forward-pointer at Step 7. Bug shape: when the user invokes `/wr-itil:work-problems just work the "Problem tickets strain as fixes decompose into multiple coordinated changes — need an RFC framework that ties all changes back to problems (and unifies technical with user/business problems)" problem` (or `only`/`first`/`merely`/`simply` paired with a ticket reference), the orchestrator over-narrows the natural-language modifier as a count constraint and emits `ALL_DONE` after iter 1 even when iter 1 returned `outcome: partial-progress` with named remaining slices AND no Step 2 stop-condition fired. Fix: SKILL.md prose classifies the scope-pin vocabulary as **selection override** (Step 1 WSJF override only); explicitly disclaims any loop-control effect; reminds that the Step 7 → Step 1 loop-back contract is unchanged and `ALL_DONE` is reserved for the framework-resolved stop surface per Step 2.4 gate (c). Inverse-direction sibling of the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem (the "`/wr-itil:work-problems` orchestrator defaults to subprocess dispatch even when the user is observably interactive — loses real-time presence advantage" problem is inverse-presence inference; the "Agent over-narrows scope-pin words ("just", "only", "first") into count constraints — halts AFK loop on agent-inferred scope rather than framework-prescribed stop conditions" problem is inverse-scope inference; both stem from agent over-inferring loop-control semantics the framework already resolved per the "— Decision-Delegation Contract: when agents act on the framework vs ask the user" architecture rule "Continue / stop loops"). Behavioural second-source: `eval/promptfooconfig.yaml` Tier-A regex + Tier-B llm-rubric asserting the orchestrator does NOT emit `ALL_DONE` after iter 1 on a scope-pin-word invocation with named remaining slices.
|
|
1230
|
+
- **the "Structured User Interaction for Governance-Skill Decisions" architecture rule** (`docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md`) — Rule 6 non-interactive fail-safe applies to every iteration-subagent decision surface.
|
|
1231
|
+
- **the "Governance Skills Commit Their Own Completed Work" architecture rule** (`docs/decisions/014-governance-skills-commit-their-own-work.proposed.md`) — preserved under the iteration subagent; the subagent commits its own work.
|
|
1232
|
+
- **the "On-Demand Assessment Skills for Governance Plugins" architecture rule** (`docs/decisions/015-on-demand-assessment-skills.proposed.md`) — Agent-tool-vs-Skill-tool delegation precedent (Step 6.5's wording mirror).
|
|
1233
|
+
- **the "Inter-iteration release cadence for AFK loops" architecture rule** (`docs/decisions/018-release-cadence.proposed.md`) — release cadence stays in the orchestrator's main turn, not the iteration subagent.
|
|
1234
|
+
- **the "AFK orchestrator preflight: get the repo into a clean state before starting" architecture rule** (`docs/decisions/019-afk-orchestrator-preflight.proposed.md`) — preflight stays in the orchestrator's main turn.
|
|
1235
|
+
- **the "Problem lifecycle — add a Verification Pending status between Known Error and Closed" architecture rule** (`docs/decisions/022-problem-verification-pending.proposed.md`) — iteration outcomes map into the return-summary's `outcome` field (`verifying` for a released fix, `known-error` for a root-cause-confirmed ticket awaiting release, etc.).
|
|
1236
|
+
- **the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule** (`docs/decisions/032-governance-skill-invocation-patterns.proposed.md`) — pattern taxonomy parent; Step 5 implements the AFK iteration-isolation wrapper — subprocess-boundary variant per the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem amendment (2026-04-21), refining the "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem Agent-tool amendment. The "Problem 077: work-problems Step 5 does not delegate iterations to a subagent, so context pressure accumulates in the orchestrator's main turn" problem amendment remains in the ADR as the historical Agent-tool variant; the subprocess variant is the lead for new adopters.
|
|
1237
|
+
- **the "Skill testing strategy — contract-assertion bats companion to" architecture rule** (`docs/decisions/037-skill-testing-strategy.proposed.md`) — doc-lint bats contract-assertion pattern used by `test/work-problems-step-5-delegation.bats`.
|
|
1238
|
+
- **the "work-problems orchestrator carries prior-ticket Fix Strategy text into iter dispatch without re-grounding in design intent" problem** (`docs/problems/known-error/211-work-problems-orchestrator-carries-prior-ticket-fix-strategy-text-into-iter-dispatch-without-re-grounding.md`) — driver for Step 5 iteration-prompt-body's "Re-ground per iter" orchestrator-side construction invariant. The bug shape (reported as inbound from downstream consumer bbstats as their the "ADRs accumulate forward-chronology evidence inline (Phase 2 dogfood evidence, amendment history, cross-iter cross-references) — `decisions` bucket dominates context at 41% / 1.3 MiB" problem): the orchestrator builds each iter's dispatch prompt by reading the target ticket's `## Fix Strategy` section and citing it verbatim into the subprocess prompt; across iterations, prior-ticket Fix Strategy text leaks into subsequent dispatches without re-grounding in the new ticket's design intent, and iters land fixes anchored on the wrong design rationale. Fix: SKILL.md Step 5's "Iteration prompt body" section now carries an explicit re-grounding paragraph (immediately after the "self-contained" opener) that (a) names the per-iter re-ground invariant against current-ticket-ID + title only, (b) forbids inlining `## Fix Strategy` verbatim into the dispatch prompt (the subprocess reads it from disk via `/wr-itil:manage-problem`), (c) names the cross-iter leakage class (prior ticket ID, prior Fix Strategy text, prior outcome reason, prior commit SHA, prior retro findings, prior outstanding-questions), (d) names the construction shape (template-driven, reset per iter, no global accumulator). Behavioural second-source: `test/work-problems-step-5-prompt-body-re-grounding.bats` (structural-permitted per the "Behavioural-tests-default for skill testing" architecture rule Surface 2; tdd-review comment in fixture cites the "Problem 012: Skill Testing Harness Scope Undefined" problem as harness-gap). Composes with the "Problem 084: work-problems iteration-worker has no Agent tool so architect + JTBD edit gates AND risk-scorer commit gate block all progress" problem (subprocess-boundary isolation — re-grounding is the symmetric orchestrator-side property of the subprocess's "no prior conversation context"), the "Governance skill invocation patterns — foreground + background with deferred-question resumption" architecture rule (AFK iteration-isolation wrapper — re-grounding clarifies the wrapper's isolation intent on the orchestrator side), the ": Progress the Backlog While I'm Away" user outcome (load-bearing — audit trail degrades if iters work the wrong ticket's design rationale).
|
|
1239
|
+
- **the "work-problems iter workers don't add changesets — fix commits accumulate without release" problem** (`docs/problems/known-error/206-work-problems-iter-workers-dont-add-changesets-fix-commits-accumulate-without-release.md`) — driver for Step 5 iter-prompt-body's explicit "if the fix changes shippable code, author a `.changeset/*.md` in the same commit" constraint (composes defence-in-depth with hook the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem's `git commit`-time enforcement). Inbound-reported by downstream consumer **bbstats** as their the "Briefing Tier 3 rotation repeat-deferral — 13 of 14 topic files over budget with 2 in MUST_SPLIT (≥2× ceiling) branch" problem (`**Origin**: inbound-reported (bbstats#195)` per the "Inbound-reported problems rank ahead of internally-discovered problems via a sort tier" architecture rule sort tier). Behavioural second-source: `test/work-problems-step-5-iter-changeset-required.bats` (structural-permitted per the "Behavioural-tests-default for skill testing" architecture rule; tdd-review comment in fixture).
|
|
1240
|
+
- **the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem** (`docs/problems/verifying/141-iter-prompt-time-reminder-misses-40-percent-of-publishable-iters-hook-level-enforcement.md`) — sibling hook (`packages/itil/hooks/itil-changeset-discipline.sh`) that enforces the changeset-discipline rule at `git commit` time. The Step 5 iter-prompt-body constraint composes-with this hook; the prompt-time rule is load-bearing because plugin-hook execution depends on the marketplace cache carrying the current hook version (a fresh-cache adopter without the "AFK iter `packages/<plugin>/` commits without changesets — orchestrator-main-turn back-fill is fragile recovery, hook-level enforcement preferable" problem still gets the constraint via the prompt).
|
|
1241
|
+
- **the ": Enforce Governance Without Slowing Down" user outcome**, **the ": Progress the Backlog While I'm Away" user outcome**, **the ": Keep Plugins Current Across Projects" user outcome**, **the "Extend the Suite with New Plugins" user outcome**, **the "Restore Service Fast with an Audit Trail" user outcome** — personas whose reliability expectations the iteration-isolation wrapper restores. the ": Progress the Backlog While I'm Away" user outcome (Progress the Backlog While I'm Away) + the ": Keep Plugins Current Across Projects" user outcome (Keep Plugins Current Across Projects) are the load-bearing pair for the "work-problems iter workers don't add changesets — fix commits accumulate without release" problem changeset-discipline constraint — the ": Progress the Backlog While I'm Away" user outcome requires the audit trail to stay accurate at release boundary; the ": Keep Plugins Current Across Projects" user outcome's closure depends on fixes actually shipping to npm.
|