Summary
Redesign the workflow agent check-in / stall-detection mechanism and step-completion validation shipped under #501/#506. A multi-agent critical review (full writeup in docs/technical/workflow-checkin-design-review.md, §"Redesign v2 — approved direction") found the as-built check-in non-functional and the akm-side LLM validation gate redundant. The owner has approved a concrete v2 direction. This issue tracks implementing it.
Why (verified defects)
Check-in is non-functional (~2/10). It is 100% pull-based: the only trigger for evaluateCheckin is the agent voluntarily running akm workflow next (src/workflows/runs.ts:227) — self-referential, so the one thing that can fire the stall check is the very thing whose absence is the stall. Plus:
- the promised "file-signal" check-in file is never written (zero
writeFileSync);
- when the directive does fire it is silently dropped by the default text formatter (
formatWorkflowNextPlain, src/output/text/helpers.ts:667);
akm workflow status does not evaluate check-in despite the ADR claiming it does;
- empirical: ~10 runs stuck
active/blocked, completedAt: null, never reaped.
LLM validation gate is redundant, not "mandatory/blocking". src/workflows/validate-summary.ts:85-124 is already fully fail-open (no key / offline / timeout / 429 / malformed → completes). The real problems are that it makes an akm-side LLM call at all (the driving agent is already a frontier LLM), a 120s foreground block, non-determinism on the sole blocking path, silent skips, and prompt-injection via the raw summary.
Approved v2 design
Owner constraints (locked): no external agent-harness hooks; no long-running OS service/daemon; akm makes no LLM call of its own.
A. Check-in → short-lived spawned monitor process
startWorkflowRun spawns a hidden akm workflow monitor <runId> via Bun.spawn(detached, unref) (reuse resolveAkmInvocation); AKM_NO_MONITOR=1 prevents the in-process test harness from forking; spawn failure non-fatal; one monitor per run via monitor_pid liveness.
- Poll loop ~60s reusing
evaluateCheckin/CHECKIN_STALL_MS; optional agent_pid kill(pid,0) liveness as an immediate-stall signal.
- Hard caps (≤240 polls / ≤4h wall) guarantee self-termination — never a daemon.
- On completion → exit. On stall → atomic
checkin.json + append workflow_run_events + idempotent guarded reap (UPDATE … WHERE status='active' AND checkin_armed_at=<value-read-this-tick>), so a late agent complete/next wins. Reap into the existing 'failed' status + terminal_reason='stalled' (no CHECK-constraint rebuild). On-command reapStaleRunsForScope + init reaping are the crash/reboot/Windows backstop.
B. Validation → delete the akm-side judge
- Delete
validate-summary.ts (+ buildDefaultSummaryJudge/summaryJudge) outright — remove the network seam.
- Only hard gate becomes a pure deterministic structural floor (non-empty, min length, criteria-keyword coverage, no placeholders) — works offline/CI by construction.
- Semantic judgment becomes an advisory agent self-review round-trip: akm emits an instruction for the agent to run an independent fresh-context review of its own changes and report back via
akm workflow complete --review-verdict pass|fail --review-notes "…" (recorded, not judged by akm). enforce=false default + maxRounds ⇒ a structurally-valid summary can always complete offline (anti-wedge).
Migration 004-monitor-and-validation (additive; 001–003 untouched)
workflow_runs += monitor_pid, agent_pid, last_seen_at, terminal_reason, checkin_path
- new table
workflow_run_events(run_id, session_id, kind, reason, at) + index
workflow_run_steps += review_requested_at, review_verdict, review_notes
Implementation sub-tasks (see doc §7)
Explicitly dropped (superseded by owner decisions): harness Stop-hook entry point, PostToolUse heartbeat hook, akm workflow reap cron job, tryLlmFeature-wrapped judge.
Supersedes the check-in/validation portions of #506.
Summary
Redesign the workflow agent check-in / stall-detection mechanism and step-completion validation shipped under #501/#506. A multi-agent critical review (full writeup in
docs/technical/workflow-checkin-design-review.md, §"Redesign v2 — approved direction") found the as-built check-in non-functional and the akm-side LLM validation gate redundant. The owner has approved a concrete v2 direction. This issue tracks implementing it.Why (verified defects)
Check-in is non-functional (~2/10). It is 100% pull-based: the only trigger for
evaluateCheckinis the agent voluntarily runningakm workflow next(src/workflows/runs.ts:227) — self-referential, so the one thing that can fire the stall check is the very thing whose absence is the stall. Plus:writeFileSync);formatWorkflowNextPlain,src/output/text/helpers.ts:667);akm workflow statusdoes not evaluate check-in despite the ADR claiming it does;active/blocked,completedAt: null, never reaped.LLM validation gate is redundant, not "mandatory/blocking".
src/workflows/validate-summary.ts:85-124is already fully fail-open (no key / offline / timeout / 429 / malformed → completes). The real problems are that it makes an akm-side LLM call at all (the driving agent is already a frontier LLM), a 120s foreground block, non-determinism on the sole blocking path, silent skips, and prompt-injection via the raw summary.Approved v2 design
Owner constraints (locked): no external agent-harness hooks; no long-running OS service/daemon; akm makes no LLM call of its own.
A. Check-in → short-lived spawned monitor process
startWorkflowRunspawns a hiddenakm workflow monitor <runId>viaBun.spawn(detached, unref)(reuseresolveAkmInvocation);AKM_NO_MONITOR=1prevents the in-process test harness from forking; spawn failure non-fatal; one monitor per run viamonitor_pidliveness.evaluateCheckin/CHECKIN_STALL_MS; optionalagent_pidkill(pid,0)liveness as an immediate-stall signal.checkin.json+ appendworkflow_run_events+ idempotent guarded reap (UPDATE … WHERE status='active' AND checkin_armed_at=<value-read-this-tick>), so a late agentcomplete/nextwins. Reap into the existing'failed'status +terminal_reason='stalled'(no CHECK-constraint rebuild). On-commandreapStaleRunsForScope+ init reaping are the crash/reboot/Windows backstop.B. Validation → delete the akm-side judge
validate-summary.ts(+buildDefaultSummaryJudge/summaryJudge) outright — remove the network seam.akm workflow complete --review-verdict pass|fail --review-notes "…"(recorded, not judged by akm).enforce=falsedefault +maxRounds⇒ a structurally-valid summary can always complete offline (anti-wedge).Migration
004-monitor-and-validation(additive; 001–003 untouched)workflow_runs+=monitor_pid, agent_pid, last_seen_at, terminal_reason, checkin_pathworkflow_run_events(run_id, session_id, kind, reason, at)+ indexworkflow_run_steps+=review_requested_at, review_verdict, review_notesImplementation sub-tasks (see doc §7)
validate-summary.ts)--review-verdict/--review-notes)akm workflow monitor <runId>)checkin.jsonsignal + idempotent reap +workflow_run_events004-monitor-and-validationExplicitly dropped (superseded by owner decisions): harness Stop-hook entry point, PostToolUse heartbeat hook,
akm workflow reapcron job,tryLlmFeature-wrapped judge.Supersedes the check-in/validation portions of #506.