2f09ad4a - Loosen error-fix ownership to device-level, add a one-shot decide dispatcher - #55
Conversation
…vel and add a one-shot error-decide dispatcher.
…spatch race found in review.
…fast when a knock is rejected.
…rting the whole scan, and refresh the skill and design docs to match.
…t was cleaning up after.
1fb847b to
badabfa
Compare
…g used elsewhere in the same section.
…runcating error ids in decide session names.
…emoving id truncation, and lock the format down with a test.
… failure from hiding a real conclusion, and let a closed decide session be reopened.
… idle wait does not stall on a real 60-second timeout.
…ept clause a few lines down.
…rief field on the error-fix executor path too.
…d give the decide-dispatcher test fixture a brief field too.
…the new payload requirement.
|
EN: DE: DetailsGrok-PR (quality + logic, 14 passes to 0/0)Findings fixed across the run: fresh-session skill gaps making implement tasks unreachable via Codex-PR (quality + logic, cross-vendor gate, 4 rounds to 0/0)Findings fixed: Every fix was pushed to the same PR and re-run through both vendors at the new head until each reported zero findings; no finding was accepted or dismissed without independent verification against the actual code. |
|
EN: Before merging, check compatibility with existing error.fix producers and pending records: brief becomes mandatory on both the write and execution paths, so older pending conclusions without it will be rejected. Define how those records and producers are updated. Also keep the rollout scope clear: this PR adds the one-shot command; it does not wire it into the daemon. |
EN:
Loosens error-fix conclusion/implement-task ownership from session-exact to device-level, adds
agent watch error-decide(a one-at-a-time dispatcher that starts a fresh, one-shot session per unresolved error, instead of relying on a single persistent session), and requires abrieffield onerror.fixconclusions.DE:
Lockert die Besitz-Prüfung für error-fix-Konklusionen/Implement-Tasks von session-exakt auf Device-Ebene, fügt
agent watch error-decidehinzu (ein Ein-nach-dem-anderen-Dispatcher, der pro offenem Fehler eine frische Einmal-Session startet, statt auf eine dauerhafte Session zu setzen), und macht einbrief-Feld auferror.fix-Konklusionen verpflichtend.Details
Why
The existing
error-fixskill's single-persistent-session model has no mechanism to auto-continue between queued items — each session does one thing, then sits idle until manually re-knocked. Rather than build that "keep it going" nudge, this drops the persistent session entirely: a fresh, uniquely-named session is started per error, does its one job (investigate, conclude), and stops.What changed
src/agent_cli/error_fix_act.py,src/agent_cli/errors.py:_error_seen,_lookup_implement_task,incident_closed,validate_conclusionall dropped theirsession_idparameter/filter, keeping only device-level (_origin_device_id) ownership checks. Necessary because a fresh one-shot session writes the conclusion under its own session id, different from theerror.seenrow's session id (the fixed scanning session named inerror-fix.json).src/agent_cli/error_decide_act.py(new) +main.py:agent watch error-decidedrains unconcludederror.seenrows oldest-first (bypayload.first_seen), one at a time, inside a lock held for the whole scan so overlapping invocations can't double-dispatch the same row. Per row: ensures a runner session (skillserror-fix,spine,review-loop,pr-review; reused and reopened on retry rather than re-created), waits for the pane to read as idle on two consecutive checks before knocking directly (not viaknock.deliver, which would target the wrong session), retries the Enter keypress with anis_busy()confirmation, polls for the conclusion with a timeout, then always stops the pane. A row's own setup/knock/stop failures (StoreError/SystemExit/OSError) are recorded as that row's outcome without aborting the rest of the backlog, and a failure while stopping a pane can never overwrite a realdecided/timeoutresult. Not wired intoagent daemonin this revision.validate_conclusionrequires abrieffield onerror.fix(short text: what's broken, likely cause, where to look), matching the existingreasonrequirement onerror.skip; the same check now also runs on the executor's read path (_pending_fix), not just at write time.DESIGN.md§21 and theerror-fixskill'sSKILL.mdupdated to match throughout.Verification
Full local suite: 714 passed, 1 pre-existing unrelated skip (missing optional
agent_corepackage). Ran the actual dispatcher twice against a real, isolated Postgres store and a real grok session (not the repo's own store) — confirmed a realerror.seenrow gets picked up, investigated, and concluded with a realerror.skip, the knock lands without manual intervention, and the session is cleanly stopped afterward.