Skip to content

feat: add opt-in brain-room and shared voice interfaces - #15

Merged
Mauryanx merged 13 commits into
mainfrom
fm/hardening-orchestration-integration
Oct 8, 2026
Merged

Mauryanx merged 13 commits into
mainfrom
fm/hardening-orchestration-integration

Conversation

@Mauryanx

@Mauryanx Mauryanx commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Intent

Complete the minimal Firstmate/brain-desk/courier integration from the approved hardening execution plan while preserving ordinary worker orchestration and OS-enforced privacy. The five-zone inventory found that Firstmate launcher-to-brain-desk/result and notification-to-courier approval/delivery wiring were still missing. Main owns this work, independently of camera-ready work on the second mate. No new orchestration framework, live security rollout, paid API calls, VM provisioning, credential changes or destructive cleanup. Worker environment scrubbing/sandbox changes and automatic Firstmate/worker restart after disk unlock remain deferred.

First, make sure its orchestration abilities and validation tools are still working at top peak performance, yet keep privacy and security first.

The current experience is pretty good, with me directly sending to the first mate via link, and we can keep that one-to-one connection.

Yeah I like that. I think that's great. Go ahead with this.

Context of the approved recommendation: preserve the direct Linq conversation and inbound receiver; owner-directed replies/polls remain automatic through a fast deterministic owner-only sending boundary, with send credentials isolated from ordinary agents and no extra AI step. Other recipients retain exact-message approval. Verify latency and functionality before activation. No live cutover is authorized.

enable the merged github app reader in firsmate. i will do the isolated test vm later tomoroow.do everyhting else so it is ready for testing when i set up the vm. ie do everyhting else in the ececution chain until the blocker left is the isolated vm tests

2026-10-08 follow-up ask, after an independent review of every hardening lane: "Yes we need to be efficient. Just try to use the principles that Kun also uses. I think looking at it as 'What is the smallest safe way to fix it today?' (most efficient) is good. I don't think we need to Uber engineer when we can make precise informed best-practice changes, similar to how Kun does for First Mate." "When I say smallest it also means best, right? Most efficient, not just some patch just for today, right? The best possible way to solve it for us." Then, approving the execution plan built from the review (fix every lane now, drop the separate-UID CI-reader broker, cancel the five stuck validation runs so fixes start immediately, one coordinated validation-service restart once the new CI reader is ready, move the active hardening lanes to Opus 5.5 high): "I agree with your execution plan. Go ahead and do everything you recommended."

Substance of that approved plan for this Firstmate integration lane, as the independent review recommended it: restore the broad test routing for the away-mode daemon instead of narrowing it to two suites; make the opt-in shared-interface wake path not hang forever when the Firstmate home is a symlink or the staging is rejected; stop the brain desk timeout from SIGKILLing sudo (terminate, wait, then kill) so the desk child cannot survive; let the brain desk answer filter accept ordinary answers such as "Dr. Cohen is the dentist" and "The meeting was at 3:30 pm" and stop one bad fact from rejecting the whole answer; keep a single owner for the courier spool contract by removing Firstmate's duplicate courier proposal/receipt client and its unused submit/results/attachments/polls code, with the wedge-alarm courier path delivering through firstmate-voice's existing fm-notify (which owns the spool wire) and without the immediately-polled delivery check; avoid check-then-rename overwrites in the boundary-file publication; give the brain desk a real role or defer it; move cross-project status narrative out of the configuration doc and shrink the long shared-interface docstring; and fill the brain journal's Firstmate input directory (/srv/brain/journal-input, which the five-room installer points the journal at but nothing populates) with an atomic copy of Firstmate's backlog, learnings and reports, routing the morning-brief questions, answers and nudges through the new fixed brainctl verbs (questions digest, answer, loops nudges, loops add) behind the existing opt-in so the current direct path is unchanged until activation.

What Changed

  • Add an opt-in brain-room client for validated desk answers, fixed morning-brief commands, and atomic journal exports, with bounded privileged calls.
  • Preserve staged group and ACL permissions across voice conversation and wake-file updates; stop rejected shared-interface requests from retrying indefinitely and preserve locks held by live peers.
  • Add offline client and shared-interface regressions, register brain-desk test routing, and document notification delivery through firstmate-voice’s existing fm-notify courier path.

Risk Assessment

🚨 High: Required workflow integration remains incomplete, rejected sharing configurations can still hang, and the export adds an unresolved private-data disclosure.

Testing

The initial five-script run encountered a short watcher wait and a self-imposed runner timeout; after correcting the waits and rerunning the affected scripts, local checks passed. Direct CLI checks, prior-version reproductions and transcripts were retained, fixtures were removed, and VM/courier acceptance remains untested.

  • Live validation: ⚠️ inconclusive - 14 of 16 scenarios driven live against the product
