task_update stored any string as a task's status, so an agent writing
"complete" left a finished task every reader misread: the ruflo-console
Automation kanban listed it under PENDING (offering assign/cancel), and
Mission Control derived it as ready, so nextTask() would hand finished work
to Claude again as a new billed turn.
CLI (mcp-tools/task-tools.ts)
- statusOf(): trimmed, case-insensitive, aliases complete/done/canceled/
running/in-progress; anything else (incl. "" and prototype keys) is
refused with the allowed list and the task is left unchanged.
- No schema enum on purpose: the HTTP/WebSocket registry validates enums
before the handler, which would refuse aliases there but not over stdio.
- Completing through task_update now finishes the task as task_complete
does (progress 100, completedAt, worker idle and counted once per
hand-out); cancelling frees workers as failing already did. Worker
effects run after the task store is saved.
Console
- taskStatusOf() reads the spellings older CLIs already stored; used by the
kanban lanes and verbs, Mission Control derive (no re-dispatch), mission
cancel, workflow links and the workflow guide.
Co-Authored-By: Ruflo & AQE
Claude-Session: https://claude.ai/code/session_01CGoza3gyxBjpaiMPhGHcHs
The status backfill set modified=true even when the UPDATE touched 0 rows, so
every open of an up-to-date store re-exported and rewrote the whole image; with
encryption at rest each write uses a fresh nonce, so read-only commands such as
'memory stats' changed the RFE1 bytes every call. Gate on getRowsModified().
Co-Authored-By: RuFlo <ruv@ruv.net>
The anchor mirror and trust key were resolved with userInfo().homedir, which
ignores a throwaway HOME, so tests wrote into the developer's real
~/.config/ruflo/policy-trust and later failed closed on a reused path.
Resolve from the environment at call time (XDG_CONFIG_HOME when absolute,
else os.homedir()/.config; legacy location kept for XDG users who already
have trust state there). mcp-client-guardrail.test.ts now uses a scratch
cwd and HOME.
Co-Authored-By: RuFlo <ruv@ruv.net>
vitest 4.1.8 does not export ./vitest.mjs, and pnpm's .bin shim exports NODE_PATH with
every workspace dependency, so the optional-package absence guards in the #3904, #3907
and #3910 fixtures failed under 'pnpm test'.
Co-Authored-By: RuFlo <ruv@ruv.net>