Skip to content

v0.9.4

Choose a tag to compare

@github-actions github-actions released this 03 Nov 09:38
· 47 commits to main since this release
adbc94b

Added

  • muxa doctor reports the daemon's swap service: taking jobs, shutting down,
    halted by a fault, or unavailable with the reason it did not open (store
    owned by another manager, an incompatible store schema, no node identity),
    read through a new read-only, bounded swap_health request.
  • The muxa_swap_account MCP tool can retry, read (status) and cancel a
    swap job and detach from one. A start or retry runs under a request key
    (the caller's own or one minted before anything is sent) that every result
    carries, errors included, with the call to read the job again; nothing is
    sent twice. muxa swap --status/--cancel take --wait-secs (0-120) to
    return the job as it is rather than wait for its end.

Fixed

  • The swap job journal no longer grows without bound: the effects and
    observations of jobs that ended cleanly more than 30 days ago are pruned,
    at most once a day and in short batches, while every job and target row
    (request key and digest, plan, outcomes, lineage, retry claims) is kept.
    A pruned job says so in --status and cannot be retried; anything
    uncertain or needing reconciliation is never pruned, and a failed run is
    reported by muxa doctor. The journal moves to schema v3 in place; muxa
    0.9.3 and older refuse a v3 journal (swap jobs are then unavailable until
    upgraded) instead of misreading pruned jobs.
  • The daemon no longer keeps every finished swap job's full outcomes in
    memory for as long as it runs: running jobs keep theirs, and only the 64
    most recently ended jobs do too. An older job's status reads from its
    journal, as it does after a restart.
  • A swap answers a relaunched agent's startup dialog only when the screen ends
    in that dialog (its footer, not the agent's own prompt) and only for the
    process resuming the planned conversation; a dialog's words quoted above the
    composer no longer get keys typed into it. A menu is read by its own rows (the
    run at its cursor's column right above its footer); one that could answer
    two dialogs is left alone. Claude's bypass-permissions warning is accepted
    only when the stopped agent's own arguments carry
    --dangerously-skip-permissions as an option and the relaunched process's
    do too, and trusting a folder's settings is never done for the user: the
    swap stops there and types nothing.

Added

  • muxa swap --cancel <key> stops a daemon swap job at its next target
    boundary (nothing running is interrupted); --detach returns as soon as the
    job is accepted. A swap relayed with --host now carries a key minted by
    the caller, so a lost answer can still be followed up.
  • muxa swap --retry <key> retries an ended daemon swap job: only targets that
    failed before their relaunch, while the very agent planned still runs, are
    swapped again (first account, no follow-up); the rest are observed
    read-only and reported. One retry per target attempt, claimed atomically.
    The job store moves to schema v2 in place.

Changed

  • An automation swap_account no longer holds the automation engine while
    it waits for its pane, plans, or runs: it is admitted (at most two at a
    time, one per pane), recorded as admitted and charged to the guards at
    once, and its job's end is recorded under the same operation key when it
    comes. A wait that runs out is waited again rather than recorded as a
    failure, and a restarted daemon follows unfinished admitted swaps to their
    end without starting them again.

  • A swap's follow-up is reported as what the transport said (delivered,
    refused, unconfirmed) and, separately, what followed within 20s: the
    agent's own prompt hook, screen activity, or nothing seen. The old "picked
    the turn back up" no longer claims more than that. Both are journalled and
    shown by --status; a kept session's follow-up is reported the same way.

  • A swap types its follow-up, and puts back the half-typed draft, only into a
    relaunch whose own process arguments resume exactly the planned
    conversation. Otherwise the agent is relaunched and left alone, and the
    report says why (continue_withheld). [swap] continue_evidence = "verified" (or --continue-evidence verified) also requires the
    conversation read from the stopped process and the account confirmed before
    the follow-up; the default binding keeps today's behaviour for a normal
    resume.

  • muxa swap runs as a daemon job when the daemon offers swap jobs: it prints
    a request key, follows the journalled job, and muxa swap --status <key>
    reads it back. Ctrl-C only stops waiting; nothing is re-sent or run locally
    after the request went out. Panes that run their agent directly are swapped
    by the CLI afterwards, bound to the agents the daemon planned. A daemon that
    runs swap jobs but cannot take one now refuses rather than being bypassed;
    --local swaps in-process, and older daemons keep the in-process swap.

Fixed

  • muxa snapshot / muxa restore keep muxa's identity marks. A restored
    window comes back as its Work (and its issue), its session as its workspace,
    and each pane with its role, task and alias, so agents relaunched into it
    are recognised from their first hook instead of appearing as anonymous
    panes in unmanaged windows. Only sessions and windows the restore creates
    are marked, by id once the layout settles — an existing same-named session
    never becomes a managed workspace, and a new window that would inherit a
    different workspace than it was saved under is left unmarked. A target that
    already carries any mark of its kind is left alone, a restored alias is
    dropped if a live peer holds it in that server's room, and worker grants,
    launch and pipeline-attempt markers are never restored.

  • Fleet inbox claims now atomically change only the requests the capped response
    can return. Unseen requests stay queued; primary protection is applied before
    the limit. Older daemons are rejected before claiming instead of silently
    falling back to an unbounded mutation.

  • muxa workers prune --execute refused every Codex worker with "no Codex
    composer on screen": it read the pane with its colour escapes, which hid an
    empty prompt. It now reads plain text, on the pane's own server, and also
    recognises a placeholder a narrow pane cuts short (dim and the start of a
    known placeholder; typed text is never taken for one).

Changed

  • muxa swap resolves a named target or --exclude to exactly one live pane
    first (a bare %81 finds rmux:%81). A name matching no pane, or the same
    %N on two servers, is reported instead of silently swapping nothing.
    Rows seen only on screen are listed by --all/--limited but swapped only
    when named with --force, and never sent a cut-off follow-up. For Claude
    on Linux, the conversation is read from the running process's
    sessions/<pid>.json (pid + start time): it makes an unregistered Claude
    swappable, turns a disagreement with the registry or the command line into
    a reported identity conflict, and is checked again right before the
    stop. Outcomes gain session_id_source, conversation_verified and
    registered.

  • muxa swap --continue "<text>" no longer sends the follow-up to every
    swapped agent. The wording and who gets it are now separate:
    --continue-text sets the text and --continue-when limited|always|never
    the policy (default [swap] continue_when, limited: only agents whose
    turn a usage cap or the swap itself cut off — never idle, finished or
    waiting-for-you agents). --continue stays as a deprecated alias of
    --continue-text and prints a notice; the MCP muxa_swap_account tool
    gains continue_text / continue_when with continue as the same alias.
    Remote --host runs pass the new options, which an older host refuses
    instead of waking every agent; a blank wording sends nothing there too.
    Each planned follow-up records why in continue_reason (rate_limited,
    cut_off, always) — eligibility, not proof of delivery.

  • Starting watch on the Work board or a topology screen loads only open-request
    metadata for hidden mailbox badges; completed-history previews wait until the
    operator opens the mailbox or collaboration screen.

  • Collaboration writes stage only affected rows instead of copying full history;
    identical plain replies are safe to retry without repeating wakes. The Work
    board reuses mailbox revisions and fetches only open-request metadata, while
    Fleet mailbox reads enforce their existing 32-record limit before IPC transfer.
    Shared Codex origins resolve by exact session at the daemon without snapshot
    lookups, and reload mcp --all --reconnect includes current-image shared hosts.

  • Adaptive short requests carry their request ID once in the shared JSON record;
    the reply hint refers to that ID. The body cap is now 768 UTF-8 bytes, still
    bounded by the complete 1024-byte instruction limit. Renderer cost matrices
    cover ASCII, Korean and escaped text, including sender results and reply receipts.

  • Resolved Claude auto-mode setup dialogs no longer leave an indefinitely waiting
    agent: two positive idle-composer observations can repair the exact unchanged
    row, while current permission/selection UI and newer hooks retain priority.

  • muxa dashboard opens muxa watch on its Work board, which now covers what
    the card console did: Enter/o follow the ▸ agent, and c copies and
    K closes it. --since, --sort attention|activity|name,
    --include-paneless and --theme carry over for the run, and so does
    --sort active: ACT/WACT is now attributed per pane and summed over the
    panes each Work holds now (an ACT column and the detail; ? when a pane
    id is on two servers), where the card console split it by
    tmux session name and showed every Work in a session the same figure. The
    card console is removed. See docs/DASHBOARD_CLI.md.

Added

  • Replacement binaries are configuration-probed before MCP handoff or daemon
    restart; rejected binary/config pairs retain the live service. Explicit
    reload mcp --reconnect rebuilds closed cached clients without restarting
    agents, and reports transport health separately from cached revision data.

  • Caller provenance canonicalizes pane evidence from the existing inventory,
    avoiding false rmux origin mismatches without extra discovery scans.

  • Opt-in collaboration.wake_payload = "adaptive" delivers bounded read-only
    peer checks inline to idle workers using the shared inbox instruction JSON,
    removing the initial inbox read while retaining primary protection, quiet
    notices, explicit permissions, and persisted delivery recovery.

  • muxa agent find and MCP muxa_agent_find locate current agents from a
    shared daemon inventory and bounded search index. Layout changes invalidate
    the inventory, concurrent refreshes share a scan, and session-ID lookups
    ignore mentions in other conversations. Ask execution ownership persists
    independently of Ask history and can be promoted by interactive evidence.

  • muxa watch has a Work board screen (Alt-3, :screen board,
    --screen board, [watch] screen = "board"): Works from the same projection
    as muxa dashboard, those that need you first, with goal, issue and every
    Run's agents for the selected one, and Enter to the exact pane of its Run.
    muxa dashboard is unchanged for now. On the board, p/P prompt the
    agent under the Tab cursor or every live agent of the Work and R/A
    interrupt them, with targets fixed when the prompt or confirmation opens and
    results that count unreachable agents; :sort attention|activity|busy|name
    (--board-sort) orders it apart from the topology sort; and the corner shows
    ACT/WACT for all sessions in --since (default today). m messages the
    agent under the cursor (recipient pane and session fixed when pressed; not
    sent to a replacement agent), b opens its mailbox and i/e claim and
    reply as that agent. The watch mailbox gains x to withdraw a queued request
    this console sent. Collaboration targets accept session:<agent session id> and origins accept exact_session, both refusing rather than falling
    back to a pane's new occupant (collaboration_exact_session_v1). The board
    detail counts each Work's open requests to and from its agents, and its
    workers with their long-idle, error and overlap flags.

  • Opt-in versioned collaboration task contracts bind requests to daemon-created
    attempt IDs, exact basis commits and structured reported evidence. Read-only
    supersession retains late replies as history without completing newer work.
    Contract-aware IPC and Fleet fail closed against older daemons; mailbox schema
    v2 is enabled only on contracted writes and prevents older binaries silently
    discarding contract fields. Mailbox load errors no longer silently lose
    persistence through an in-memory fallback; non-schema load failures disable
    collaboration with a health/doctor diagnostic while other services stay online.
    Do not downgrade after using contracts: old daemons cannot read mailbox v2.

  • Reply notifications and interruption recovery follow agent session identity
    after pane moves, so a sender's new pane receives its outstanding replies.

  • muxa agent search / read and MCP muxa_agent_search / muxa_agent_read
    find historical Claude/Codex conversation and command evidence using local
    Korean/English query expansion, event-time filters, source-attributed context,
    and paired tool results. A private resumable index reports partial coverage,
    parse gaps and truncation; transcript files remain unchanged.

Fixed

  • Codex Ask continuation places parent exec options before resume, so
    configured additional directories and sandbox controls work on later turns.
    CLI argument errors retain the actual error instead of only the help footer.

  • Works on rmux (and other non-tmux backends) show up on the Work board.
    Their panes lost the muxa work marks on the way into the Work projection,
    so every such Work was counted as an unlinked execution; muxa dashboard
    also scanned tmux only and showed no Work at all on an rmux host. rmux rows
    are now read with their @muxa_* marks (Work and issue) like tmux rows, so
    only windows explicitly marked as a Work become one.