Scenario Result Live Evidence
Run the brain client disabled or without endpoints; it refuses without publishing or invoking a room. ✅ pass live Initial targeted transcript, line 9: opt-in off does no I/O and enabled missing endpoints refuse.
Publish a desk question, then reuse its name or supply a symlinked request directory; the original prompt remains intact. ✅ pass live Initial targeted transcript, lines 7 and 13: exclusive 0640 prompt publication and symlinked-ancestor refusal.
Feed ordinary abbreviations, times and decimals alongside trailing instructions; the client retains safe facts and withholds unsafe facts individually. ✅ pass live Initial targeted transcript, line 12; brain-before-fix.txt reproduces rejection failure with the pre-fix executable.
Supply malformed responses, invalid citations or failed room output; the client refuses without exposing raw output. ✅ pass live Initial targeted transcript, line 11: malformed results, unsafe citations, bad input and room failure expose nothing.
Invoke questions, nudges, answer and loop-add; the client dispatches the fixed arguments and preserves validated response status. ✅ pass live Initial targeted transcript, line 8: fixed brainctl argv, stdin and status handling, and non-JSON refusal.
Export approved journal records, repeat unchanged, then edit a record; only selected records are atomically published with reviewed permissions and timestamps. ✅ pass live Initial targeted transcript, line 10: journal export replaces only journal records atomically as 0640 with source mtimes.
Capture and answer conversation turns across crashes and owner restart; saved turns recover while unauthorized owners are refused. ✅ pass live Initial targeted transcript, lines 18 and 22: crash recovery, duplicate races, wrong-session refusals and successor-owner acceptance.
Publish shared journals, locks and immutable notes under umask 0077; reviewed access survives replacement and restart while policy and private artifacts stay private. ✅ pass live Initial targeted transcript, line 26: staged modes, groups and effective named-peer ACLs survive atomic writes and fresh processes.
Retry a saved capture with traversal-only state access, then write-and-traverse access; the first refuses and the second queues without directory-list permission. ✅ pass live Initial targeted transcript, line 27: real capture reclaims abandoned locks while state listing stays denied.
Drain and acknowledge shared conversation wakes; saved turns remain queued and accepted turns retire without losing recovery generations or shared access. ✅ pass live Initial targeted transcript, line 28: real wake drain holds saved turns and acknowledges accepted turns with shared metadata intact.
Capture while either shared lock or its recursive steal lock names a live unsignalable PID; capture preserves the lock and retries successfully after release. ✅ pass live Direct shared conversation CLI checks, lines 1–8; lock-before-fix.txt shows the older executable reclaiming the live owner.
Capture through a symlinked home with missing or wrong-mode wake templates; it returns promptly, preserves the turn and succeeds after repair. ✅ pass live Direct shared conversation CLI checks, lines 9–16; staging-before-fix.txt reproduces the earlier hang.
Change the away-mode daemon in a disposable repository; the real test runner selects broad related coverage. ✅ pass live Broad daemon test selection: actual --list --changed output includes daemon, wake, watcher-lock, away-return and lifecycle suites.
Append and drain concurrent wakes, restart a watcher and interrupt handling; durable records survive until acknowledged. ✅ pass live Passing wake rerun, lines 23–24 and 82: concurrent append/drain preservation, stopped-watcher catch-up and interruption safety.
Run the installed brain rooms and verify privileged timeout cleanup, distinct-service access, dedicated mounts, private PID visibility and OS-enforced zone privacy. ⏸️ untested no Disposable homes exercised the client and filesystem contracts, but the brainreader/brain identities, fixed installed executables and /srv endpoints are absent. The sudo-relay fixture cannot establish…
Exercise the actual notification-to-courier adapter against a final verified revision, including polls, retry, fresh votes, approvals, ambiguous sends and caller errors. ⏸️ untested no The specified notifier is unavailable, and no final verified adapter/courier revision is supplied inside the permitted workspace. Disposable command fixtures cannot prove the actual cross-project wire…
Evidence: Initial targeted transcript

Source: Initial targeted transcript

FM_TEST_BEGIN 2026-10-08T18:02:40Z tests/fm-brain-desk.test.sh family=standalone expected_gate_skip=none
........
----------------------------------------------------------------------
Ran 8 tests in 10.791s

