Repository navigation
A judged-wide /task whose division the reviewer refuses loses the divide verb for the rest of its run #958
Description
What happened
A /task whose width the sizing judge says is wide can end up with a worker that has no way to divide at all, where before #936 that same task ran with the divide_work verb on its belt.
The judge's yes used to arm the node at admission (rememberDivisible → armDivision), which put divide_work on the worker's belt and prompts/divide.md in its system prompt for the whole run. Since #936 the judge reads the request beside the worker and its parts are submitted as a division through the #883 road. spec.armed is left frozen at admission, because the belt and the prompt are built from it when the worker is constructed (Config.mayDivide → TaskNode.dividing) and a late arming would leave the two disagreeing.
So on this branch:
- judge says wide → the division is proposed → the reviewer refuses it → the worker carries on with no
divide_workverb and no divide prompt, and cannot hand out parts later even when it has opened the material and can see them. - On dev, the same run had the verb for the rest of the task.
The node's own text can still arm it (enumeration in the brief, armDivision's ordinary road), so this is only the branch where the JUDGE was the sole source of width.
Replication
Deterministic (no model). Base: dev with #950 merged.
go test -count=1 -run TestAWideTaskStartsItsWorkerFirstAndTheJudgesPartsArriveAsTheReceipt ./internal/session/
That test asserts today's behaviour: spec.armed == "" after a judged-wide start. Drive the same shape with a division reviewer that REFUSES (the besideCompleter in internal/session/task_divide_sketch_test.go, answering the review call with a no) and assert on the worker's config: Config.mayDivide() is false and divide_work is not on the belt, for a request the judge called wide. On dev the equivalent node is armed judged and has the verb.
Field (real models). OPENROUTER_API_KEY, a few cents, ~2 minutes:
aforge chat # then: /task port the nine codec adapters to the new interface, one file each
Watch the task room. It fires whenever the judge says wide and the division reviewer then refuses the parts — most often when the parts it names are thin.
Where
internal/session/task_divide.go—Config.mayDivide,TaskNode.dividing,Agent.armDivision(searcharmedByJudgement).internal/session/task_divide_sketch.go—Agent.proposalBeside,judgedDivision,askedByJudge.internal/session/prompt.go—renderSystemAtreadsmayDividewhen the worker is built and onclockRefresh.internal/session/task_person.go—StartTaskfreezesspec.armedat admission (/task waits 28 s on a sizing judge and a shaper that both run out their windows before the task exists #936).
The fix
A worker whose width was judged wide keeps the ability to divide for the rest of its run, whatever the reviewer says about the FIRST set of parts. The reviewer's no is a judgement about those parts, not about whether the work can ever be split.
That means arming has to stop being frozen-at-construction, or the belt and the prompt have to be able to gain the verb mid-run without disagreeing: one door that arms the node AND re-renders the system prompt and rebuilds the belt for the running worker, in one step, under the same lock. Anything less reintroduces the belt/prompt disagreement #936 refused to create.
Pick one and say so in the change entry: (a) a mid-run arm door that re-renders both, or (b) arm every unsized /task at admission and let the reviewer be the only gate — which costs the prompt's divide section on every typed task.
Acceptance
- e2e: through the real
/taskdoor with a stub provider (internal/session, the besideCompleter road): a judged-wide task whose division the reviewer refuses still hasdivide_workon its worker's belt, and the worker's system prompt still carries the divide section, on the step after the refusal. - e2e: the control — a task nobody called wide, whose brief enumerates nothing, still has no
divide_workverb and no divide section, so the fix does not arm everything. - Unit: a structural law that the belt and
renderSystemAtread the same predicate, so the two cannot be rebuilt from different answers. - The manual page covering division (
internal/manual/chat/tasks.md) quotes the resulting wording, and the change entry'sinvalidatesnames what /task waits 28 s on a sizing judge and a shaper that both run out their windows before the task exists #936 left true.
Found in review of #950 (issue #936). Quality-law record: this is the one branch where #936 trades a capability for the start latency, and it is written down rather than absorbed.
Drafted with CodeAF · reviewed and owned by the author
Activity
task: the two readings a /task still owes survive the checkpoint (#936)
task: the two readings a /task still owes survive the checkpoint (#936)
task: the two readings a /task still owes survive the checkpoint (#936)
task: the two readings a /task still owes survive the checkpoint (#936)
task: the two readings a /task still owes survive the checkpoint (#936)
task: /task starts at once; the brief and the width are read beside i…
changes: the entry for #958
A refusal is about the parts, not the width: the judge that reads a t…