What happened
builder-spir-52 (SPIR, 4 phases, --harness opencode --model xai/grok-4.6) hit porch's context-refresh task at the phase_1 → phase_2 boundary and reported:
Context refresh refused at plan-phase:phase_2: harness opencode has no in-session reset. Continuing into phase 2.
That refusal is correct behaviour — afx refresh documents that it requires a harness with in-session context clearing and aborts loudly otherwise. The problem is what happens next.
Why it matters
Porch emits refresh tasks at phase boundaries because a multi-phase SPIR is expected to exhaust a context window. On Claude that is handled. On opencode it is not, and the protocol continues anyway, so the run proceeds with no mechanism to reclaim context and no plan for what happens when it runs out.
The recovery options are all blocked or unhelpful:
afx spawn <id> --resume reattaches the same conversation, so it does not help with exhaustion — that is exactly what afx refresh exists for.
afx cleanup + respawn is explicitly forbidden (irreversible-acts rule; it destroys the worktree).
- So the only real fallback is a human decision, on a run that may be hours deep.
This matters more now rather than less: opencode is the lane you reach for when the Claude account is constrained, which means the longest, least-supervised runs are the ones most likely to be on the harness with no recovery path.
What I did as mitigation
Told the builder to commit and push at every phase boundary and keep codev/state/spir-52_thread.md current enough for a stranger, on the reasoning that a pushed branch and an honest thread log are the only artifacts that survive the builder. That is a workaround, not a fix, and it depends on the builder complying while its context is already degrading.
Options worth considering
- Refuse at spawn, not at the boundary. If a protocol has more than N phases and the harness has no in-session clear, say so at
afx spawn time when the choice is still free, rather than mid-run when it is not.
- A supported handoff. A way to end one builder and start a fresh one on the same worktree and branch, carrying the thread log, without destroying anything. This is the missing primitive:
--resume keeps the conversation, cleanup destroys the worktree, and nothing keeps the work while dropping the conversation.
- Warn loudly at the first refused refresh rather than logging and continuing, so the architect knows the run is now unprotected.
Option 2 looks like the real fix. Options 1 and 3 are cheap and would have surfaced this before a four-phase run was underway.
Found while running spec 52 (#52) on opencode.
What happened
builder-spir-52(SPIR, 4 phases,--harness opencode --model xai/grok-4.6) hit porch's context-refresh task at the phase_1 → phase_2 boundary and reported:That refusal is correct behaviour —
afx refreshdocuments that it requires a harness with in-session context clearing and aborts loudly otherwise. The problem is what happens next.Why it matters
Porch emits refresh tasks at phase boundaries because a multi-phase SPIR is expected to exhaust a context window. On Claude that is handled. On opencode it is not, and the protocol continues anyway, so the run proceeds with no mechanism to reclaim context and no plan for what happens when it runs out.
The recovery options are all blocked or unhelpful:
afx spawn <id> --resumereattaches the same conversation, so it does not help with exhaustion — that is exactly whatafx refreshexists for.afx cleanup+ respawn is explicitly forbidden (irreversible-acts rule; it destroys the worktree).This matters more now rather than less: opencode is the lane you reach for when the Claude account is constrained, which means the longest, least-supervised runs are the ones most likely to be on the harness with no recovery path.
What I did as mitigation
Told the builder to commit and push at every phase boundary and keep
codev/state/spir-52_thread.mdcurrent enough for a stranger, on the reasoning that a pushed branch and an honest thread log are the only artifacts that survive the builder. That is a workaround, not a fix, and it depends on the builder complying while its context is already degrading.Options worth considering
afx spawntime when the choice is still free, rather than mid-run when it is not.--resumekeeps the conversation, cleanup destroys the worktree, and nothing keeps the work while dropping the conversation.Option 2 looks like the real fix. Options 1 and 3 are cheap and would have surfaced this before a four-phase run was underway.
Found while running spec 52 (#52) on opencode.