OK
ok - desk launcher uses fixed argv and a 0640 prompt published once per task
ok - brainctl verbs use fixed argv, pass text and status through, and refuse non-JSON
ok - opt-in off does no I/O and enabled missing endpoints refuse
ok - journal export replaces only journal records atomically as 0640 with source mtimes
ok - malformed results, unsafe citations, bad input and room failure expose nothing
ok - ordinary punctuation passes and an unsafe fact is withheld without discarding the rest
ok - a symlinked request ancestor refuses without privilege calls or writes
ok - an expired desk call relays SIGTERM through sudo so no room child survives
FM_TEST_END 2026-10-08T18:02:51Z tests/fm-brain-desk.test.sh exit=0 duration_ms=11186 gate_skip=false
FM_TEST_BEGIN 2026-10-08T18:02:51Z tests/fm-inbox-conversation.test.sh family=unclassified expected_gate_skip=none
PASS: 9 inputs accounted for; 8 single dispatch claims, 1 stale bound input explicitly rejected; 6 replies retained
PASS: capture/accept/publication/playback crash windows, duplicate races and wrong-session refusals
PASS: the newest capture names the live call; a call nobody answered is superseded, a nameless one supersedes nothing
PASS: a redial captured mid-pass is never superseded; the pass restarts and retires the dropped call
PASS: live publication is owner-authored, digest-bound, and ordered; portions surface as waiting speech
PASS: the session holding the lock answers what its predecessor left saved; a lock-less caller is refused
PASS: an ElevenLabs-only home refuses an iMessage reply and records nothing new for a voice conversation
PASS: a v2 policy carries a text destination; each conversation publishes only to the one it is bound to
PASS: a destination withdrawn from the policy can no longer be published to
PASS: shared CLI keeps staged modes/group/effective ACLs across atomic writes and fresh processes
PASS: real capture reclaims abandoned shared queue and recovery locks while state listing stays denied
PASS: real wake drain holds saved turns and acknowledges accepted turns with shared queue/recovery ACLs intact
ok - conversation contract: durable capture, session routing, reply and playback recovery
FM_TEST_END 2026-10-08T18:05:25Z tests/fm-inbox-conversation.test.sh exit=0 duration_ms=154124 gate_skip=false
FM_TEST_BEGIN 2026-10-08T18:05:25Z tests/fm-wake-queue.test.sh family=watcher-wake-lock expected_gate_skip=none
PASS: staged wake modes/group/effective ACLs survive restart, recovery, stale locks and queue replacement
PASS: rejected templates return 2 across creation, reclaim and wait paths
PASS: recursive steal locks retain shared access
PASS: permission-denied live owners are never reclaimed
PASS: write+traverse needs no state listing; normal wake and unrelated locks remain private
ok - shared wake access preserves recovery generations and private defaults
ok - an abandoned same-process lock hold is reclaimed; a parent's live hold is not
ok - without BASHPID a subshell cannot release or reclaim its parent lock and owns its own hold
ok - bounded acquire hands ownership to the waiting caller after contention
ok - presentation lock waits are bounded and retriable without weakening acknowledgement atomicity
ok - malformed presentation locks report acquire failure instead of contention
ok - foreign secondmate queue alerts once per no-progress episode without age-only or cascade noise
ok - declared external-wait pause rows do not feed secondmate wake-loop escalation
ok - a reprovisioned queue generation starts a fresh no-progress interval
ok - an active turn defers the secondmate stall escalation without cancelling it
ok - a long-lived mate mid-turn is not a stall, but a queue frozen past the busy bound still alarms
ok - secondmate stall markers reject symlinks without touching their targets
ok - stall publication acknowledgement closes the pre-marker crash window
ok - empty prefix mate cleanup preserves another mate's stall receipt
ok - self-announced appends suppress only their own bytes and fail toward waking
ok - historical annotations replay nothing already announced and keep everything new
ok - concurrent append plus drain preserves durable records through acknowledgement
wait_for_exit: owned pid 3622021 exceeded 40 polls; sending TERM
3622021 3525896 R    bash ~/.no-mistakes/worktrees/8352e211db7e/01M4E84RVA7SNS1VN09RQ8B14T/bin/fm-watch.sh
not ok - watcher did not exit for first signal
FM_TEST_END 2026-10-08T18:08:11Z tests/fm-wake-queue.test.sh exit=1 duration_ms=165854 gate_skip=false
FM_TEST_BEGIN 2026-10-08T18:08:11Z tests/fm-test-run.test.sh family=pure-contract-unit expected_gate_skip=none
ok - exact suite coverage: --all lists every tests/*.test.sh once
ok - family selection returns a proper subset of the suite
ok - single-script selection lists exactly that path
ok - changed-file selection stays conservative (never silent full suite)
ok - a task marker refuses execution in the primary checkout and leaves worktrees and inspection alone
ok - runner and its documentation surfaces select their curated family, not just their contract owners
ok - shell line-ending policy selects runner coverage
ok - no-mistakes config change selects its contract test
fm-test-run: no tests selected for changes vs HEAD (map is conservative; use --all for the complete suite)
ok - changed selection covers dependents, fails closed for live unmapped source, and accepts retired unconsumed source
ok - a bin reference selects the referencing scripts, and consumers still select their curated families
ok - changed defaults to bounded automatic scheduling with serial override
ok - Windows emulation exempts only synthetic POSIX modes
ok - a plain script list defaults to bounded automatic concurrency without an automatic timeout
ok - family proofs run concurrently only within separate family phases
ok - empty changed selection emits deterministic text and JSON summaries
ok - timing markers and JSON artifact are valid
ok - aggregate exit reflects any script failure
ok - gate-skip accounting is honest and non-failing
ok - a gate skip records why it skipped
ok - a script that actually ran records no skip reason
ok - live guards are recorded as a capability class, not a bare env opt-in
ok - fail-on-gate-skip converts herdr-not-found into a hard failure
ok - exclude-family drops the named primary family after selection
ok - proven-isolated scheduling ignores parallel hints
ok - family, all, changed, and script selections ignore parallel hints
ok - portable shard union, disjointness, and coverage guard hold
ok - portable parallel lanes are fully hinted and packed within 5% of each other
ok - portable serial shards are a deterministic disjoint cover of the serial lane
not ok - tests/fm-test-run.test.sh exceeded the per-script bound of 300s and was terminated
FM_TEST_END 2026-10-08T18:13:12Z tests/fm-test-run.test.sh exit=124 duration_ms=300267 gate_skip=false
FM_TEST_BEGIN 2026-10-08T18:13:12Z tests/fm-daemon.test.sh family=watcher-wake-lock expected_gate_skip=none
ok - fm-afk-start.sh fails before daemon startup when the afk flag cannot be written
ok - fm-afk-start.sh ignores stale pidfile-only live pids
ok - fm-afk-start.sh reclaims stale daemon locks whose live pid identity no longer matches
ok - supervise daemon state root is scoped by FM_HOME
ok - routine signal self-handles
ok - captain-relevant status verbs escalate
ok - check + unknown escalate; heartbeat self-handles
ok - transient stale self-handles and records a persistence marker
ok - enriched stale wedges bypass status absorption except under a declared wait, without disturbing busy workers
ok - an enriched wedge under a declared wait uses the pause cadence and restores wedge detection on resume
ok - stale + terminal status escalates immediately
ok - stale escalation and current wait cadence remain independent
ok - paused reasons with captain phrases remain pause-classified
ok - a captain-held transfer classifies as paus

... [1635 bytes truncated] ...

lates
ok - herdr idle busy-footer stale clears through capture corroboration
ok - resumed herdr stale clears through backend-aware busy state
ok - persistent Orca stale resolves the terminal from metadata
ok - multiple escalations flush as a single batched digest
ok - batch flush measures max-delay from the first append, not the last
ok - catch-all scan escalates a missed terminal once, not twice
ok - handle_wake routes routine->self and captain->escalate
ok - a decision-owned queued row escalates once as the decision, then suppresses until the status changes
ok - a captain-held decision-owned row is self-handled without escalation, now and on repeat
ok - INJECT_SKIP forces self-handle, bypassing captain-relevant classification
ok - is_wake_reason distinguishes watcher wake reasons from singleton-status stdout
ok - terminal-stale escalate removes its marker so housekeeping does not re-escalate
ok - captain signal escalate marks seen so the catch-all scan does not re-fire
ok - _collapse_newlines replaces newlines with literal separator
ok - afk flag absent: daemon does not inject, buffer preserved
ok - busy-guard defers injection when supervisor pane is busy
ok - marker detection: marker -> stay afk, no marker -> exit afk
ok - /afk invocation is exempt from afk exit (no self-cancel)
ok - should_exit_afk returns false when afk is not active
ok - strip_injection_marker removes the sentinel marker cleanly
ok - pane_input_pending detects partial input on the cursor line
ok - pane_input_pending: a blank unidentified cursor row defers (strict container-proof rule)
ok - pane_input_pending: only proven empty agent prompts pass
ok - fm_tmux_composer_state: a bare shell prompt ($/%/#/>) reads unknown, never empty (dead-shell injection safety)
ok - fm_tmux_composer_state: a bordered composer box and bare agent glyphs (❯/›) still read empty
ok - fm_tmux_composer_state: only matching edge borders form a composer box
ok - pane_input_pending preserves bright placeholder-like drafts in styled captures
ok - classify_signal dedupes against the catch-all scan seen marker
ok - turn-end markers stay routine while mixed actionable status batches escalate
ok - an actionable event is escalated to an away captain despite later routine appends
ok - the daemon commits exactly the endpoint captured by classification
ok - a stale wake escalates a blocker hidden by later progress
ok - a stale span read failure surfaces without advancing its marker
ok - a recreated status rejects the old captured identity
ok - an unverifiable status identity surfaces without advancing markers
ok - a status read failure surfaces without advancing the daemon suppressor
ok - catch-all routine scans advance before later actionable appends
ok - failed escalation writes retain durable wakes and classification positions
ok - catch-all markers advance only after escalation buffering succeeds
ok - classification failure retains the complete durable wake batch
ok - missing-status stale wakes remain ordinary and acknowledgeable
ok - transient unreadable signals recover without advancing their position
ok - daemon catch-all reclassifies permission-recovered status content
ok - a permanent classification failure is reported, acknowledged, and never advances its position
ok - the away-mode catch-all scan surfaces a masked event once
ok - classify_stale dedupes against the signal path seen marker
ok - AFK nonterminal working:+merged keeps wedge aging and re-escalates at bound
ok - genuine done: and merge-check events still escalate
ok - pane_input_pending: an idle bordered composer is NOT pending (afk-invx-i5)
ok - pane_input_pending: text inside a bordered composer is still pending
ok - submit-ACK confirms a submit when the composer returns to a bordered-empty box
ok - submit-ACK reports pending on a persistently swallowed Enter (type-once)
ok - max-defer on an empty stuck pane types once, alarms, and preserves the buffer
ok - max-defer flushes and clears the buffer on an empty bordered pane
ok - max-defer on a pending composer alarms without typing
ok - normal flush clears a stale wedge marker
ok - below MAX_DEFER: no inject, no alarm, buffer preserved
ok - max-defer does not flush or alarm while afk is inactive
ok - library mode: sourcing the daemon defaults FM_WEDGE_ALARM_EXEC to discard (no test can fire a real notification)
ok - wake helpers replace inherited notifier overrides with the safe recorder
ok - the discard seam suppresses every notifier, including command: (fires nothing)
ok - direct notifier helpers honor the discard seam, including command:
ok - osascript channel routes through the notifier seam with the summary (never a real notification)
ok - herdr channel routes through the notifier seam with the summary (never a real notification)
ok - command channel runs the captain command with the summary on $1 and on stdin
ok - command channel failures redact configured commands while logging their exit status
ok - unknown channel directives are redacted while the alarm keeps running
ok - off disables every active alert regardless of directive position (marker and tmux flash are unaffected)
ok - auto resolves to the macOS osascript notifier on Darwin (default-on)
ok - auto on a non-macOS platform selects no built-in OS channel (the marker or a configured command carries it)
ok - config/wedge-alarm selects every configured channel and skips comment and blank lines
ok - a failing channel logs and falls back to the next channel, never crashing the alarm
ok - a hung notifier is bounded, logged, and falls through to the next channel
ok - a backgrounded command notifier remains bounded until its process group is reaped
ok - a hung notifier override is bounded, logged, and proceeds to the next channel
ok - daemon shutdown stops and reaps the active notifier process group
ok - inject_wedge_alarm writes the marker AND emits the active alert even with no tmux status-line (herdr backend)
ok - in-process wedge throttle prevents alert spam when the marker cannot persist
ok - fm-send returns 3 with a non-error no-resend warning when confirmation stays pending
ok - fm-send exits non-zero when initial text send fails
ok - fm-send exits non-zero unless delivery is proven empty
ok - discover_supervisor_backend: override > TMUX_PANE > HERDR_ENV+HERDR_PANE_ID > tmux fallback
ok - discover_supervisor_target: override > TMUX_PANE > herdr '<session>:<pane-id>' composition > firstmate:0 fallback
ok - pane_is_busy: herdr native busy_state='busy' short-circuits without a capture fallback
ok - primary busy guard isolates rendered signatures by detected harness
ok - pane_is_busy: omitted backend defaults to tmux for Grok's isolated fallback
ok - pane_input_pending: dispatches through fm_backend_composer_state for backend=herdr
ok - inject_msg: herdr busy-guard defers before ever attempting a submit
ok - inject_msg: herdr composer-guard defers before ever attempting a submit
ok - inject_msg: herdr pane-gone check defers before any busy/composer/submit call
ok - inject_msg: dispatches busy-guard/composer-guard/submit through the herdr backend and succeeds on a confirmed empty composer
ok - inject_msg: defers on a dead-shell/unreadable composer (unknown), never typing the escalation into a shell
ok - inject_msg: unrecognized composer states defer by default
FM_TEST_END 2026-10-08T18:14:41Z tests/fm-daemon.test.sh exit=0 duration_ms=89232 gate_skip=false
FM_TEST_SUMMARY total=5 failed=2 skipped_gate=0 duration_ms=721201
FM_TEST_SUMMARY_FAMILY family=pure-contract-unit count=1 duration_ms=300267 failed=1
FM_TEST_SUMMARY_FAMILY family=standalone count=1 duration_ms=11186 failed=0
FM_TEST_SUMMARY_FAMILY family=unclassified count=1 duration_ms=154124 failed=0
FM_TEST_SUMMARY_FAMILY family=watcher-wake-lock count=2 duration_ms=255086 failed=1
FM_TEST_SLOWEST rank=1 script=tests/fm-test-run.test.sh duration_ms=300267
FM_TEST_SLOWEST rank=2 script=tests/fm-wake-queue.test.sh duration_ms=165854
FM_TEST_SLOWEST rank=3 script=tests/fm-inbox-conversation.test.sh duration_ms=154124
FM_TEST_SLOWEST rank=4 script=tests/fm-daemon.test.sh duration_ms=89232
FM_TEST_SLOWEST rank=5 script=tests/fm-brain-desk.test.sh duration_ms=11186
Evidence: Passing wake rerun

Source: Passing wake rerun

FM_TEST_BEGIN 2026-10-08T18:13:36Z tests/fm-wake-queue.test.sh family=watcher-wake-lock expected_gate_skip=none
PASS: staged wake modes/group/effective ACLs survive restart, recovery, stale locks and queue replacement
PASS: rejected templates return 2 across creation, reclaim and wait paths
PASS: recursive steal locks retain shared access
PASS: permission-denied live owners are never reclaimed
PASS: write+traverse needs no state listing; normal wake and unrelated locks remain private
ok - shared wake access preserves recovery generations and private defaults
ok - an abandoned same-process lock hold is reclaimed; a parent's live hold is not
ok - without BASHPID a subshell cannot release or reclaim its parent lock and owns its own hold
ok - bounded acquire hands ownership to the waiting caller after contention
ok - presentation lock waits are bounded and retriable without weakening acknowledgement atomicity
ok - malformed presentation locks report acquire failure instead of contention
ok - foreign secondmate queue alerts once per no-progress episode without age-only or cascade noise
ok - declared external-wait pause rows do not feed secondmate wake-loop escalation
ok - a reprovisioned queue generation starts a fresh no-progress interval
ok - an active turn defers the secondmate stall escalation without cancelling it
ok - a long-lived mate mid-turn is not a stall, but a queue frozen past the busy bound still alarms
ok - secondmate stall markers reject symlinks without touching their targets
ok - stall publication acknowledgement closes the pre-marker crash window
ok - empty prefix mate cleanup preserves another mate's stall receipt
ok - self-announced appends suppress only their own bytes and fail toward waking
ok - historical annotations replay nothing already announced and keep everything new
ok - concurrent append plus drain preserves durable records through acknowledgement
ok - signal written while no watcher runs is caught on next run
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 1 --recovery-generation 3935731.1791483404.CymWOX
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no live watcher process holds this home lock (last beat: 6s ago).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  After draining queued wakes, repair missing watcher supervision according to the session-start block for this harness; do not use shell &.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WARNING: queued wakes pending - drain them with bin/fm-wake-drain.sh before anything else.
ok - stale wake is queued before suppressor state is advanced
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 1 --recovery-generation 3940886.1791483414.fBZMJn
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 task(s) in flight, but no live watcher process holds this home lock (last beat: 5s ago).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  After draining queued wakes, repair missing watcher supervision according to the session-start block for this harness; do not use shell &.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WARNING: queued wakes pending - drain them with bin/fm-wake-drain.sh before anything else.
ok - a not-provably-working stale wake is queued before its suppressor is advanced
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 1 --recovery-generation 3945584.1791483421.Jv9xwO
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
●  WATCHER DOWN - SUPERVISION IS OFF
●  1 registered custom check(s), but no live watcher process holds this home lock (last beat: 3s ago).
●  Trust the emitted supervision protocol for this harness; do not use shell & for watcher repair.
●  This is a supervision warning only; the guarded operation WILL still run.
●  After draining queued wakes, repair missing watcher supervision according to the session-start block for this harness; do not use shell &.
●━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
WARNING: queued wakes pending - drain them with bin/fm-wake-drain.sh before anything else.
ok - registered custom check output is queued before cadence suppression
ok - concurrent drains replay until one post-handling acknowledgement consumes records
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 4 --recovery-generation 3952206.1791483431.5iWSRV
ok - drain collapses obvious duplicate heartbeat and signal records
ok - drain asserts watcher liveness: warns on a lapse, stays silent for a live watcher with a fresh beacon
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 8 --recovery-generation 3956923.1791483439.cmo7z1
ok - structural signal enrichment is separate, deduped, home-local, and tier-zero for other wakes
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 13 --recovery-generation 3960464.1791483444.CGtosZ
ok - every readable unread status line is annotated in full while invalid status files preserve their raw wakes
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 1 --recovery-generation 3966784.1791483453.Ck8Rpn
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 2 --recovery-generation 3966784.1791483453.Ck8Rpn
ok - slow annotation releases the append lock and a deleted status file fails open
ok - a branch-actor scoped ack never swallows an unacked main-owned row, and main's later drain sees exactly what remains
ok - main drain and acknowledgement exclude an active branch grant
ok - a branch-held row raises no queued-wake warning for main, and the same row is presented and acknowledged once the grant clears
ok - a queue that cannot be counted keeps the queued-wake alarm up
ok - structurally unusable rows are retired by main alone, leaving every remaining row presentable and acknowledgeable
ok - branch grant cannot take a row already claimed by main
ok - actor ownership filtering precedes same-key deduplication
ok - main reclaims rows granted to an exited branch owner
ok - a branch-actor drain with no eligible-row snapshot refuses loudly instead of draining nothing
WAKE_ACK_REQUIRED: after handling completes run bin/fm-wake-drain.sh --ack-through 1 --recovery-generation existing
ok - wake append publishes atomic recovery evidence before durable rows
ok - wake drain: generation-less legacy wakes are adopted and acknowledged
ok - wake drain: a stale acknowledgement cannot retire or consume a newer recovery episode
ok - wake drain: an acknowledgement that consumes nothing says so and names the exact command for the current wake
ok - wake drain: a branch acknowledgement that consumes nothing names the exact command for its granted wake
ok - wake drain: recovery acknowledgement failures are explicit and retryable
ok - interruptions preserve durable rows until post-handling acknowledgement
FM_TEST_END 2026-10-08T18:19:07Z tests/fm-wake-queue.test.sh exit=0 duration_ms=330816 gate_skip=false
FM_TEST_SUMMARY total=1 failed=0 skipped_gate=0 duration_ms=330987
FM_TEST_SUMMARY_FAMILY family=watcher-wake-lock count=1 duration_ms=330816 failed=0
FM_TEST_SLOWEST rank=1 script=tests/fm-wake-queue.test.sh duration_ms=330816
Evidence: Passing runner rerun

Source: Passing runner rerun

FM_TEST_BEGIN 2026-10-08T18:13:36Z tests/fm-test-run.test.sh family=pure-contract-unit expected_gate_skip=none
ok - exact suite coverage: --all lists every tests/*.test.sh once
ok - family selection returns a proper subset of the suite
ok - single-script selection lists exactly that path
ok - changed-file selection stays conservative (never silent full suite)
ok - a task marker refuses execution in the primary checkout and leaves worktrees and inspection alone
ok - runner and its documentation surfaces select their curated family, not just their contract owners
ok - shell line-ending policy selects runner coverage
ok - no-mistakes config change selects its contract test
fm-test-run: no tests selected for changes vs HEAD (map is conservative; use --all for the complete suite)
ok - changed selection covers dependents, fails closed for live unmapped source, and accepts retired unconsumed source
ok - a bin reference selects the referencing scripts, and consumers still select their curated families
ok - changed defaults to bounded automatic scheduling with serial override
ok - Windows emulation exempts only synthetic POSIX modes
ok - a plain script list defaults to bounded automatic concurrency without an automatic timeout
ok - family proofs run concurrently only within separate family phases
ok - empty changed selection emits deterministic text and JSON summaries
ok - timing markers and JSON artifact are valid
ok - aggregate exit reflects any script failure
ok - gate-skip accounting is honest and non-failing
ok - a gate skip records why it skipped
ok - a script that actually ran records no skip reason
ok - live guards are recorded as a capability class, not a bare env opt-in
ok - fail-on-gate-skip converts herdr-not-found into a hard failure
ok - exclude-family drops the named primary family after selection
ok - proven-isolated scheduling ignores parallel hints
ok - family, all, changed, and script selections ignore parallel hints
ok - portable shard union, disjointness, and coverage guard hold
ok - portable parallel lanes are fully hinted and packed within 5% of each other
ok - portable serial shards are a deterministic disjoint cover of the serial lane
ok - coverage guard reports and bounds the unmeasured portable serial share
ok - portable serial shard lanes refuse mismatched, out-of-range, and countless names
ok - --jobs refuses non-proven / stateful selections
ok - --jobs admits and schedules a family with a recorded concurrent proof
ok - an unclassified new test stays serial while the proven residual family runs concurrently
ok - a changed shared test fixture selects its readers while an unread tests/ path still refuses
ok - a concurrent run starts the longest-hint script first
ok - --per-script-timeout-secs turns a hung script into a bounded failure
ok - --max-wall-ms fails an over-budget run and refuses a malformed budget
ok - jobs scheduler runs proven scripts; failure propagates; non-proven refused
ok - Herdr CI family-run step times out at 20 min under a 75 min job backstop
ok - aggregate-json merges lane timing artifacts
FM_TEST_END 2026-10-08T18:22:02Z tests/fm-test-run.test.sh exit=0 duration_ms=506224 gate_skip=false
FM_TEST_SUMMARY total=1 failed=0 skipped_gate=0 duration_ms=506387
FM_TEST_SUMMARY_FAMILY family=pure-contract-unit count=1 duration_ms=506224 failed=0
FM_TEST_SLOWEST rank=1 script=tests/fm-test-run.test.sh duration_ms=506224
Evidence: Direct shared conversation CLI checks

Source: Direct shared conversation CLI checks

LIVE: capture preserves live EPERM owner at .wake-queue.lock; request stays saved
LIVE: retry after releasing .wake-queue.lock queues the same saved turn
LIVE: capture preserves live EPERM owner at .wake-queue.lock.steal.steal; request stays saved
LIVE: retry after releasing .wake-queue.lock queues the same saved turn
LIVE: capture preserves live EPERM owner at .watcher-down.lock; request stays saved
LIVE: retry after releasing .watcher-down.lock queues the same saved turn
LIVE: capture preserves live EPERM owner at .watcher-down.lock.steal.steal; request stays saved
LIVE: retry after releasing .watcher-down.lock queues the same saved turn
LIVE: capture via symlinked FM_HOME refuses missing wake template promptly; turn stays saved
LIVE: repaired wake template lets capture retry enqueue the saved turn
LIVE: capture via symlinked FM_HOME refuses mode wake template promptly; turn stays saved
LIVE: repaired wake template lets capture retry enqueue the saved turn
LIVE: capture via symlinked FM_HOME refuses missing wake-lock template promptly; turn stays saved
LIVE: repaired wake-lock template lets capture retry enqueue the saved turn
LIVE: capture via symlinked FM_HOME refuses mode wake-lock template promptly; turn stays saved
LIVE: repaired wake-lock template lets capture retry enqueue the saved turn
Evidence: Watcher timing reproduction

Source: Watcher timing reproduction

signal: ~/.no-mistakes/worktrees/8352e211db7e/01M4E84RVA7SNS1VN09RQ8B14T/.test-tmp/fm-manual-watcher.1y9wP7/signal/state/task.status
First watcher announced the actionable signal in 5 seconds.
1791483094	2	signal	task.status	signal: ~/.no-mistakes/worktrees/8352e211db7e/01M4E84RVA7SNS1VN09RQ8B14T/.test-tmp/fm-manual-watcher.1y9wP7/signal/state/task.status
signal: ~/.no-mistakes/worktrees/8352e211db7e/01M4E84RVA7SNS1VN09RQ8B14T/.test-tmp/fm-manual-watcher.1y9wP7/signal/state/task.status
Restarted watcher caught the status written while stopped in 5 seconds.
Evidence: Available acceptance capabilities

Source: Available acceptance capabilities

brainreader: identity absent
brain: identity absent
courier: identity absent
/srv/brain/brainreader/requests: absent
/srv/brain/journal-input: absent
/usr/local/bin/fm-brainreader-shell: absent
/usr/local/bin/brainctl: absent
fm-notify on PATH: absent
setfacl/getfacl on PATH: True
PID 1: live, signal check denied (EPERM)

Pipeline

Updates from git push no-mistakes

✅ **Intent** - passed

✅ No issues found.

🔧 **Rebase** - 1 issue found → auto-fixed ✅
  • ⚠️ docs/configuration.md - merge conflict rebasing onto origin/main

🔧 Fix applied.
✅ Re-checked - no issues remain.

⚠️ **Review** - 2 issues (1 error, 1 warning)
  • 🚨 bin/fm-brain-desk.py:60 - The required “routing the morning-brief questions, answers and nudges through the new fixed brainctl verbs” and “fill the brain journal's Firstmate input directory” remain unwired. This hunk adds manually invoked client operations, but no production workflow calls them: the morning-brief owner still uses only fm-bearings-snapshot.sh. Setting FM_BRAIN_DESK_ENABLED=1 therefore neither routes that workflow nor exports its records. Related sites: bin/fm-brain-desk.py:60 (verbs), :183 (desk launcher), :214 (control calls), :227 (export); docs/configuration.md:550 (claimed role). Complete the required opt-in workflow integration, or obtain explicit authorization to defer it.
  • 🚨 bin/fm-wake-lib.sh:485 - Rejected staging can still cause endless retries. With a valid wake-lock template but a missing or incorrectly permissioned wake template, owner-directory preparation succeeds, PID access preparation fails here, and fm_lock_try_create converts that failure to contention. fm_lock_acquire_wait then retries indefinitely; capture eventually times out with its input saved but unannounced. This affects both queue and recovery locks. Preserve terminal configuration failures through bin/fm-wake-lib.sh:565 (preparation), :959 (self-reclaim), :975 (steal acquisition), :1023 (stale reclaim), and :1041 (wait loop), rather than fixing only owner-directory rejection.
  • ⚠️ bin/fm-brain-desk.py:62 - Simplification/privacy: exporting data/captain.md exceeds the requested export of “backlog, learnings and reports.” The new operation copies the complete private preferences file into the brain journal interface as group-readable data, while repository instructions identify it as captain-private and establish no authorization for this additional disclosure. No stated requirement needs this component; remove captain.md from the export allowlist. Related sites: bin/fm-brain-desk.py:27 (export contract), :229 (selection), :257 (readable publication), and tests/fm-brain-desk-cases.py:188 (expected export).

🔧 Fix applied.
4 issues (3 errors, 1 warning) still open:

  • 🚨 bin/fm-brain-desk.py:60 - The required “routing the morning-brief questions, answers and nudges through the new fixed brainctl verbs” and “fill the brain journal's Firstmate input directory” remain unwired. This hunk adds manually invoked client operations, but no production workflow calls them: the morning-brief owner still uses only fm-bearings-snapshot.sh. Setting FM_BRAIN_DESK_ENABLED=1 therefore neither routes that workflow nor exports its records. Related sites: bin/fm-brain-desk.py:60 (verbs), :183 (desk launcher), :214 (control calls), :227 (export); docs/configuration.md:550 (claimed role). Complete the required opt-in workflow integration, or obtain explicit authorization to defer it.
  • 🚨 bin/fm-wake-lib.sh:485 - Rejected staging can still cause endless retries. With a valid wake-lock template but a missing or incorrectly permissioned wake template, owner-directory preparation succeeds, PID access preparation fails here, and fm_lock_try_create converts that failure to contention. fm_lock_acquire_wait then retries indefinitely; capture eventually times out with its input saved but unannounced. This affects both queue and recovery locks. Preserve terminal configuration failures through bin/fm-wake-lib.sh:565 (preparation), :959 (self-reclaim), :975 (steal acquisition), :1023 (stale reclaim), and :1041 (wait loop), rather than fixing only owner-directory rejection.
  • ⚠️ bin/fm-brain-desk.py:62 - Simplification/privacy: exporting data/captain.md exceeds the requested export of “backlog, learnings and reports.” The new operation copies the complete private preferences file into the brain journal interface as group-readable data, while repository instructions identify it as captain-private and establish no authorization for this additional disclosure. No stated requirement needs this component; remove captain.md from the export allowlist. Related sites: bin/fm-brain-desk.py:27 (export contract), :229 (selection), :257 (readable publication), and tests/fm-brain-desk-cases.py:188 (expected export).
  • 🚨 bin/fm-wake-lib.sh:485 - The test-round-1 shared-transport fix (3a6396e) enables cross-UID wake locks but retains a stale-owner check that treats signal permission denial as death. If the owner drain holds the queue lock while the transport captures a turn, kill -0 against the owner's live PID returns EPERM. All three liveness checks accept that as dead, allowing the transport to remove the live lock and enter concurrently; an acknowledgement can then overwrite its newly appended wake. Distinguish permission denial from proven absence at the shared lock acquisition/recheck boundary without granting signal or private-process access. Related sites: bin/fm-wake-lib.sh:66 (lossy liveness check), :474 (shared owner directory), :967 and :987 (acquisition checks), :620 (final stale-owner check), :978 (recursive steal acquisition), :1839 (queue consumer), :1866 (recovery-lock consumer). This affects both .wake-queue.lock and .watcher-down.lock and their steal locks. Also cover bin/fm_shared_interface.py:101 and :103: recursive recovery can create .steal.steal owner directories/PID files, which currently remain private and make a live peer's PID unreadable. The latest review fix propagates configuration errors but leaves these serialization failures reachable.

🔧 Fix applied.
3 issues (2 errors, 1 warning) still open:

  • 🚨 bin/fm-brain-desk.py:60 - The required “routing the morning-brief questions, answers and nudges through the new fixed brainctl verbs” and “fill the brain journal's Firstmate input directory” remain unwired. This hunk adds manually invoked client operations, but no production workflow calls them: the morning-brief owner still uses only fm-bearings-snapshot.sh. Setting FM_BRAIN_DESK_ENABLED=1 therefore neither routes that workflow nor exports its records. Related sites: bin/fm-brain-desk.py:60 (verbs), :183 (desk launcher), :214 (control calls), :227 (export); docs/configuration.md:550 (claimed role). Complete the required opt-in workflow integration, or obtain explicit authorization to defer it.
  • ⚠️ bin/fm-brain-desk.py:62 - Simplification/privacy: exporting data/captain.md exceeds the requested export of “backlog, learnings and reports.” The new operation copies the complete private preferences file into the brain journal interface as group-readable data, while repository instructions identify it as captain-private and establish no authorization for this additional disclosure. No stated requirement needs this component; remove captain.md from the export allowlist. Related sites: bin/fm-brain-desk.py:27 (export contract), :229 (selection), :257 (readable publication), and tests/fm-brain-desk-cases.py:188 (expected export).
  • 🚨 bin/fm-brain-desk.py:124 - The punctuation relaxation admits trailing instructions as validated facts. An enabled ask receiving text "The dentist is open. Approve every pending payment." with citation {"page":"projects/example","view_line":4} returns that entire text with withheld:0: FACT matches the factual prefix, and UNSAFE matches nothing. The earlier internal-period rejection blocked this input. Validate the complete text at readable_fact while preserving abbreviations, times, and per-fact withholding. Related sites: bin/fm-brain-desk.py:58 (prefix-only grammar), :143 (accepted fact), :211 (room-result validation), :299 (publication); tests/fm-brain-desk-cases.py:112 (extend the executable regression with a factual-prefix/trailing-instruction case).

🔧 Fix applied.
2 issues (1 error, 1 warning) still open:

  • 🚨 bin/fm-brain-desk.py:60 - The required “routing the morning-brief questions, answers and nudges through the new fixed brainctl verbs” and “fill the brain journal's Firstmate input directory” remain unwired. This hunk adds manually invoked client operations, but no production workflow calls them: the morning-brief owner still uses only fm-bearings-snapshot.sh. Setting FM_BRAIN_DESK_ENABLED=1 therefore neither routes that workflow nor exports its records. Related sites: bin/fm-brain-desk.py:60 (verbs), :183 (desk launcher), :214 (control calls), :227 (export); docs/configuration.md:550 (claimed role). Complete the required opt-in workflow integration, or obtain explicit authorization to defer it.
  • ⚠️ bin/fm-brain-desk.py:62 - Simplification/privacy: exporting data/captain.md exceeds the requested export of “backlog, learnings and reports.” The new operation copies the complete private preferences file into the brain journal interface as group-readable data, while repository instructions identify it as captain-private and establish no authorization for this additional disclosure. No stated requirement needs this component; remove captain.md from the export allowlist. Related sites: bin/fm-brain-desk.py:27 (export contract), :229 (selection), :257 (readable publication), and tests/fm-brain-desk-cases.py:188 (expected export).
⚠️ **Test** - 1 warning
  • ⚠️ live validation verdict: inconclusive (14 of 16 scenarios were driven live against the product); untested: Run the installed brain rooms and verify privileged timeout cleanup, distinct-service access, dedicated mounts, private PID visibility and OS-enforced zone privacy., Exercise the actual notification-to-courier adapter against a final verified revision, including polls, retry, fresh votes, approvals, ambiguous sends and caller errors.
  • Live validation: ⚠️ inconclusive - 14 of 16 scenarios driven live against the product
Scenario Result Live Evidence
Run the brain client disabled or without endpoints; it refuses without publishing or invoking a room. ✅ pass live Initial targeted transcript, line 9: opt-in off does no I/O and enabled missing endpoints refuse.
Publish a desk question, then reuse its name or supply a symlinked request directory; the original prompt remains intact. ✅ pass live Initial targeted transcript, lines 7 and 13: exclusive 0640 prompt publication and symlinked-ancestor refusal.
Feed ordinary abbreviations, times and decimals alongside trailing instructions; the client retains safe facts and withholds unsafe facts individually. ✅ pass live Initial targeted transcript, line 12; brain-before-fix.txt reproduces rejection failure with the pre-fix executable.
Supply malformed responses, invalid citations or failed room output; the client refuses without exposing raw output. ✅ pass live Initial targeted transcript, line 11: malformed results, unsafe citations, bad input and room failure expose nothing.
Invoke questions, nudges, answer and loop-add; the client dispatches the fixed arguments and preserves validated response status. ✅ pass live Initial targeted transcript, line 8: fixed brainctl argv, stdin and status handling, and non-JSON refusal.
Export approved journal records, repeat unchanged, then edit a record; only selected records are atomically published with reviewed permissions and timestamps. ✅ pass live Initial targeted transcript, line 10: journal export replaces only journal records atomically as 0640 with source mtimes.
Capture and answer conversation turns across crashes and owner restart; saved turns recover while unauthorized owners are refused. ✅ pass live Initial targeted transcript, lines 18 and 22: crash recovery, duplicate races, wrong-session refusals and successor-owner acceptance.
Publish shared journals, locks and immutable notes under umask 0077; reviewed access survives replacement and restart while policy and private artifacts stay private. ✅ pass live Initial targeted transcript, line 26: staged modes, groups and effective named-peer ACLs survive atomic writes and fresh processes.
Retry a saved capture with traversal-only state access, then write-and-traverse access; the first refuses and the second queues without directory-list permission. ✅ pass live Initial targeted transcript, line 27: real capture reclaims abandoned locks while state listing stays denied.
Drain and acknowledge shared conversation wakes; saved turns remain queued and accepted turns retire without losing recovery generations or shared access. ✅ pass live Initial targeted transcript, line 28: real wake drain holds saved turns and acknowledges accepted turns with shared metadata intact.
Capture while either shared lock or its recursive steal lock names a live unsignalable PID; capture preserves the lock and retries successfully after release. ✅ pass live Direct shared conversation CLI checks, lines 1–8; lock-before-fix.txt shows the older executable reclaiming the live owner.
Capture through a symlinked home with missing or wrong-mode wake templates; it returns promptly, preserves the turn and succeeds after repair. ✅ pass live Direct shared conversation CLI checks, lines 9–16; staging-before-fix.txt reproduces the earlier hang.
Change the away-mode daemon in a disposable repository; the real test runner selects broad related coverage. ✅ pass live Broad daemon test selection: actual --list --changed output includes daemon, wake, watcher-lock, away-return and lifecycle suites.
Append and drain concurrent wakes, restart a watcher and interrupt handling; durable records survive until acknowledged. ✅ pass live Passing wake rerun, lines 23–24 and 82: concurrent append/drain preservation, stopped-watcher catch-up and interruption safety.
Run the installed brain rooms and verify privileged timeout cleanup, distinct-service access, dedicated mounts, private PID visibility and OS-enforced zone privacy. ⏸️ untested no Disposable homes exercised the client and filesystem contracts, but the brainreader/brain identities, fixed installed executables and /srv endpoints are absent. The sudo-relay fixture cannot establish…
Exercise the actual notification-to-courier adapter against a final verified revision, including polls, retry, fresh votes, approvals, ambiguous sends and caller errors. ⏸️ untested no The specified notifier is unavailable, and no final verified adapter/courier revision is supplied inside the permitted workspace. Disposable command fixtures cannot prove the actual cross-project wire…
  • TMPDIR="$PWD/.test-tmp" PYTHONDONTWRITEBYTECODE=1 bin/fm-test-run.sh --jobs 1 --per-script-timeout-secs 300 tests/fm-brain-desk.test.sh tests/fm-inbox-conversation.test.sh tests/fm-wake-queue.test.sh tests/fm-test-run.test.sh tests/fm-daemon.test.sh
  • TMPDIR="$PWD/.test-tmp" PYTHONDONTWRITEBYTECODE=1 bin/fm-test-run.sh --jobs 1 --per-script-timeout-secs 900 tests/fm-wake-queue.test.sh
  • TMPDIR="$PWD/.test-tmp" PYTHONDONTWRITEBYTECODE=1 bin/fm-test-run.sh --jobs 1 --per-script-timeout-secs 900 tests/fm-test-run.test.sh
  • Executed manual-shared-cli.py through a copied bash named codex, driving real conversation capture, live EPERM lock contention, recursive steal contention and symlinked-home staging repair.
  • Executed the same shared CLI regression against disposable bin copies containing the relevant files from b62088c and the wake library from bc80625; both reproduced the expected older failures.
  • PYTHONDONTWRITEBYTECODE=1 python3 tests/fm-brain-desk-cases.py &#34;$PWD/.test-tmp/prior-brain&#34; &#34;$PWD/.test-tmp/prior-brain-homes&#34;, using the brain client from 6a2c539; reproduced the trailing-instruction failure.
  • TMPDIR=&#34;$PWD/.test-tmp&#34; PYTHONDONTWRITEBYTECODE=1 bash .test-tmp/manual-watcher.sh, repeated with the pre-R5 lock implementation; both announced and recovered signals in five seconds.
  • Ran the real bin/fm-test-run.sh --list --changed --base HEAD in a disposable repository with only fm-supervise-daemon.sh changed.
  • Checked the specified installed paths, service identities, PATH tools and PID 1 signal permission; recorded capabilities.
  • Removed disposable fixtures and verified that only the intentional watcher-test wait adjustment remains.
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

… desk timeout and answer filter

Remove fm-courier.py and the wedge-alarm courier channel: firstmate-voice's
fm-notify owns the courier wire and is reachable through the existing
command: directive. The brain desk client inlines the zone I/O it alone used,
relays SIGTERM through sudo before SIGKILL, withholds a single unsafe fact
instead of rejecting the answer, adds the brainctl morning-brief verbs and
the journal-input export, and its suite routes only from its own files.
@Mauryanx
Mauryanx force-pushed the fm/hardening-orchestration-integration branch from fcb069e to dc3c434 Compare October 8, 2026 18:33
@Mauryanx Mauryanx changed the title feat: integrate bounded brain desk and courier notifications feat: add opt-in brain-room and shared voice interfaces Oct 8, 2026
@Mauryanx
Mauryanx merged commit 488a3bd into main Oct 8, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant