Context
src/api.ts:1530 has a long-standing TODO from Akari (P1):
// TODO (Akari P1): no replan loop for phase 2 failures — add brainDigest→replan in future
When a phased accomplish call's Phase 2 planEngine.execute() rejects, we currently:
- Log the error
- Mark the Phase 2 plan as completed (cleanup)
- Schedule the entry for deletion after 1h
- Fall back to returning the Phase 1 result as if Phase 2 didn't happen
The Phase 1 wait-mode path (src/api.ts:1571-) does honor MAX_REPLAN_ROUNDS = 3 with brainDigest-driven replan. Phase 2 doesn't. This is a behavioral asymmetry.
What "done" looks like
- Phase 2 failures trigger up to
MAX_REPLAN_ROUNDS replan attempts via brainDigest, mirroring the Phase 1 flow
- Each replan attempt is persisted via
persistPlanHistory with a discriminating event (e.g. replan-attempted)
- A test exercises the failure → replan → success path and the failure → replan-exhausted path
Why P1, not P0
Caller still gets some result (Phase 1's), so the system isn't broken — just under-recovering on multi-phase goals. Surface area is one branch; the fix is bounded.
Acceptance
- TODO comment removed, replaced with link to this issue
- Behavior parity test added in
tests/api.phased.spec.ts (or nearest existing suite)
- No regression in current Phase 2 success path
Context
src/api.ts:1530has a long-standing TODO from Akari (P1):When a phased accomplish call's Phase 2
planEngine.execute()rejects, we currently:The Phase 1 wait-mode path (
src/api.ts:1571-) does honorMAX_REPLAN_ROUNDS = 3with brainDigest-driven replan. Phase 2 doesn't. This is a behavioral asymmetry.What "done" looks like
MAX_REPLAN_ROUNDSreplan attempts via brainDigest, mirroring the Phase 1 flowpersistPlanHistorywith a discriminating event (e.g.replan-attempted)Why P1, not P0
Caller still gets some result (Phase 1's), so the system isn't broken — just under-recovering on multi-phase goals. Surface area is one branch; the fix is bounded.
Acceptance
tests/api.phased.spec.ts(or nearest existing suite)