Skip to content

Muse parity: best-possible CONDITIONAL — activity nudge, schedules, roles, rooms, honest doctor/health - #95

Merged
XertroV merged 4 commits into
masterfrom
muse-parity
Oct 14, 2026
Merged

XertroV merged 4 commits into
masterfrom
muse-parity

Conversation

@XertroV

@XertroV XertroV commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Top finding

Muse was already at parity on install/uninstall, identity, CLI, MCP tools, hooks plumbing, and managed start. Its one structural gap is upstream: Muse exposes no admitted out-of-process synthetic-turn API (session-message refused, B356 parked), so idle wake from c2c alone is NONE and the honest ceiling is Monitor-CONDITIONAL. This PR closes every c2c-controlled gap and stops every surface from implying more.

What changed (T1–T10)

  • Activity delivery (T1): Stop/PostToolUse now peek and count-nudge. Destructive mid-session drain was tried first and proven unsafe live on muse 1.4.7 (Stop rejects additionalContext in every shape; a PostToolUse drain ate mail during a reminder-subagent window), so SessionStart remains the only hook drain surface and mid-session events can never eat mail.
  • Skill refresh (T2): refresh_muse_skill_if_stale wired into SessionStart (was defined/tested with zero call sites).
  • Default-alias (T3): hook writes it only when unambiguous (no conflicting sid row, no other live session with a different alias) — fail-closed.
  • Schedules (T4): muse added to heartbeat clients; schedules are watcher-owned with/without MCP because the MCP grandchild env is literal-only (the old timer branch was a silent no-fire). One shared decision prevents double-fire.
  • Roles (T5): muse renderer arm at all dispatch sites; no unread role file is written — the role travels via managed kickoff.
  • Rooms (T6): SessionStart auto-joins on the no-MCP path; room list = env > install-written c2c-auto-join-rooms file > swarm-lounge (muse scrubs C2C_* from hook env, so the env knob alone was dead).
  • Uninstall (T7): removes muse-sid-mapping.json + statefile; never deregisters live rows; --dry-run lists leftovers.
  • Doctor/health (T8): no green on a bare install marker; rearm prints the verbatim in-session Monitor instruction per live alias instead of silent success. Wake tier stays CONDITIONAL/NONE — classify_muse_deaf=false pin retained.
  • Docs (T9): overclaims removed everywhere; findings note added.
  • E2E (T10): scripts/muse-parity-e2e.py — isolated legs against the real binary plus a live tmux TUI leg that passes only when the DM token is model-visible.

B098

No sender, no PreToolUse arm, no deliver-watch entry, no new message-triggered action. Mail remains DATA in the existing envelope; the inertness test pair is extended to the new events.

Verification (this branch, this host)

Explicitly out of scope: B356 sender, PreToolUse approval arm (needs spike + B098 review), MCP allowlist (platform-unenforced).

…rooms auto-join

T1: Stop/PostToolUse now peek and count-nudge instead of touch-only.
Destructive mid-session drain was proven unsafe live on muse 1.4.7
(Stop rejects additionalContext in every shape; a PostToolUse drain
ate mail during a reminder-subagent window), so SessionStart remains
the only hook drain surface and mid-session events can never eat mail.
T2: wire refresh_muse_skill_if_stale into SessionStart (was defined
and tested with zero call sites). T3: hook writes the default-alias
file only when unambiguous (no conflicting row for the sid and no
other live session with a different alias). T6: SessionStart joins
auto-join rooms on the no-MCP default path; room list resolves
env > install-written c2c-auto-join-rooms file > swarm-lounge,
because muse scrubs C2C_* from hook env. B098 inertness pair extended
to the new events; mail stays DATA in the existing envelope.
T4: add muse to default_heartbeat_clients. Schedules for managed
muse are watcher-owned with or without MCP: the MCP grandchild env
is the literal install block plus MUSE_SESSION_ID only (proven live),
so the previous C2C_MCP_SCHEDULE_TIMER=1 branch suppressed the
watcher while no timer ever ran — a silent no-fire. One shared
decision function derives both child env and parent mirror, so
watcher and timer cannot double-fire.
T5: render_role_for_client and all dispatch lists gain a muse arm
(unified through C2c_role.render_for_client). Muse is not
file-backed: roles compile writes no file muse cannot read; the
role reaches the session via the managed kickoff string, covered by
a real c2c start muse --agent stub-binary test.
Also add muse to known_agent_process_tokens for pid discovery.
T7: c2c uninstall muse removes the broker-side muse-sid-mapping.json
and muse statefile (fails closed on foreign/unparseable state),
never deregisters live rows or deletes inboxes; --dry-run lists the
leftovers. Install records the c2c-auto-join-rooms file as an owned
artifact so uninstall recompute covers it.
T8: health no longer reports green on a bare install marker. Green
requires a hooks marker from the live set (trusted plugin or the
settings.json fallback); unapproved plugin, denied gate without
fallback, and no-marker installs are yellow, and every message
states live firing is not observed. doctor hooks --rearm prints the
verbatim in-session Monitor instruction per affected LIVE alias
(deduped) instead of silent success; it still arms nothing and
classify_muse_deaf stays pinned false, so exit codes are unchanged.
Remove the same-delivery-guarantees overclaim; muse is documented
as Monitor-CONDITIONAL (NONE at true idle from c2c alone) with
Claude Code and Grok, never GUARANTEED. Document the SessionStart
drain, mid-session peek+nudge, default-alias fail-closed behavior,
watcher-owned schedules, and the auto-join room source order.
Monitor invocations copied verbatim. Add the parity-gaps findings
note (documented/installed-but-inert class) and
scripts/muse-parity-e2e.py: isolated end-to-end legs against the
real binary (install, SessionStart register+join, nudge-no-drain,
CLI surface, doctor/health, uninstall dry-run) plus a live tmux
TUI leg that passes only when the DM token is model-visible in the
pane.
@XertroV
XertroV merged commit 4c0460b into master Oct 14, 2026
2 of 3 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