- Sessions list starts folded; jumping from the queue opens it.
- First reads past a pass's byte budget wait for the next pass ("not read yet").
- A Codex sub-agent rollout's trailing parent session_meta is lineage, not a second identity.
- ADR/CHANGELOG/README say discovery spawns nothing; the only write is the four-count summary.
Co-Authored-By: RuFlo <ruv@ruv.net>
Needs-you queue (approvals, questions, failures, finished-unread) across Claude Code, Codex and Ruflo
sessions, a browser grouped by repository and worktree, and a preview of the selected session. Local,
read-only discovery (no model call, no process); ambiguous identity goes to an unassigned bucket;
finished work clears only after its preview was drawn; transcript text never reaches a model, the
state, the disk or a text answer. ruflo-mods gains an optional counts-only attention row.
Co-Authored-By: RuFlo <ruv@ruv.net>
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
handleDeliveryError()'s retry re-queue used message.to ('broadcast') as the
queue key for a broadcast message instead of the per-subscriber agentId
enqueue() actually fanned the message out to. processQueues() skips any
unsubscribed queue, so a failing broadcast subscriber's retries -- and
eventual message.failed -- were silently dropped into an orphaned queue
leaking until shutdown(). Explicitly disclosed as a known limitation by the
preceding #3562/#3563 MessageBus rewrite; closed by threading
subscription.agentId through deliverMessage() -> handleDeliveryError() ->
the re-queue.
2 new discriminating tests (stash-isolated baseline-fails/candidate-passes,
independently reproduced by an adversarial critic). Full swarm suite
274/274 -> 276/276, 0 regressions, tsc clean both ways.
Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_016qkoWKmaupqNEJwqiedzsX
A refused mod or a permission deny has no action, so it held 'n to approve' up
with nothing to press. The band, menu badge, change notices and the Approvals
header now count waitingApprovalsOf(); notices stay listed, named apart.
Co-Authored-By: RuFlo <ruv@ruv.net>
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>
- A Yes runs only the card it was pressed on: every pending card has an id,
the Yes / Always allow / Always accept buttons carry it, runner.confirm(seen)
runs nothing (and says so) when another card took its place. A card Claude
raised is re-checked against the level and Stop when it lands and when the
Yes arrives.
- Everything returned to the model goes through modelLine (escapes, then
control and invisible characters removed, cut, withheld whole when it holds
a secret shape or an invite code) and every answer leaves through
modelLines; a version such as v2.1.0-beta.3 is not an invite.
- ESCAPES is linear: an unterminated OSC ends at the next introducer or the
end of the text (7.7 s on the old pattern became milliseconds on 1 MB).
- Mission state/status, hive role, audit severity and Settings plugin names
that are Object.prototype keys read as unknown (own()).
- Approvals and a mission objective wrap at 80 columns instead of being cut
with an ellipsis (#3899).
Specs ported from #3820, #3821 and #3822, adapted to main.
Co-authored-by: Dragan Spiridonov <spiridonovdragan@gmail.com>
Co-Authored-By: RuFlo <ruv@ruv.net>
The v3 critical-blocking npm audit started failing on 4.7.9 (GHSA-xw65-4hp5-5hc7, GHSA-8r5x-fm3f-whwj, GHSA-p8wg-vrv2-v86f). The existing >=4.7.9 override already admits 4.7.10; only the lock entries change. npm audit --audit-level=critical now reports 0 critical.
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>