Skip to content
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ All notable changes to codexclaw are documented here. The format follows

## [Unreleased]

### Fixed

- Subagent waiting guidance instructed coordinators to retire workers after
about three empty waits, even when analysis could still be progressing.
`waiting.md` now requires evidence of progress or stagnation, preserves
unavailable observations, and uses non-interrupting checkpoints. Delegation
and DISPATCH-RETIRE-01 clarify actual shutdown checks and managed recovery;
cancellation or exhausted limits grant no retry or replacement. Progress
assessment remains agent-followed (#178).
- Managed dispatch now accepts explicit `task_failed` reports for confirmed
stagnation or unusable final output. A recorded stopped child, task evidence
and reconciliation are required before the existing bounded handoff can run.
Provider errors keep their existing classification; cancellation and permission
denials cannot be overridden by a task-failure label (#178).

## [0.2.28] - 2026-09-14

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-3%2C150_passing-brightgreen" alt="3,150 tests passing">
<img src="https://img.shields.io/badge/tests-3%2C165_passing-brightgreen" alt="3,165 tests passing">
<img src="https://img.shields.io/badge/skills-29-blue" alt="29 skills">
<img src="https://img.shields.io/badge/hooks-28-blue" alt="28 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-3%2C150_passing-brightgreen" alt="3,150 tests passing">
<img src="https://img.shields.io/badge/tests-3%2C165_passing-brightgreen" alt="3,165 tests passing">
<img src="https://img.shields.io/badge/skills-29-blue" alt="29 skills">
<img src="https://img.shields.io/badge/hooks-28-blue" alt="28 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
2 changes: 1 addition & 1 deletion README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<p align="center">
<a href="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml"><img src="https://github.com/lidge-jun/codexclaw/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<img src="https://img.shields.io/badge/tests-3%2C150_passing-brightgreen" alt="3,150 tests passing">
<img src="https://img.shields.io/badge/tests-3%2C165_passing-brightgreen" alt="3,165 tests passing">
<img src="https://img.shields.io/badge/skills-29-blue" alt="29 skills">
<img src="https://img.shields.io/badge/hooks-28-blue" alt="28 hooks">
<a href="https://lidge-jun.github.io/codexclaw/"><img src="https://img.shields.io/badge/docs-codexclaw-black" alt="Documentation"></a>
Expand Down
101 changes: 101 additions & 0 deletions devlog/_fin/260915_subagent_retirement/000_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Require evidence before retiring a subagent

An executor can still be investigating while its working tree is clean. Issue
[#178](https://github.com/lidge-jun/codexclaw/issues/178) records a worker stopped
seconds after a successful read. This unit replaces the wait-count heuristic with
an activity-based decision procedure in the existing waiting reference. It also
keeps repeated busywork, explicit limits and safe handoff in view.

## Scope and completion

- Class C2; one satisfy-spec PABCD work-phase, `wp1`.
- Trigger: implement #178 and open a linked pull request.
- Goal: a coordinator can distinguish slow progress, suspected stagnation,
confirmed failure and unavailable observations before deciding to retire.
- Out: runtime watchdogs, provider retries, new configuration/schema fields,
installed-payload changes, merge, release and deployment.
- Tools: local Git/source reads, native V1 subagents, existing checks and GitHub
branch/PR publication. Writes stay in this task's linked worktree and native
session evidence. No user token/cost/wall-clock budget was specified; preserve
explicit limits when present and do not invent a universal timeout.
- Verifier: the baseline commands below plus independent semantic review of
[the scenario matrix](010_policy.md#acceptance-scenarios).
- Stop: close the cycle with verified text and publish an ordinary PR to `dev`.
DONE requires a linked PR and accurate check results; unmet evidence stays
incomplete. Host limits or cancellation are reported as such, never success.
- Memory artifact: this unit, then its `_fin/` archive; raw consultation/dispatch
handles and receipts remain in untracked native session evidence.
- Escalation: main resolves scope/judgment gaps. A new worker handoff requires a
plan amendment. Retirement and replacement follow managed dispatch results;
`reconcile`/`stop` never authorize direct work or another spawn.

## Existing owners and baseline

`plugins/codexclaw/skills/loop/references/waiting.md:31-35` retires after about
three waits. `structure/20_pabcd_dispatch_doctrine.md:181-195` includes bare
timeout among failure reasons. The V1 table in
`plugins/codexclaw/skills/pabcd/references/delegation.md:133` calls a wait timeout
a normal outcome. The waiting reference already owns the shared decision rule;
the other files should point to it rather than copy a second classifier.

Verified on upstream `dev` at `03541398` before edits:

| Command | Result | What it observes |
| --- | --- | --- |
| `npm run gate` | exit 0 | `gate.mjs` scans skill references and `structure/*.md` for claim hygiene and checks inventory; not retirement semantics |
| `node plugins/codexclaw/scripts/test.mjs plugins/codexclaw/test/manifest-policy.test.mjs` | 7 pass, 0 fail | existing owner-route resolution includes `waiting.md`; not model behavior |

No phrase-presence test or unused decision helper will be added. They would test
the wording or a second implementation that the coordinator never executes
(`dev-testing` TEST-PROMPT-SEAM-01). The source is agent-followed E7 guidance;
execution surface: main's judgment; bypass: ignore/misread it; residual: model
variance and missing observations; final enforcement layer: none.

## Architect consultation and main decisions

The native V1 architect proposed D1-D5 from the owner files. Its initial proposal
included phrase tests; its revised proposal withdrew them after the existing
testing rule was supplied. Actual handle, proposal and reflection are retained
with this session's dispatch evidence, outside published project documents.

| Decision | Main disposition |
| --- | --- |
| D1 trigger taxonomy | Accept with amendment: a confirmed stop/cancel is not automatically a provider failure. Separate wait timeout, terminal error and evidenced stagnation. |
| D2 activity evidence | Accept with amendment: new reads or command events are candidate evidence only when they advance the packet. Repeated reads/messages prompt investigation, not an automatic new count threshold. |
| D3 checkpoint | Accept: use supported non-interrupting delivery, explain queued-input limits, request findings/remaining work/next artifact. Reviewers report next review result, not a forced first edit. |
| D4 retirement evidence | Amend: record decision before stop; verify terminal state and owned processes after stop. A returned *previous* `running` status does not prove termination. Preserve managed fallback gates. |
| D5 observation and proof | Accept revised semantic review. No assumed access to child rollouts. Do not link installed skills to repository-only devlogs. |

No-code alternatives: doing nothing retains the contradiction; merely lengthening
three waits still mistakes elapsed observations for failure; a runtime helper has
no existing consumer and expands this change. Reuse the current protocol owners.

Reflection of this concrete plan: ALIGNED on D1-D5, with the named main
amendments accepted. Independent A audit: PASS, no blockers. S3 now explicitly
permits retirement only after stagnation is evidenced; the canonical recovery
rule must also govern shorthand references such as `plan-output.md:18`.

## Change ownership

The executor owns the four bounded source-document edits listed in
[010_policy.md](010_policy.md). Main owns this plan, semantic acceptance decisions,
consultation records, final review/integration, checks and publication. One commit
may carry the coherent document fix; follow repository `[agent] fix(...)` style.
No branch stacking is needed. Preserve unrelated local integration work.

## Delivery conclusion

The four document edits are implemented. The final independent reviewer derived
all twelve intended actions from the policy without seeing expected answers;
its initial and focused follow-up verdicts were PASS. The existing gate, seven
owner-route tests and whitespace check passed. See
[011_verification.md](011_verification.md) for scope and limits.

The chosen hypothesis was that clearer evidence requirements can prevent the
observed premature retirement. This unit does not measure model compliance;
there is no basis for claiming faster execution or a runtime guarantee. A
watchdog and phrase-presence tests were rejected because neither would verify
the coordinator behavior without a real runtime consumer.

Delivery stops at a reviewed contribution to upstream `dev`, linked to #178.
No merge, release, deployment or installed-payload update is part of this unit.
63 changes: 63 additions & 0 deletions devlog/_fin/260915_subagent_retirement/010_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# wp1: Change the retirement decision at its existing owners

Depends on `000_plan.md` D1-D5. One C2 work-phase; no production code or new types.

## Exact edit map

| File | Before | After | Owner |
| --- | --- | --- | --- |
| `plugins/codexclaw/skills/loop/references/waiting.md` | final bullet retires after about three waits | Replace that bullet with compact progress/checkpoint/retirement sections. Keep existing peer boundary and V1/V2 wait visibility. | executor |
| `structure/20_pabcd_dispatch_doctrine.md` | DISPATCH-RETIRE-01 treats bare timeout as failure and implies unconditional replacement/reclaim | Refer to waiting's evidence rule; qualify timeout as actual terminal error only; keep bounded recovery but defer managed replacement/reclaim to protocol result. | executor |
| `plugins/codexclaw/skills/pabcd/references/delegation.md` | wait route and normal-timeout table; generic failure recovery | Clarify non-interrupting checkpoint delivery and timeout observation. Preserve transport schemas and existing first-fallback gates. | executor |
| `CHANGELOG.md` | empty Unreleased | One concise Fixed entry for #178, explicitly agent-followed guidance. | executor |

The waiting rule must distinguish substantive progress, suspected stagnation,
confirmed failure and unavailable observation. Refresh task-scoped observations
just before retiring. Liveness alone and file timestamps alone do not prove
semantic progress; no edits alone do not prove a stall. A healthy long command
may have sparse output and must be inspected before cancellation.

For suspected stagnation, request one non-interrupting checkpoint where supported,
then compare new evidence with the prior observation at a stated, task-appropriate
next review point. Repeated/no-op work must not reset that review point forever.
That review point is not a new cancellation budget. An unread queued message and
silence with missing visibility do not confirm a stall. If an opaque task cannot
be assessed within authorized limits, report the observation gap and seek direction
without claiming failure or silently replacing it.

Explicit cancellation, actual terminal failures and stated user/host resource
limits take precedence over progress. Keep cancellations/exhausted limits separate
from provider errors. Record pre-stop reason and last meaningful activity, then
post-stop terminal state, owned processes/partial edits, retained results and
remaining work. If termination is unknown, no overlapping writer may be started.
Managed `ready` requires a new claim; `main-direct` permits reclaim;
`reconcile`/`stop` permit neither. Never manufacture an OCX error code for a stall.

## Acceptance scenarios

These are semantic review cases, not executable runtime tests. A fresh C reviewer
must derive actions from the final policy and name ambiguities before acceptance.

| ID | Activation | Expected observable decision |
| --- | --- | --- |
| S1 | Four waits, no edits, nine meaningful reads; last read seconds ago | keep active; no retirement from polls/clean Git |
| S2 | A long build is running with sparse output and no expired limit | inspect command state; sparse output alone cannot retire |
| S3 | Same unchanged reads/status repeatedly; delivered checkpoint and later comparable observations show no advancement | eligible to retire once stagnation is evidenced at the stated review point; repeats alone only prompt investigation |
| S4 | No child log access; clean Git; checkpoint may still be queued | observation unavailable; no invented failure or unanswered-message deadline |
| S5 | Native V2 wait reports updates without final text | obtain the separately delivered answer before judging |
| S6 | Actual terminal error | preserve original error and use managed failure/reconciliation path |
| S7 | User cancels or an explicit resource bound expires despite progress | stop within authority; report cancellation/bound, not provider failure |
| S8 | Stop call returns previous status `running` | verify current terminal state and owned jobs before handoff |
| S9 | Failure report returns `reconcile` or `stop` | neither direct implementation nor replacement spawn |
| S10 | New irrelevant reads or identical heartbeats keep arriving | liveness only; do not postpone reassessment forever |
| S11 | Reviewer produces no files while making new findings | treat review artifacts as progress; never require an edit |
| S12 | Finished child still has a queued checkpoint response/turn | reconcile actual current status; a checkpoint request is not permission to duplicate work |

## Verification and delivery

Run `npm run gate`, the existing manifest-policy test command in `000_plan.md`,
and `git diff --check`. Review links and all active retirement-rule references.
The first two checks already ran successfully at baseline; whitespace check is
mechanical only. No typecheck/build is claimed for prose. Record per-scenario
review and limitations in `011_verification.md`, archive this unit at completion,
and publish an ordinary fork PR to upstream `dev` with `Closes #178`.
Loading
Loading