fix(delivery): record previous_assignee on needs_input escalation too - #47
Conversation
spec 027 mandates previous_assignee on every assignee-clear event. The retry-vs-escalate fix (v0.81.2) stamps it on cap-exhaustion only; the needs_input path (task-wrong, permanent) cleared assignee without the stamp, so the operator inbox couldn't show which agent parked the task. Both deliverer paths now record the pre-clear owner on needs_input too.
There was a problem hiding this comment.
I have all the information I need. Let me compile the consolidated report.
PR Review: fix(delivery): record previous_assignee on needs_input escalation too
Target: master ← fix/needs-input-prev-assignee (c547039)
Verdict
approve — the bug fix is correct, well-tested, and the new tests verify the exact contract change. All three concerns from the plan are resolved. The remaining findings are pre-existing violations unrelated to this PR, or mechanical-tool false positives.
Must Fix (Critical)
None — no new critical issues introduced by this PR.
Should Fix (Important)
None — no new important issues introduced by this PR.
Nice to Have (Optional)
None.
Pre-existing Issues (not introduced by this PR, but visible in the diff)
The mechanical funnel surfaced real violations that pre-exist this PR in result-deliverer.go. Flagging them for visibility, not as blocking this PR:
delivery/result-deliverer.go:128—for k, v := range fmMaploop has noctx.Done()check. Cancellation mid-loop (e.g. during a slow iteration if the map grows) would not abort early. (rule:go-context/cancel-check-in-loop)delivery/result-deliverer.go:116—DeliverResultfunction iterates the frontmatter map and callsapplyResultFrontmatterwithout a ctx.Done() guard between iterations. (rule:go-functional-composition/list-checks-ctx-done)delivery/result-deliverer.go:18—github.com/golang/glogimport. This project is mid-migration; if glog is being phased out, theglog.V(2).Infofat line 165 andglog.Warningfat line 226 are candidates. (rule:go-cli/slog-not-glog-in-new-projects)
Mechanical Funnel False Positives (for traceability)
The following findings from the ast-grep run are incorrect — do not flag as issues:
delivery/content-generator.go:17— The//counterfeiter:generatedirective is present on line 14 of the same file. The scanner reported line 17 (the interface body start) but the directive is 3 lines above it. No action needed.delivery/result-deliverer_test.go:77,113,115,132,152,177,203,…— Allno-bare-error-callviolations on*.Returns(...)mock calls. Counterfeiter-generated mock methods return only(...)— there is no error to check. These are all false positives from the errcheck rule.delivery/*_test.gosuite-test-file-requiredfindings — The companiondelivery/delivery_suite_test.goexists and registersRunSpecs(t, "Delivery Suite"). Ginkgo discovers specs across all files in the package; no missing suite.
Plan Concern Resolution
| Concern | Resolution |
|---|---|
correctness — content-generator.go: order of previous_assignee before assignee clear |
✅ Confirmed: lines 78–81 set previous_assignee before clearing assignee, matching the cap-exhaustion path at lines 96–99 |
correctness — result-deliverer.go: AgentStatusNeedsInput stamps previous_assignee before clearing |
✅ Confirmed: lines 217–220 do previous_assignee before assignee = "", identical order to content-generator.go |
correctness — result-deliverer.go: assignee/previous_assignee initialized from incoming frontmatter before stamp/clear |
✅ Confirmed: frontmatter is built from fmMap (copied from generator output) at lines 128–131, so the stamp reads from the same source as the content-generator path |
Notes
- The bug fix is minimal and targeted:
needs_inputnow stampsprevious_assigneebefore clearingassigneein both the content-generator and kafka-deliverer paths, matching the cap-exhaustion behavior from v0.81.2. - New tests cover the case where an assignee is present (
previous_assigneerecorded) and when no assignee is present (no spurious empty stamp — both paths guard withif prev != ""/if prev != ""). - The
AgentStatusNeedsInputbehavior is now:status: in_progress,assignee: "",previous_assignee: <prior-owner>,phasepreserved. This is consistent across file and Kafka deliverers.
{
"verdict": "approve",
"summary": "Bug fix is correct and well-tested. Both deliverer paths (content-generator and kafka-result-deliverer) now record previous_assignee before clearing assignee on needs_input, matching the cap-exhaustion behavior from v0.81.2. New tests verify both the with-assignee and without-assignee cases. The plan concerns are all resolved. Remaining findings are pre-existing violations or mechanical-tool false positives.",
"comments": [
{
"file": "delivery/result-deliverer.go",
"line": 128,
"severity": "minor",
"message": "for k, v := range fmMap loop has no ctx.Done() check — cancellation mid-iteration would not abort early. Pre-existing issue, not introduced by this PR. (rule: go-context/cancel-check-in-loop)"
},
{
"file": "delivery/result-deliverer.go",
"line": 116,
"severity": "minor",
"message": "DeliverResult function iterates frontmatter without ctx.Done() between iterations. Pre-existing issue. (rule: go-functional-composition/list-checks-ctx-done)"
},
{
"file": "delivery/result-deliverer.go",
"line": 18,
"severity": "nit",
"message": "Uses github.com/golang/glog instead of log/slog. Pre-existing. (rule: go-cli/slog-not-glog-in-new-projects)"
}
],
"concerns_addressed": [
"correctness: content-generator.go order of previous_assignee before assignee clear — addressed: lines 78-81 set previous_assignee before clearing assignee",
"correctness: result-deliverer.go needs_input stamps previous_assignee before clearing — addressed: lines 217-220 match content-generator.go order",
"correctness: assignee and previous_assignee fields initialized from incoming frontmatter before stamp/clear — addressed: frontmatter built from fmMap at lines 128-131, stamp reads same source as content-generator path"
]
}
spec 027 mandates
previous_assigneeon every assignee-clear event. The retry-vs-escalate fix (v0.81.2, #46) stamps it on cap-exhaustion only; theneeds_inputpath (task-wrong, permanent — e.g. "no date range", "zero trades") clearedassigneewithout the stamp, so the operator inbox couldn't show which agent parked the task.Fix: both deliverer paths (Kafka + file) now record the pre-clear owner on
needs_inputbefore clearingassignee.needs_inputstays an immediate escalation (agent already did the work, retry can't help); this only adds the query-ability stamp.Tests: needs_input with an incoming owner records
previous_assignee+ clearsassignee, for both deliverers.make precommitgreen (0 lint issues).