Skip to content

v0.91.0

Choose a tag to compare

@davidfarah2003 davidfarah2003 released this 21 Oct 21:10
e7eea1a

Cotal 0.91.0 is out!

Grab it: npm i cotal-ai@0.91.0

Changes in this release

  • Add canonical backup restore through the existing guarded restoration and activation path. Return one finite rich, plain or JSON receipt, keep checkpoint progress off JSON stdout, and reconcile connectors as startup does. Restore follows the artifact's selection or an explicit registry-only narrowing, preserves native trust and stopped-cut guards, and never claims per-seat joins. Controller-owned stacks still require their preservation route before they can be restored.

  • Add cotal chat [<channel>], a live session under its own identity in the terminal view, as --plain lines, or as the --stdio NDJSON participant protocol. The command resolves the mesh once and admits the session by that target's recorded auth mode only: a routing identity on an open mesh, a manager-admitted session on a static-auth mesh, and an auth-service session under the signed-in person's cli grant on a user-auth mesh. It never falls back to another mode. A named channel is the session's initial channel, and on an authenticated mesh its whole read and post list. Before admission the command reads the channel registry on the resolved mesh through the one-shot connection and read cotal send uses, and says whether the channel is registered, unregistered or could not be read; it never creates the channel. --name sets the display label, which defaults to the OS login and host with a short suffix. The terminal view refuses without a terminal and names --plain and --stdio; --stdio refuses with --plain, and the command declares no --json. --kind endpoint is accepted and changes nothing, since every admission presents the session as an endpoint; --kind agent and any other kind refuse as a usage error. --role, --link, --token, --creds and --lifecycle-uid are declared and refuse as unsupported until an admission supports them. Signals are held from before admission until the front end handles them, so a session admitted during an interrupt is closed at once and keeps the signal's exit status. A session that ends exits 0 when its close was confirmed, 4 when its retirement was requested and not confirmed, and 3 when the outcome is unknown. Completion offers registered spaces and the target mesh's declared channels. The workspace exports connectTargetOrThrow, the connect half of connectOrThrow for a target the caller already resolved. The flag inventory and the capability census gain the command's rows and the manager's two chat-session commands.

  • The command line resolves, validates and explains a command before it does anything. A usage error (an unknown command, an unknown flag, a missing value, or a first word a command does not declare as a subcommand) now exits 1 before the built-in connectors are seeded or any configuration is written. Before, every command but help reconciled the connector store first, so a mistyped flag installed the connectors and only then printed the refusal.

    • Bare cotal names the selected space, lists the common commands and points a machine with no selected space to cotal setup. It starts nothing.
    • cotal help [command] [subcommand] [--all] prints the command list or one command's or subcommand's help; --help and -h print the same. cotal version prints the version, as do --version and -V. Breaking: -v no longer prints the version and is refused; it is reserved for --verbose.
    • Commands can declare aliases, subcommands with their own aliases, structured outputs and examples. This release adds sp (spawn), a (attach), s (status), r (run), x (ext), h (history) and cotal ext rm. A word is never matched by prefix. The registry refuses a name or alias another command already claims, and cotal ext add refuses an extension whose name or alias an installed extension claims, naming both.
    • Completion resolves an alias as dispatch does.
  • cotal completion reports which shells have the completion stub: for each shell, whether the stub is installed, whether it matches the script this version prints, the stub file, and where completion install wired it in (the startup file holding its install line, or fish's completions directory). --json writes the report as one document and --plain as plain text. A stub or startup file it cannot read is reported with a warning, and the run is partial and exits 4. cotal completion script <shell> prints the stub as raw shell code.

    Breaking: cotal completion <shell> is replaced by cotal completion script <shell>. The old form exits 1 with nothing on stdout, so a hand-written source <(cotal completion bash) loads nothing, and names its replacement on stderr. Stubs installed by cotal completion install keep working unchanged. See the upgrade notes for the line to write instead.

    A usage error now prints the command's help on stderr with the reason, so a refused command writes nothing on stdout. completion install reads an install line only when it is a line of its own, not one that ends in a carriage return, ignores a relative XDG_CONFIG_HOME, and refuses PowerShell and unknown shells as usage errors. It reads the startup file before writing anything, so an unreadable one, a missing directory for it or a relative ZDOTDIR is refused with nothing changed, and a line it cannot add after writing the stub fails with exit 5, naming the stub. writeResult in @cotal-ai/workspace can report a partial read.

  • Add cotal config for personal preferences: harness, persona, detach-key, color and editor. Bare config and config get <key> show the value each key resolves to, where it came from and the values it outranks; config set and config unset change your defaults, or your values for one space with --space (harness and persona only). All four forms take --json and --plain.

    • One resolver decides each key: an explicit flag, the persona's pin, the named variable (COTAL_DEFAULT_AGENT, COTAL_DEFAULT_PERSONA, COTAL_DETACH_KEY, FORCE_COLOR then NO_COLOR, VISUAL then EDITOR), your value for the space, your own value, then the default. spawn (both paths), attach, personas edit and color all read through it, so a saved harness reaches a detached spawn as the caller's default and still yields to a persona pin.
    • Preferences are saved in preferences.json in the configuration directory, private to their owner and versioned. A write holds a lock, refuses with CONFLICT when the file changed after it was read, and replaces the file atomically. A file that does not validate stops every command except help and completion, naming the file; nothing resets it.
    • @cotal-ai/workspace exports the preferences store and resolver, and writeResult can report a no-op.
  • On a controller-owned stack, down --preserve-state, backup create, backup restore and up --restore now refuse UNSUPPORTED (exit 2) while validating, before the confirmation, the connector seed, any write or any manager request, in every stack mode. The remedy names plain cotal down, which keeps the stack's store, channels and history for the next cotal up. Preserve, backup and restore of a controller-owned stack return in a later release. A root without a stack journal keeps its preserve, backup and restore.

  • Bare cotal ext (and ext list) writes one structured document with --json and a plain report with --plain: result.root is the install prefix and result.items the installed extensions. This replaces one JSON line per extension. --json and --plain on the other ext subcommands are refused with USAGE_INVALID, and ext root stays a raw path.

    A subcommand can declare its own structured outputs (Subcommand.outputs in @cotal-ai/core). The kernel reports a form by the 0 to 5 exit table only when that form declares a JSON output, and help prints each form's own structured output line, so ext add, ext remove and ext seed keep exiting 1 on any failure.

    Add cotal docs [<page>], the installed version's own protocol and CLI docs, offline: bare docs lists the pages, a page prints its Markdown, --search <query> shows the best-matching sections, and --refresh also tries the version-pinned copy on docs.cotal.ai and says which copy it served. @cotal-ai/connector-core exports the docs reads it uses (docsIndex, readDocsPage, searchDocs, capSection) through a new ./docs subpath, so the bundle loads only when docs runs.

  • cotal history [<channel>] reads the newest retained messages in the selected space within the identity's read grant, newest last. --limit bounds the read (default 50, at most 1000); --since (a time, an age or a stream sequence), --from and --grep filter that window, and --dms adds DM history for an identity that may read it. The result names the chat stream's per-sender retention limit and each sender at it, so a short history is never shown as complete, and each channel's replay policy for new members. --follow keeps listening; with --json it writes one stream record per line, a snapshot, then one event per message, a gap after a reconnect, and an end record. A channel the identity may not read is refused with PERMISSION_DENIED, and a part that could not be read makes the run partial (exit 4). history clear purges the whole selected space after a confirmation, or with --yes in a script. Extra channel names and read filters are refused before a purge; --dms remains an explicit extension.

    CotalEndpoint.multiChannelHistory now also returns each message's stream sequence, chatRetention() reports the chat stream's per-sender and age limits with each sender's retained count per channel, and channelReplayPolicy(channel) reads a channel's effective replay policy from the registry.

    --since rejects ages outside the supported date range and sequences that cannot be represented without rounding, before connecting. They are usage errors, not unknown outcomes or silently rounded cursors.

    CotalEndpoint.channelHistoryPage reads a newest window through a lifecycle-pinned, single-channel CHAT consumer. Native user-auth history uses that grant without enrolling the human CLI actor in delivery or publishing an ACL mirror. Concurrent readers wait for broker cleanup within bounded read budgets and never delete the shared consumer by name.

    A connected history read that times out or is cut short reports OPERATION_FAILED (exit 5) with its target, not an unknown mutation outcome. Permission and usage refusals keep their existing codes.

  • The manager contract moves to revision 33. While preserved, status.stopImpact reports the preservation attempt and inventory digest. A preserved-exit stop request names that binding with withAgents: false, and the manager accepts it only when fully preserved and quiescent, returning preserved-exit-returned. The open-space local receipt keeps its earlier shape. Each serving manager child writes a protected served-contract file before its serving receipt, so a controller can prove which contract that exact instance serves. New launches pass the resume commit token as a protected file named by path and digest; the deprecated supervise --resume-commit-token input stays accepted. The native manager child takes only the file form. The broker service admits the maintenance work a controller-custody attempt records, and a controller resume names its broker with --name. Core exports recompileContractClosure.

  • cotal ps, cotal models and cotal runtimes write one structured document with --json and a plain report with --plain, and exit by the structured outcome table. A read that could not read part of what it was asked for, such as a manager that did not answer a census, is partial and exits 4, with a warning naming each part it could not read. A mesh a structured command cannot resolve or reach is refused before any request with a stable code (TARGET_NOT_FOUND, TARGET_UNAVAILABLE, AUTH_REQUIRED, PERMISSION_DENIED, DEPENDENCY_UNAVAILABLE and others) and exits 2, and under --json that refusal is one envelope. The user-auth provider names why it could not issue credentials (signed out, service unavailable, refused), so that refusal carries the right code. cotal version --json with an unreadable extensions manifest is now partial and exits 4. A connector's listModels can return unavailable with a reason when its install has no catalog to list; the manager then reports it supported: false instead of a failed read, and OpenCode 2.x does so instead of failing cotal models. An installed connector the manager cannot load makes cotal models partial with its load error, and a home folder reached through a symlink is no longer read as a project with a stopped mesh.

    Breaking: cotal ps --json writes one envelope whose result.items are the manager rows, instead of one row per line. An incomplete manager census exits 4 instead of 1, and a mesh ps or models cannot reach exits 2 instead of 1. The human reports of ps, models and runtimes are tables, and ps --wide prints one record per seat. See the upgrade notes.

  • Read commands no longer install or refresh the built-in connectors and the web dashboard before they run. A command or subcommand declares that it only reads with reads (a new optional field on Command and Subcommand in @cotal-ai/core), and the dispatcher skips the seed for it: status, ps, who, whoami, models, runtimes, history, docs, endpoints, describe, bare space and space show, bare config and config get, and bare ext, ext list and ext root. Installed extension commands keep the declaration through caching and lazy dispatch, including bare reads. Every other command still seeds first, so the first such command after an upgrade refreshes what is installed. The CLI never imports a built-in installed at another version than its own; it names the package and cotal ext seed instead. On a fresh machine status points at cotal setup for the connectors.

    Breaking: a read run right after an install, such as cotal ext list, no longer installs the built-ins. Run cotal ext seed, cotal setup or any command that is not a read. See the upgrade notes.

  • cotal setup takes four inputs: the destination (--destination local|self-hosted), the application (--harness), the project folder (--project) and the space (--space). On a terminal it asks for each one no flag gave, shows the answers before it writes, and offers Save, Change and Cancel; Cloud is listed as in development and cannot be chosen. Without a terminal, or with --yes, --no-input or --json, every input is a flag and a missing one is USAGE_INVALID before anything is written; --destination cloud is UNSUPPORTED. A local space is prepared as cotal space create prepares it; a self-hosted space is one registered here whose root is the project, or one --connection-file registers. Setup seeds the default persona into the project's .cotal/agents, records the application as the space's harness preference, runs that application's own setup actions, and writes one envelope with --json listing every file it wrote. A rerun with the same answers is a no-op. An application whose executable is not on PATH leaves the rest saved and exits 4. --configure-only is accepted and is the default. recordPreparedSpace in @cotal-ai/workspace returns the file it wrote, and meshFile names a space's registry file.

    Breaking: cotal setup --yes without the four inputs is refused, setup sets up one application rather than every detected connector, and a repeat setup no longer prints a status card (cotal status reports the same state). See the upgrade notes.

  • cotal setup sets up the runtimes your agents run in. On a terminal it asks which runtimes to set up after the application question: pty is built in and always set up, and each official runtime (tmux, cmux, orca, herdr) and each installed third-party runtime shows whether it is set up and whether its host tool is on PATH. Installed ones and ones whose tool was found start selected. A script names each runtime with --runtime <name>, repeatable; without it a script sets up no runtime beyond pty. An unknown name is USAGE_INVALID and an official runtime whose host tool is not on PATH is DEPENDENCY_UNAVAILABLE, both before anything is written.

    Setup installs each chosen runtime as cotal ext add does, at the running cotal's version, then asks its provider whether it answers, as cotal runtimes reports. A chosen runtime whose host tool is missing is not installed, and one that does not install or answer leaves the rest saved and the result partial (exit 4). Setup never removes a runtime left out; cotal ext remove does. result.runtimes lists each runtime with its package, its host tool, whether it was chosen and whether setup found it set up, added it or left it out. With --json or --plain the install progress goes to stderr.

    cotal ext add of a @cotal-ai/* package named without a version now installs the running cotal's version instead of the registry's newest, which could be a release the binary does not match. A version or tag you name is installed as given.

  • cotal space add and cotal space forget register and forget spaces on the structured output contract.

    • cotal space add <name> --server <url> registers a space that runs elsewhere, with the trust under --root. cotal space add --file <bundle.json> registers a user-auth space from a connection bundle, and --from <https url> fetches its discovery document on a terminal. Every check runs before anything is written, and each refusal carries its code: CONFLICT for a registered name or a broker that enforces another mode, TARGET_UNAVAILABLE for a broker that does not answer, DEPENDENCY_UNAVAILABLE for missing trust, UNSUPPORTED for an address credentials may not cross. On a terminal it shows what it will trust and asks; --yes skips that question. It never changes the selection. --force replaces only a registration added by hand. With no --root, a home folder reached through a symlink is refused like the home folder itself instead of being recorded as the root.
    • cotal space forget <name> removes a registration this machine keeps, and keeps the root's files. It refuses a space this machine is running, including one whose controller stack has a member that may still run, and a space a catalog lists. A stack member that is gone without its stop receipt does not block, and the result warns that it was never stopped cleanly. Forgetting the selected space clears the selection.
    • A registration check from @cotal-ai/workspace can carry its refusal code, and preflightCode is exported.
  • cotal space create <name> [--root <dir>] prepares a space to start on this machine.

    • It records the name and root, and makes <root>/.cotal/, so cotal up in that root starts the space under that name and drops the prepared record. It starts nothing and keeps the selection. It refuses with CONFLICT a name that is registered or prepared, a folder that is already a space's root, and the home folder.
    • cotal space lists prepared spaces under their own heading, and cotal space show, cotal use and cotal space forget accept one. cotal space add refuses a prepared name.
    • A command that targets a prepared space refuses with TARGET_UNAVAILABLE, naming the root to start it in, before anything dials an address. cotal up --space <name> from another folder refuses before it writes anything.
    • @cotal-ai/workspace keeps prepared spaces in their own store under ~/.cotal/prepared, apart from the mesh registry, and target resolution reports one with the not-started code.
  • Add cotal space and cotal space show [<name>], and put cotal use on the structured output contract. space lists the registered spaces with each broker's state, server, mode, origin and root, and never dials a discovered space; space show gives one in full, the selected one by default, without its credential paths. Both take --json and --plain, and their rows match cotal status --json.

    • cotal use <space> selects any registered space without checking its broker, refuses a name that is not registered with TARGET_NOT_FOUND (exit 2), reports a repeat as a no-op, and bare cotal use reports the selection. A selection that names no registration is reported with a SELECTION_NOT_REGISTERED warning.
    • A command run without --space targets the selection: when its broker is down it refuses with TARGET_UNAVAILABLE, and a selection that names a space no longer registered refuses with TARGET_NOT_FOUND. Neither falls back to another mesh.
    • @cotal-ai/workspace exports brokerAnswers, and a MeshTargetError for a dangling selection carries selected: true.
  • cotal status writes one structured document with --json and a plain report with --plain, and exits by the structured outcome table. The report keeps its order (this machine, extensions, this folder, the recorded meshes, the selected mesh) and ends with the hints. Only the selected mesh is checked unless --all asks for every recorded one, and a part status cannot read is named on its row and makes the run partial. That includes a persona catalog, the current-mesh pointer (an empty one included), the mesh registry directory and each of its records: the readable records are still listed. @cotal-ai/workspace adds readMeshRegistry, readCurrent and MeshRegistryError for those reads.

    Breaking: bare status exits 4 when it could not read part of what it reports, instead of 0. The recorded meshes other than the selected one read not checked without --all. The report lists no roster, and --components is refused with --json, --plain or --all. See the upgrade notes.

  • Commands share one structured output contract, and every command takes --no-color and --no-input.

    • cotal version --json (or -j) writes one JSON document on stdout: schemaVersion 1, the command, a null target, the outcome, completeness, the result (the version and each installed extension's), and warnings. A usage error under --json is one refused document with code USAGE_INVALID and a remedy, and the help it names stays off stdout. A command with no JSON output refuses --json as an unknown option.
    • A command that declares a JSON output exits by its outcome: 0 for ok or no-op, 1 for a usage refusal, 2 for a refusal at a known boundary, 3 when the outcome is unknown, 4 for partial, 5 for failed. An error such a command does not classify is unknown. Other commands keep exiting 1 on any failure.
    • @cotal-ai/workspace exports the envelope and NDJSON record types, the stable error codes, the outcome-to-exit table, and CommandFailure, which keeps an endpoint's own code and outcome under error.cause.
    • --no-color turns color off for that run, including the setup prompts and the console, whatever FORCE_COLOR says; the programs it starts are no longer forced into color by FORCE_COLOR. --no-input means no prompt, editor or browser: a prompt behaves as it does without a terminal, cotal web prints its link without opening it, and cotal personas edit is refused. --json implies --no-input. Both flags work before the command word, and after it on any command that does not take its words raw. No command may declare either name: an installed extension command that does is an internal error, and cotal exits 1 before running any command.
    • cotal console now follows a non-empty NO_COLOR, as the rest of the CLI does.
  • A command picks its space the same way in every surface, and says what to do when it cannot.

    • With no --space, --server or --creds, nothing selected and no project in the folder, a command that several running spaces could serve asks which one on a terminal. The answer targets that one run and leaves the selection alone; cancelling exits 0. A script, --json and --no-input still refuse with TARGET_AMBIGUOUS.
    • A refused target, a broker that does not answer and refused credentials carry what to run next in error.remedy, apart from error.message. The one-line wording elsewhere is unchanged apart from punctuation.
    • cotal up -f and cotal spawn -f refuse a --space that names another space than the manifest's, before anything is written. Before, --space replaced the manifest's space.
    • cotal sync writes one envelope with --json and a plain report with --plain. An account whose catalog could not be refreshed is named in a CATALOG_UNAVAILABLE warning and makes the result partial (exit 4); when none could be refreshed it refuses with DEPENDENCY_UNAVAILABLE.
    • @cotal-ai/workspace exports workspaceErrorParts, and a ConnectRefusal can carry its message and remedy apart.
  • Add cotal who and cotal whoami. who lists the live roster of the selected space with each participant's status, condition, activity, attention, harness, model and host, and whether a manager runs the seat; --waiting keeps rows that are waiting or report a condition and --all adds infrastructure endpoints. whoami reports the identity the CLI acts under in the selected space and what it may read, post and do, without connecting. Both write one structured document with --json and a plain report with --plain; a part they could not read makes the run partial (exit 4), and a roster the identity may not read is refused with PERMISSION_DENIED. who watches the roster on every mesh so it can report an unfinished snapshot, a stale roster and a watch error. On a static-auth or user-auth mesh each run's watch consumers stay on the broker for five minutes after it exits. A manager census the identity's grant does not reach, such as a user-auth user's, is labeled with a warning and leaves the run complete.

    For a remote user-auth registration, a cached login remains a login even when the owner and grant cannot be derived on this machine. whoami reports the grant as unknown and partial, leaves the owner and principal null, and does not tell that user to sign in again. Human output labels the cached login and its advisory expiry.

    whoami also skips dispatcher catalog refresh, so a cached login and an uncached catalog do not make this local identity read contact the IdP.

    Broker addresses in identity reports and shared connection-failure messages omit URL user information, query strings and fragments. Stored connection values and connection behavior are unchanged. An unparseable address is refused by whoami without printing it.

    Use a URL placeholder in auth-mismatch recovery instructions rather than a display address with connection data removed.

    Validate display addresses as broker addresses before returning an unchanged value, and escape terminal controls. Preserve bare hosts, IPv6, TLS and WebSocket routes without changing stored or dialed values.

    Classify malformed local registry data as SCHEMA_INVALID before any read request, without printing its stored field values. Include the roster suite in the Linux, macOS and Windows platform matrix.

  • Report cotal actor grant and cotal actor revoke honestly when the actor row changes or disappears while the predecessor's lifecycle retires. When the auth service reports that the command retired the lifecycle, the command now ends partial (exit 4) with the retired lifecycle under changed and a remedy to re-read cotal actor list, instead of unknown (exit 3). When the service reports that the lifecycle never started or was already retired, or the row has no lifecycle, the command retired nothing, so the same race refuses with CONFLICT, as does a first grant that finds another grant landed while it waited for the ledger lock. A retirement answer without a readable result now ends unknown before anything is written, instead of letting the grant or revoke continue.

  • Make the auth commands agree with each other and classify their refusals.

    • cotal actor list, grant and revoke now resolve their space and root as cotal auth grants, grant and revoke do. With no space to resolve they refuse with TARGET_NOT_FOUND instead of assuming main, and on a root without the space's user-auth ledger actor list refuses with UNSUPPORTED instead of reporting no rows.
    • Grant usage is checked before any space or authority is read, under both spellings. A grant or revoke missing --sub or --owner, or a grant missing an ACL flag without --full, refuses with USAGE_INVALID (exit 1) and names every missing input in one refusal, where actor grant used to end with exit 5 and auth grant named one input per run. actor also refuses a flag that does not belong to its verb, as auth does.
    • cotal login against a provider that cannot be reached or stops answering refuses with DEPENDENCY_UNAVAILABLE (exit 2) and a --idp remedy, instead of printing the raw transport error with exit 1. No session is cached.
    • cotal doctor auth reports every credential with no expiry claim as a finding, including an agent credential that cotal auth mint wrote without --expires-in or --expires-at, so that root no longer reads as having no findings. The mint default is unchanged.
  • Refuse cotal actor grant and cotal actor revoke plainly when the predecessor's lifecycle retirement did not run. When the auth service is not running, refuses the connection, or answers that the retirement did not run, the command now refuses (exit 2) with DEPENDENCY_UNAVAILABLE, PERMISSION_DENIED, CONFLICT or UNSUPPORTED, says the actor row was not changed, and names the recovery, usually cotal up. It used to report every such failure as unknown (exit 3). The auth service's /interactive-lifecycle/retire door now answers every refusal it makes before the retirement barrier, its token checks and authority head read included, with outcome: "not-executed". A retirement request that may have reached the barrier, such as a timeout or an error answered without that outcome, stays unknown, now with its own reason.

  • Attribute stream initialization and registration failures to the already-started broker instead of the next unstarted member. Preserve typed JetStream numeric API codes and status without exposing arbitrary broker error descriptions, retrying effects or treating an unknown startup as complete.

  • Start every npm child of cotal update, cotal ext add and setup's global install with 022 added to the process umask, and create a missing extension prefix with mode 0755 and its package.json with mode 0644. Under a umask of 0002, npm made group-writable directories, files and bin targets, and its own --umask setting still left package directories and bin targets group-writable. A stricter umask keeps its bits, and the previous umask is restored as soon as each spawn call returns.

  • Add static-mode chat session admission. A static manager serves chat-session-open and chat-session-retire (cluster revision 34): it draws a chat_ alias and a fresh nkey identity, provisions the session over the native static activation with a spawn's three channel lists under a spawn's rules, and mints an agent-profile leaf with no role, capabilities, endpoint rows or issuance, expiring within 900 seconds with no renewal. The manager writes the leaf's credential ledger row itself before it leaves the process. The reply carries no credential in the clear: the leaf is sealed to a one-time curve key the caller sends as sealTo, bound to the space, the admitting instance and the reply's fields, so a generic invoke, an agent or a browser sees only ciphertext. Retirement runs the static terminal and refuses any alias, instance, uid or actor it did not admit. It marks the credential's ledger row revoked and verifies that the session's principal has no live connection, but a static mesh cannot revoke the leaf itself, so a copy of it still connects until its expiry. The admitting manager retires each session it admitted at that expiry when nothing retired it sooner, retires every session it still holds when it stops without preserving its state, and its startup sweep leaves alone a session it is admitting or holds. Only operator instruments carry the two command rows. An ordinary spawn now refuses names that start with chat_. The workspace exports mintControlInstrument, which mints a control-caller instrument for a target the caller already resolved. Core adds sealJson, SealRecipient and isCurvePublicKey, one-time sealing over the existing NATS curve keys. The CLI gains the static chat adapter, which opens the sealed reply once and checks every bound field, keeps the leaf in memory, mints every manager call from the target it was opened on, and retires at the admitting manager instance. The CI suite list gains the two new smokes.

  • Allow ordinary shutdown of a legacy stack after its restore has reached the validated active state for the registered space. Keep pending maintenance transitions, mismatched spaces and all existing root, ownership, sharing and native process guards blocked. Shutdown preserves the restore journal and fallback store.

  • Terminal output reads cleanly at any width.

    • On a terminal, long report values and lines, warnings and failures wrap at spaces, each continuation line under the text it continues; a word wider than the line, such as a path, is never split. Output to a pipe or a file is not wrapped.
    • Help, the command list and the entry screen wrap the same way. A usage line breaks only between options, and when the flag names leave their descriptions fewer than 30 columns, each description goes on the lines under its flag.
    • --plain writes punctuation in ASCII: · and long dashes as -, … as ..., → and ↳ as ->, and § as section. A partial result's line starts with !.
    • A table too narrow for the terminal becomes one record per row whose labels are lowercase like every other report's, and a field the row leaves empty is left out. ps --wide labels its records the same way.
    • history --follow wraps each new message to the terminal, as the window above it is.
    • The status membership feed row says how long ago the feed was updated instead of printing its ISO time; --json keeps the time.
    • cotal completion fills every cell: a shell with no install line says not wired in, and PowerShell's file says none.
    • The help for --on and ps --slots says what they do in plain words.
  • Record managed-grant custody and serialize ledger reads, decisions and writes in one synchronous transaction. Bind conditional revocation to the lifecycle and custodian, preserve legacy row reads without adopting them, and define the lease-first optional retirement-only composition. Full recovery authority is not enabled.

  • Accept group write on a protected directory, or on a declared service adapter path, when the account database proves the group is the caller's user private group, the Debian and Ubuntu default under umask 0002. On Linux, getent must show that the group is the caller's primary group, lists no other member and is no other account's primary group, and getfacl must show no extended ACL on the entry. The account list counts only when /etc/nsswitch.conf names files and systemd alone for passwd and group, so a directory source such as LDAP or SSSD refuses. Each read is bounded, and only a proven group is remembered for the life of the process. World write, a foreign owner, a symlink, an extended ACL and an unavailable proof still refuse, and a credential file stays owner-only. A refusal now names the offending path, the reason and a chmod remedy, and says what kind of path was checked instead of calling every path a credential reference. The installer sets umask 022 before it creates anything.

  • Add closed user-mode chat row, holder-index, quota and parent-pin foundations, and optional chat session methods to AuthProvider. Interactive and managed grants refuse aliases already present in the chat row space. Admission and public chat entry are not wired by this foundation.

  • Apply the new terminal screens to status, help, settings, setup receipts and inventories. Add compact action guidance, command shorthands, named agent details and the live observer. Group guarded manager maintenance and channel metadata operations under their new command names.

    Validate the public recipient and agent-target arguments before installation or catalog preparation.

    Support explicit message file/stdin input, channel mentions and direct replies with non-echoing structured storage receipts. Show broker-derived channel membership without treating it as access or task progress.

    Consolidate workflow reads, file-based launches, offline language tools and own-seat turn handling under run/r with explicit source and outcome labels.

    Add account-provider selection, private device-approval guidance, structured sign-out receipts and a non-installing update availability report.

    Expose native managed-launch readiness and original request/goal attribution, verified self stop,
    hard despawn and manager supervision flags. Add non-echoing native terminal-input receipts,
    authorized endpoint contract/invocation reports, the full read-only watch view family, partial
    recorded team reads and account/actor authority reports. Keep unestablished live state explicit.

    Share protected owner-private local record access between endpoint references and service
    definitions. Add case-safe per-space service definition inventory, guided/file import, policy
    reports and guarded local removal, keeping existing process observations distinct from owned
    instances and serving readiness.

    Resolve saved endpoint targets through the canonical describe/invoke namespace. Pin the local
    reference revision through native calls, disclose the resolved target and preserve exact instance
    selection without broader-caller or class-queue fallback.

    Read authorized native endpoint registrations with explicit bounded-lag enumeration, leader-read
    coordinates and partial results for unreadable or omitted keys. Keep registration, reported status,
    process ownership and current serving responses distinct.

    Add the guarded history-clear screen with default-cancel scope review, explicit scripted confirmation,
    offline dry-run and per-stream native purge receipts. Preserve acknowledged partial work and unknown
    submissions without retrying destructive requests.

    Expose digest-verified action metadata to clients and add native endpoint action following with
    --wait. Retain original requests and accepted goal identity, use accepting-instance reconciliation
    and emit explicit bounded goal stream records without resubmitting an unknown action.

    Apply the shared report treatment to classified failures and expose safe original-request, accepted-
    goal and responder attribution without copying raw argument or native-detail objects into reports.

    Make spawn --file select a persona on its execution host, with the native shared manifest schema
    providing the team-deploy refusal. Add non-launching offline preview reports and a protected explicit
    foreground enrollment-file input without changing native launch fields or adding wire authority.

    Add a Linux process-service driver with machine/boot and process-creation ownership, exact
    instance selection, explicit multi-instance launch, bounded readiness/log reads and guarded
    stop/restart/removal. Distinguish owned process presence and HTTP reachability from endpoint
    serving, retain uncertain launch receipts and never fall back to PID-only or remote controls.

    Add ownership-aware completion installation, refresh and removal with finite JSON/plain receipts.
    Keep custom and modified shell material, preserve the stable offline dispatcher and refresh only
    existing recorded stubs through the current-generation updater without adding startup wiring.

    Add offline endpoint contract scaffolding and checking through the installed native cluster/schema
    compilers. Create files exclusively, derive digests from schemas and keep handler execution,
    serving authority and opaque attribute/event semantics separate from local validation.

    Expose native ephemeral endpoint casts with pre-publication journal refusal and non-execution
    receipts. Keep original request/binding attribution, broker denial and unknown outcomes distinct.

    Expose target-bound account signer export under auth signer with required protected output,
    inspected same-account replacement, public-only receipts and no operator-root or caller issuance.
    Share protected workstation file access across the credential, endpoint and service frontends.

    Add protected, explicitly unverified handle metadata inspection without signatures, redemption or
    caller issuance. Resolve literal nested help and scoped aliases through declared metadata while
    keeping help offline and provider imports behind validated execution.

    Move static credential minting into auth mint through a registered implementation action, with
    one shared flag grammar and public-only JSON/plain receipts. Keep source-root authority/profile
    checks, native provisioning and expiry metadata, use create-only default labels and explicitly
    report a reused nkey's new out-of-band lifecycle instead of claiming its old inbox was retained.
    Reject the top-level mint spelling before effects and keep explicit exports out of managed state.
    Name both roots when the selected root and current folder disagree about the signing authority.

    Expose one-shot native endpoint class scatter with frozen-set reconciliation, attributed member
    results and every native anomaly bucket. Keep pinned/targeted/journaled calls off this route,
    preserve classified mixed/unknown outcomes and retain useful result data in finite failure reports.

    Add exact-manager persona list/show/create with native ownership checks and bounded complete-file
    merging. Refuse unsupported metadata before submission, retain the actual responder/request and
    separate a confirmed save from a denied or unknown optional announcement without retrying it.

    Expose exact-target endpoint deregistration through the existing native guard as a registered
    operator action. Require a reviewed full class/instance, preserve TLS and selected static authority,
    refuse unsupported auth fallback, keep dry-run offline and report native deletion revisions or
    uncertainty without retry. Turn the old default-instance spelling into a pre-effect migration refusal.

    Add finite private-backup creation receipts after native cleanup, read-only manifest inspection
    and size/SHA-256 verification without staging or restore claims. Expose exact-attempt recovery
    and healthy fallback cleanup with default-cancel review, offline plans, revision rechecks and
    native owner/identity guards. Keep confirmed publication and incomplete cleanup distinct.

    Add public-only JSON/plain feedback receipts with bounded response metadata, explicit unknown
    submission outcomes and no redirect or retry. Accept protected key-file input, refuse raw keys on
    argv and keep submitted bodies, contact values, credentials and response text off diagnostic output.

    Move credential diagnosis and native static daemon repair onto shared JSON/plain reports. Add
    nonmutating observation intent at the existing local migration boundaries, retain acknowledged
    path moves/re-signs separately from adoption, keep prior broker refusals visible and avoid live
    agent or open-mode claims from absent/local credential files. Never expose secret fingerprints or
    raw credential/audit parser diagnostics in the new reports.

    Evolve workstation local-process providers with a versioned service ABI, closed bounded option
    schemas and package-bound cached declaration fingerprints. Validate definitions without provider
    imports, then route explicit adapter launches through the creation-pinned direct-process
    controller. Retain adapter provenance, exact native readiness coordinates and unknown hook
    outcomes. Check declared capabilities and keep service launch intents behind extension-removal
    guards without introducing wire grants, manager impact bypasses or implicit dependencies.

    Add declarative service presets with schema-derived parsing, scoped help/completion and guided
    creation. Validate declared protected path references without reading contents. Expose the native
    feedback-intake preset through the shared controller, using the guarded same-binary re-exec and
    existing intake implementation. Correlate post-listen startup with the exact child/launch,
    preserve TLS and private append-only storage, keep credentials on file references and refuse
    the former top-level intake launcher before effects. Separate controller-only providers from
    legacy PID inventory and retain startup/data receipts without claiming endpoint serving.

    Expose the independent delivery preset through its own registered local-process provider, using
    shared workspace custody metadata instead of an implementation import. Retain the native scoped
    store, SYS account scan, singleton lease and TLS checks, refuse legacy custody adoption and
    publish startup only after native readiness. Share private child-bound startup receipts and
    public-only target resolution between native adapters, while preserving the workstation path
    context without inheriting arbitrary credential or agent identity environment values.

    Expose caller-scoped manager stop-impact observations through the native status contract. Reuse
    its actual runtime seat policy, retain owner filtering and show pending lifecycle/retirement work
    without treating an observation as stop authority, a reservation or completed cleanup.

    Put manager gate repair and retained-seat maintenance on shared JSON/plain reports and default-
    cancel confirmations. Preserve the registered target/TLS policy, classify uncertain submitted
    effects without replay and separate native gate/custody receipts from serving or cleanup claims.

    Apply scoped grammar/help and shared account, inventory and native-request reports to Linear.
    Keep native MCP isError results distinct from unknown execution, bound human output without
    truncating JSON and preserve its existing serving/caller authority during the pending transitions.

    Give existing native Linear caller issuance a private create-only output preflight and shared
    receipts. Preserve original identity/lifecycle and uncertain provisioning/publication without
    replay, broader caller substitution, managed-launch claims or environment-export onboarding.

    Keep direct-service supervisor assignment distinct from unperformed OS discovery in instance
    and preview reports; a recorded none does not claim external supervision is absent.

    Prepare private, request/process-bound native stop handoffs and immutable phase observations.
    Keep cleanup unverified and existing reservations untouched; manager service control is not
    activated by these primitives alone.

    Expose the manager embedding's own registration/policy observation without exporting credentials,
    URLs or grants. Keep it distinct from fresh serving evidence and wire caller authorization.

    Provide a public-only native manager identity callback before endpoint construction and expose
    its actual per-process UID in status. This supplies launch-correlation data without treating
    identity metadata as serving readiness, ownership authority or a generic caller grant.

    Prepare private native identity bindings before endpoint construction. Preserve dotted endpoint
    class names under the native validator, keep epochs out of pre-serving identity data and require
    a separate attributed response before any serving or process-control inference.

    Add the native manager service preset with pre-endpoint identity binding, post-start signal-ready
    receipt and invoking-caller readiness/impact observations. Show the full native seat consequences
    before default-cancel confirmation and bind the unchanged scope to the live native reservation.
    Require immutable accepted/returned evidence plus original process exit before a stopped record;
    retain unknown requests without force kill or restart, and leave cleanup unverified. Keep generic
    and legacy signal paths from bypassing this boundary. The child never publishes its console URL.
    Foreground, OS-supervised and non-Linux manager service operation remain unsupported.

    Add the prepared native auth-service preset with shared daemon inputs, exclusive real-child PID
    custody and a private post-initialization startup receipt. Keep discovery capability and key
    material native and private. Refuse existing custody, remote brokers and TLS-required targets
    instead of reclaiming a daemon, weakening transport or generating new issuer material. Keep
    foreground/OS-service operation unsupported.

    Add the Linear service preset over the existing account, native static registration and renewal
    implementation. Bind its explicit root/registered transport and publish a private handler-
    initialization phase only after shutdown handlers exist. Keep process/initialization evidence
    separate from broker flush, fresh endpoint response and native deregistration completion. Refuse
    unsupported issuer/foreground/OS-service modes without substituting authority.

    Show checked installed preset metadata and declared readiness/foreground/instance/stop capabilities
    in service inventory. Keep unavailable or mismatched metadata partial with explicit warnings;
    metadata validation is not application readiness or OS-install support.

    Prepare full-instance/definition/host-bound supervisor receipts and non-echoing recorded-unit
    file observations. Keep loaded OS state/autostart unchecked, preserve missing/modified receipts,
    and refuse direct process controls or removal beside a recorded supervisor. OS installation and
    native unit control remain unimplemented; no unit is created or enabled by these readers.

    Claim the managed manager child's real native PID custody exclusively before endpoint startup,
    without adopting a contender or treating a starting record as readiness. Settle the same process
    and retain owner-bound release after native start; keep legacy entry behavior separate.

    Add bounded same-host status reads for unchanged recorded systemd user units. Report physical
    fragment, native states, invocation and exact process/launcher attribution without unit or
    environment bodies; keep missing/ambiguous/drop-in observations partial. Status does not reload,
    start/stop a unit, infer endpoint readiness or prove effective autostart.

    Prepare a built-in direct-process unit boot entry with complete controller/definition/instance
    validation before extension overlays, repair or package materialization. Require the recorded
    native invocation before same-PID process replacement, refuse managed-spawn handoffs and retain
    unknown starting evidence without retry. This does not install units or prove execution/readiness.

    Declare auth and Linear foreground service lifetime through the shared owned-child controller
    and native shutdown handlers. Print lifetime/output policy before launch, retain manager's native
    impact requirement, and prevent native service child boot from repairing connector packages.
    Process exit still does not prove endpoint, descendant, registration or authority cleanup.

    Route recorded systemd service logs through bounded native journal reads/following pinned to the
    original unit invocation, boot and UID. Preserve native cursors/timestamps and binary JSON, report
    record/query/diagnostic gaps, close only the reader on interruption, and refuse missing invocation
    evidence without substituting a direct-child file. Journal retention and cleanup stay unestablished.

    Expose the service install/uninstall paths with the same exact definition/instance
    selection and a typed unsupported boundary where native OS control is missing. Never route them
    through the old manager-only installer, allocate a stopped record or change autostart on refusal.

    Expose auth redeem with closed per-mode input and the selected native auth target. Refuse
    unsupported conferring-handle redemption before reading the file or spending authority, rather
    than substituting agent enrollment, session redemption or unverified artifact parsing.

    Move the dashboard package from its public command to an owned service preset with explicit
    protected static credentials and read-only intent. Preserve native HTTP/cookie/origin behavior,
    registered TLS, exclusive PID custody and private full-launch bootstrap records; publish only
    process initialization and non-secret reference paths. Refuse unsupported user-auth/open/OS
    routes without operator identity or mutation-transport fallback. Hide obsolete cached web commands
    and refuse them with an explicit matching-update remedy before loading code or repairing installs.
    Keep legacy process observations separate and migrate setup, tool hints and dashboard guides.

    Add auth mint --endpoint with closed channels/expiry/private-output inputs and the shared static
    signing-authority checks. Resolve a live digest-verified untargeted synchronous ephemeral surface,
    then use the native agent provisioner for its exact additional command rows and lifecycle footprint.
    Refuse targeted/journaled/action scopes without omitting rows. Publish a create-only non-secret
    issuance intent before native footprint work, block blind replay, preserve private output checks
    and report temporary provisioner close separately. Do not add spawn/run/admin authority, user-auth
    issuance, arbitrary raw-file caller derivation, managed launch or environment-export onboarding.

    Expose exact auth retire grammar with a typed unsupported boundary until a caller-owned native
    serve-gate retirement instrument exists; never borrow manager identity or use host loopback doors
    as a substitute. Prepend native journal reader output-close handling before the binary's global
    EPIPE exit; final stream output and reader cleanup remain observations, not assumptions.

    Show endpoint caller scope in the shared receipt: actual caller/lifecycle, described owner and
    responder, native expiry, explicit channels and bounded command rows with a JSON-preserving
    omission count. Label the local issuance request separately from native provisioning evidence.

    Consume paired native standalone endpoint caller files through registered static targets and saved
    references. Verify signatures against current validated issuer pins, matching user keys/time windows,
    native permission projections and principal tags before broker admission. Retain TLS and private
    snapshots; refuse arbitrary/profile/versioned/targeted/instance/scatter/admin/action authority without
    operator fallback, binding repair or unknown-effect replay. Show public caller binding and described
    file-scope limits in shared reports. Share the local intent contract with issuance and validate
    explicit dashboard credentials against the selected issuer before PID custody or initialization.

    Declare the endpoint watch/session/work and invocation handle paths with closed mode
    inputs and typed unsupported boundaries while native declaration/auth-slot adapters are absent.
    Refuse before broker/file access or subscription, cursor, session, lease, commit or redemption;
    never infer a generic subject, remote execution, verified attenuation or broader caller authority.

    Route one named down target through the existing owned-service stop controller and retain its
    native identity, confirmation, reservation and manager-impact policy. Keep down-labelled finite
    receipts, full-instance selection, offline preview and saved-definition completion. Refuse
    multi-service sets before effects until whole-set preflight exists, reject named agent-reap flags
    with the explicit manager-service remedy, and never fall back to a legacy component PID. Reject
    new receipt/acknowledgement flags on the bare-stack/manifest paths.

    Expose the existing direct endpoint/workflow stream definitions through one pure native config
    factory consumed by bootstrap. Retain creation order, options, retention-floor checks, independent
    ownership census and existing contract/authority hardening; do not add schema mutations or schema
    apply.

    Add a pure conservative diff for that native stream subset. Preserve not-observed, denied,
    not-found-without-authoritative-absence and target-mismatch states; compare only explicit fields,
    retain uninspected defaults and never emit creation/migration actions or enable apply. Add no
    full-space schema observation, authority policy or privileged reconciliation.

    Share native message/registry, contract, authority/session, issued/admission, membership and artifact
    creation inputs with a read-only resource catalog, retaining the existing TTL source, native guards
    and independent inventories. Keep SDK defaults, complete canonical policy, seeds/default delivery
    and reconciliation authority unestablished.

    Add a narrowed native stream-info facade and internal resource observer with structured SDK
    error classification, no message matching, credential substitution or authoritative absence.
    Share declared-field comparison with the endpoint subset; keep native KV/object verification
    required, expose uninspected fields and always disable apply.

    Share native registry seed ordering and profile-default patches with explicit no-write initialization
    definitions. Preserve seed-before-profile precedence and existing explicit delivery classes. Keep
    validation, strict revision observations and guarded application separate; do not infer a profile,
    expose patch bodies in diagnostics or claim legacy seeding gained revision safety.

    Share pure native contract, authority/session, issued/admission and artifact config checks between
    existing creators and schema comparison. Retain the guarded shadow/legacy-cap migrations outside
    readers, never run TTL write canaries during diffing, suppress raw native failure text and distinguish
    uncompared fields, unconfirmed checks and invariant matches from complete canonicality or authority.

    Add bounded read-only initialization observation over an existing selected registry handle. Validate
    native profile/patch inputs before key reads; retain revisions and tombstones and keep missing,
    denied, unavailable, malformed, mismatched and unvisited rows distinct. Preserve private values,
    explicit deadline/non-cancellation and incomplete field-policy labels. No bucket open/create,
    credential fallback, revision-guarded write plan or apply authority is introduced.

    Prepare a read-only existing-static schema inspection adapter with upfront native input validation,
    strict registered root/server/TLS selection, validated current full trust and one native temporary
    provisioner identity. Keep native mode/floor and registry read failures, private observations and
    local reader closure explicit. Do not expose mutation ports, substitute other authority, promote
    reported server metadata to account proof or connect an incomplete apply/public command path.

    Share the existing pure primary/Limits/no-global-eviction authority-store check through core for
    schema inspection and native lifecycle binding. Preserve the auth module's sibling import surface,
    existing checks and error class/text. Move no lifecycle/gate operation, connection, grant or repair
    into core, and keep complete field policy and apply authority separate.

    Attribute the first failed native primary/no-eviction invariant to structured field names from the
    same ordered check. Keep native diagnostic text private to its existing bind error, preserve its
    class/message and avoid parsing or echoing exception strings in schema reports. Field attribution
    is not full canonical policy, current binding, write authority or a completed migration.

    Prepare explicit registered open-mode schema inspection alongside static mode. Select the mode
    before connection, preserve registered TLS, load/mint no open-mode signer or identity and require
    the reported broker authentication mode to match. Keep user-auth unsupported, never retry an auth
    refusal anonymously, and retain private reads and disabled apply without public command wiring.

    Compare extra observed direct-stream fields with the existing first-party baseline, without
    normalizing absent settings from desired values or copying private SDK defaults. Classify
    nondefault undeclared/unmodeled settings as blocked and expose field names without their values.
    Reuse reserved NATS metadata policy; do not add KV/object expansion, full policy or apply.

    Prepare a public-only schema inspection projection and shared terminal view without connecting an
    incomplete public/apply path. Show target/profile, non-atomic resource/key observations, revisions
    and safe policy-field attribution. Omit raw configs, registry/patch contents, unknown field names
    and native diagnostics; retain unproven absence, incomplete policy and disabled apply labels.

    Add one bounded native NATS current-connection identity query and the temporary provisioner's
    self-only $SYS.REQ.USER.INFO publish grant, documented in the ownership matrix/profile summary.
    Require matching public user/account/server before static schema reads without system credentials,
    arbitrary-user queries or authority fallback. Ignore response permissions/expiry as ceiling or
    lifecycle evidence and keep apply/absence authority disabled; explicit open does not invent an
    identity. This is prepared source, not a native conformance or deployment claim.

    Compare native store subjects and explicit public KV/object creation options with their documented
    wire fields, including TTL/marker units, storage, history, limits and hardening. Do not fill SDK
    defaults or invoke constructors. Block unexpanded options, expose their count rather than values
    and keep full field/runtime/revision/apply policy separate.

    Compare observed existing registry rows using native seed-before-profile precedence, a closed
    known-field policy and private revision-pinned candidates. Preserve explicit delivery choices,
    block unknown fields and unreadable/deleted/missing rows, and expose only comparison states,
    changed field names and observed revisions. Do not turn a candidate into write authority or
    change legacy seeding; add no guarded application or public stack/update path.

    Bound the resource observer by one shared deadline, preserve unvisited rows and surface the
    budget separately from policy comparison. Deadline expiry is not request cancellation or
    authoritative absence; the caller still owns connection closure.

    Extend observed-extra-field policy to native KV/object backing streams using shared first-party
    baselines and scalar public KV input defaults, not private builders or missing-field filling.
    Retain native artifact direct-read tolerance and valid smaller TTL duplicate windows. Unknown
    or nondefault fields remain blocked, and runtime/full-schema/apply authority stay separate.

    Name only the existing TTL-enforcement, stock legacy artifact-cap and contract-shadow guard
    families in reconciliation reports. Share native constants/hardening fields, block other drift
    and unknown settings, and keep guard-required metadata separate from an accepted migration.
    Inspection runs no canary, state guard, creator, update or readback.

    Route multi-name down through whole-set owned-service selection, process-role preflight, stable
    definition reservations, explicit default-cancel confirmation and complete native-impact recheck
    before the first stop. Keep per-effect native guards, input-order execution and one attributed
    receipt. Stop on failure, retain unattempted members and never claim atomic rollback or cleanup.
    Dry-run imports no provider and reserves/stops nothing; duplicate names and multi-name instance
    selectors refuse. Bare-stack and manifest migration remain separate.

    Include selected-space owned service definitions/instances on the shared status screen and JSON
    result. Keep legacy pidfile rows separately labeled. Show full identities, process observations,
    historical readiness and supervisor-record evidence without endpoint or OS-state promotion;
    unavailable record families make the report partial rather than empty. Read no provider code
    and control no service. Recheck each held definition again immediately before its set-stop effect.

    Keep whole-set reservation/preflight and release errors in the attributed down receipt. Attempt
    all acquired-hold releases without claiming verified lock cleanup or erasing completed stops.
    Owned-service status warnings retain classified cause codes without native diagnostic bodies.

    Share desired native resource creation configurations across the first-party stream baseline,
    public scalar KV defaults, explicit options and hardening. Reject unexpanded inputs and include
    hardening at creation rather than adopting and updating an existing bucket. Keep creation input
    construction separate from mutation authority, existing-store repair and broker-store custody.

    Make up background by default with an explicit --foreground mode and --detach as the accepted
    background spelling. Reject conflicting intent before seed/effects, preserve each recovery
    request's recorded mode, and document the supervising-unit/container migration. This retains
    the native launch path.

    Extend the background-up systemd advisory to the exact native invocation/main PID, naming the
    unit and --foreground remedy without mistaking inherited terminal metadata for main-process
    ownership. Preserve inherited recovery-lock release when new mode validation refuses early.

    Connect setup's explicit start/detach flow after saved preparation. Validate script detachment
    before effects, keep configure-only and default-cancel Start decisions separate, and retain one
    finite setup envelope around the shared native managed-join observer. Local startup uses the
    prepared root and original CLI, pins the follow-on request to its recorded manager and never
    promotes command exit into readiness. Preserve safe failure/request/coordinator coordinates,
    saved preparation and unknown outcomes without retrying, rolling back or replacing a manager.
    Allow self-hosted setup startup to select one manager with --on before preparation writes;
    retain that request in receipts and next-step hints. Local setup retains its own manager
    pin and refuses an external selection.

    Show the resolved mesh in shared rich/plain report headers, including ps and failures,
    without re-resolving selection or changing JSON envelopes. Keep mesh context on live
    watch and history rows and membership snapshots.

    Route named Linux reset space through reviewed native local identity cleanup with
    provider-declared key inventory, full local trust validation, unchanged filesystem scope,
    stopped-custody checks and default-cancel confirmation. Restrict secret and raw deletions
    to the reviewed remaining tree, retain returned per-path receipts on partial/unknown outcomes,
    and remove only the unchanged eligible local registration after checking cleanup. Preserve
    personas, service definitions, packages, account logins and remote data; refuse unsupported
    provider, shared-root, foreign-material, TLS-first, remote and non-Linux targets.

    Add bounded all-new agent and mixed channel/agent team deployment on static/open
    meshes through an attributed, exact-manager native launch path. Persist one full intent
    before effects, create new live channel cards through a separate scoped create-only
    writer, then launch agents through the pinned manager. Sync each channel submission
    and returned revision, each original launch request, each accepted allocation before
    goal following, and each identity-matched joined result before continuing. Match both
    step families before saving the full receipt. Retain unknown phases and partial channel
    creates, allocations and joins without replay or rollback; expose them through team
    show/inventory and keep them behind down/reset custody guards. Refuse user-auth inline
    launch, reapply and unsupported manager/runtime selection rather than reusing the
    unsafe legacy writer.

    Extend the native manager slots read with an explicit bounded name query and optional
    retired rows at cluster revision 30. Preserve default nonretired listing, exact manager
    ownership and ordered slot/head observations so teardown can distinguish native terminal
    and cleanup facts from a stop acknowledgement or a missing live-map row.

    Route static agent-only team removal through the original manager and exact recorded
    incarnations, with native impact preview, default-cancel confirmation, root maintenance
    locking, synced original stop markers and matched retired slot/head plus cleanup receipts.
    Retain partial and unknown per-agent outcomes without replay. Keep original creation and
    removal history, and release only a fully receipt-matched deployment's known additive
    blocker in boot/down/reset/deploy guards. Mixed/channel, open/user-auth and legacy removal
    remain unsupported. Show accepted allocations without joined receipts in human deploy
    output as well as structured output.

    Add explicit static-space online handle signature inspection over native leader-served signer
    and issuer-namespaced revocation records. Reuse one protected file snapshot for verification
    and metadata; check raw signatures, issuer scope, parent links and containment without claiming
    presenter binding, holder currency or use authorization. Require current spec/status pairs and
    explicitly unrevoked sturdy handles, preserve offline unverified output by default, and never
    redeem a handle or persist/print the ephemeral reader credential. Refuse unsupported open/user
    authority instead of substituting a signer; report reader-close uncertainty separately.

    Add the independent executable-endpoint service preset for selected Linux static-auth roots.
    Compile and pin local contracts without handler execution, publish native contract artifacts,
    and register through scoped native serve issuance. Run bounded no-shell JSON handlers with a
    separate fixed argv and empty environment, retaining native schema validation, deadlines,
    process/pipe cleanup uncertainty and no effect replay. Distinguish initialized process evidence
    from current endpoint health, renew through the original issuer, pin native deregistration to
    the original revision, and block reuse of unsettled full local service instances.

    Correct reproduced source-build blockers in native registry-reader construction, protected
    record imports, scoped help validation, optional observations and typed terminal reports.
    Bind initialization reads through the public native KV API rather than private handle fields.

    Avoid creating a control directory or catalog lock for a no-account observation, while keeping
    malformed cache refusals and serialized refresh/application for existing signed-in accounts.

    Create a missing extension config root privately before its first lock so a group-writable
    umask does not make Cotal's own directory block completion installation. Keep existing
    permissions and the completion writer's protected-ancestor refusal unchanged.

    Classify local catalog-preparation cache and missing-login failures as pre-effect refusals,
    not unknown remote operations. Keep cache paths and recovery guidance without parser excerpts
    or cached values, and preserve existing-account refresh/application serialization.

    Point unknown-space refusals at the canonical space inventory instead of a removed command,
    and describe missing registration without claiming that its broker is down.

  • down --preserve-state, bare up, backup restore and up --restore gain a controller-owned route, described below. This release refuses that preserve, backup and restore before any effect; the route returns in a later release.

    The preserve first runs the scope check bare down runs, so another live service instance in the space, a legacy pidfile process or a shared broker address refuses before any effect, and a retry of a committed cut checks again before any further stop. It then proves, with no effect, that the stack's manager instance serves the preserved-exit stop contract; an older manager refuses before any stop. It stops the manager with a preserved-exit request that retains its agents, then auth and the broker, and records each member's own stop receipt in the cut. A preserved manager, and one launched for a resume that has not committed, still answers status as a counted read, so the preview and resume readiness can attribute it.

    Bare up resumes a ready cut through its recorded members. Each start is journaled before it is made, a member whose earlier launch is unproven holds, and after the manager commits only the manager starts again, once its exit is receipted, with the commit token as a protected file.

    A controller restore keeps the broker definition for the preserved store's own path. For another --store-dir it journals and then writes an attempt-owned broker configuration and points the definition at it; the broker starts as a new journaled instance and the cut's old broker record is removed once the restore is active. Rollback returns the definition to the original configuration as a new revision before the store, and any unattributed revision holds. Backup and restore also require the broker configuration to match the cut launch's recorded digest. A settled active controller restore no longer fences controller down or up, including up --no-manager, or the broker and manager services; down and up name it in their receipts. While any other maintenance journal is held, the manager service launches only a resume or restore attempt's own journaled manager start, as the broker service does, and a broker or manager service restart whose start would be refused refuses before it stops anything. down --preserve-state and team boot still refuse an active restore and now say why: a new cut needs the restore journal retired with backup cleanup-fallback, and a team boot never resumes a stack whose manager already ran.

    On a controller root, backup, reset store and reset space count a stack member as running unless its process is gone with its own stop receipt. @cotal-ai/core exports brokerJetStreamBlock.

  • Add a read-only auth-provider server preflight and require it before a controller user-auth stack writes state. Validate the first IdP requirement, existing pin and first-enable JWKS through the native provider, without provisioning, pinning or granting authority. Refuse missing or unreachable IdPs with a typed cause and remedy before maintenance or trust creation, and repeat authoritative checks during preparation.

  • Wire user-mode chat sessions end to end below the command surface. The auth service admits a session per holder hash under the person's own cli grant, serves /chat-session/open, /chat-session/bearer and /chat-session/retire, re-checks the session, holder index and pinned grant before and after signing each bearer of at most 900 s, mints the plain agent leaf for a chat principal at connect, and sweeps, retires and compacts sessions. The auth provider implements the three optional chat methods and keeps each session on the route its open resolved; an open may name the IdP and exchange position the caller resolved, and the provider refuses any other. The CLI gains an internal user-mode session factory over a real endpoint.

  • Add a DM-only consume mode to CotalEndpoint. With dmOnly: { handler }, an endpoint whose credential grants only its own DM durable binds that existing dm_ durable and reads nothing else: no presence, channel registry, channel subscription, delivery durable, history or JetStream account lookup. A missing durable fails start with DmDurableMissingError (dm-durable-missing) and a refused bind with DmBindRefusedError (dm-bind-refused); the durable is never created and no other credential is tried. Messages pass the existing sender check before the handler, which runs one DM at a time. stop() resolves after the running handler settles and the connection closes, and throws when either cannot be proven. A copy the client received after stop() began or after a reconnect replaced the connection is left unacked for redelivery, and an ack on a closed connection throws.

  • Add the dm-reader exchange view and the purpose-bound IdP proof it rides. An embedding can now read one user's own DMs with a credential that holds only that user's DM durable. The callout mints consumer info, next message and ack on the user's own dm_ durable plus its connection inbox, and nothing else; core gains the matching dm-reader profile. The view is loopback-only and needs no ledger scope. It is exchanged only for a proof on the new dmReaderAudience IdP pin field, which must differ from audience, carrying purpose: "dm-reader" and the requested actor, the actor's current lifecycle and this space. The bearer and its broker connection expire no later than the proof.

    Breaking for embedders that put a purpose claim on ordinary IdP tokens: the ordinary verifier now refuses any token carrying purpose, at every door that takes a human proof.

  • startMembershipFeed now accepts a source for observerCreds, as it already does for rwCreds. The feed renews the observer at 75% of its lifetime, proves each candidate on a throwaway connection before the observer connection presents it, and refuses a candidate whose issuer or permission scope differs from the first read. The delivery daemon reads the observer through its secret store, so a host that re-mints it under the same system signer keeps the feed running past the old expiry. A static string keeps today's behavior.

  • cotal up writes the authenticated broker configuration server.conf owner-private (0600), and creates .cotal and the broker store owner-private (0700), whatever the umask. Under a group-writable umask the stack's own broker preset no longer refuses the files up just made. The broker, auth service and delivery logs are created 0600, and the pid, identity pin and manager marker records up writes are created 0600. A private file written in place, through writeSecretFile or the new openPrivateAppend, is never opened through a symlink: on POSIX a symlink, a non-regular file or a file another user owns is refused with EPERM and left unchanged, and a file the user owns is set to 0600 through the descriptor before it is truncated or appended to. Windows keeps a mode-0600 open with no owner check, and its ACL hardening is unchanged. A refused service path now names the option, the path that failed, and its owner and mode, and a group-writable ancestor is named instead of the path below it. The text failure report shows a wrapped cause's detail as one line. The whole-stack failure hints name cotal service --space <space>, which lists every member with no definition name needed, in place of a bare cotal service status.

  • Keep create-only private temporary filenames independent of the destination basename so long native service phase records can be published without exceeding the filesystem component limit. Preserve exclusive temporary creation and atomic no-replace hard-link publication.

  • Process records never write through a symlink. @cotal-ai/core adds writePrivateRecord and createPrivateRecord, which take writeSecretFile's private open without its Windows ACL step. The manager's delivery-aware marker and a pid identity pin are rewritten with writePrivateRecord, so a symlink at either name is refused with EPERM and left unchanged. The pid, pin and bridge temporaries writePidPair publishes are created with createPrivateRecord, exclusively and owner-private, and only the temporaries a call created are removed afterwards.

  • Files written in place under ~/.cotal or a project's .cotal are no longer written through a symlink. The manager's own delivery-aware marker, the agent-bearer health file, the onboarding marker, the setup log and personas, the web session file and detached log, the feedback store, persona files saved by saveAgentFile, the seat custody record, payload, exit record and log, the Claude seat home and plugin marketplace, the Codex host log, the Jcode launch record, the ext extensions prefix package.json, and the isolated broker's config rewrite and watchdog now refuse a symlink and leave it unchanged. A file rewritten in place is set to 0600 through the open file. hardenPrivate on a file now uses the same no-follow descriptor. A directory is still hardened to 0700 by its path, so a symlinked ~/.cotal or .cotal is not refused there. The manager and native service custody no longer chmod their pid records by path, since those are created 0600. The broker ports report refusal names the report's path, and a failed close no longer hides it.

  • A broker-refused manager call no longer claims a cause the broker did not report. It keeps the refused subject, instance and not-executed outcome. On a user-auth mesh a refused ps or slots read adds the documented admin-scope requirement and points to cotal auth grants. Grants, routing and the refusal itself are unchanged.

  • Deliver incoming local-mesh messages through Claude Code's native plugin hooks, including supported Desktop Code sessions, without special launch flags. Surface busy notifications at a main-conversation boundary instead of waiting for the whole turn. Preserve plugin attribution, respect native Stop, and reoffer unread wakes when the local reader restarts. Idle wake notifications display as a compact, expandable Cotal indicator. Setup can use Desktop's bundled Code executable and records Node's absolute path so the app needs neither a separate terminal CLI nor Node on its PATH.

    Refresh existing Claude messaging and skills plugin registrations during updates and ordinary first use after an npm upgrade. Preserve disabled settings and check the resolved payload rather than only the marketplace copy. A missing native runtime refuses the upgrade without accepting a stale generation. Allow an update after configure-only setup when the local project has no manager or broker running. Use provider readiness through the public setup entrypoint, including Desktop-only installations. Probe native executables only at an explicit availability or action boundary, with bounded timeouts, so a broken unrelated Claude command does not block connector registration, seeding or another harness's setup. Report a partial setup if the selected harness loses readiness before an action, rather than silently skipping it.

  • Record a process-exit receipt on a service instance that a generic stop signalled and saw exit. Stack journals accept preserve and resume operations bound to one maintenance attempt. Restore listener proofs gain a controller variant tied to one broker instance, launch request and pinned process; both bind paths refuse it until controller custody is recorded. Service adapters gain a typed, closed launch-attempt context that no adapter reads yet. Older readers refuse records that carry the new fields.

  • Maintenance journals can now record controller custody: the cut's original members and their per-role stop receipts, preserved-exit stop attempts, the resume's started members, a private commit-token handoff record (path, inode and digest, never the token), and an alternate-target restore's broker reconfiguration. The readers are closed, so each new field must match the cut's custody. Listener proofs bind only in the variant that matches custody, and a controller proof also needs a live running check from the caller. Stack resume reports process-exit evidence when a member carries its own stop receipt. Older readers refuse journals that carry these fields.

  • Deprecate the daemon entries supervise, deliver, auth-service and feedback-intake. Each keeps its existing flags for units, scripts and containers written for earlier releases, help and completion no longer list them, and every run prints one stderr line naming its service preset (manager, delivery, auth-service, feedback-intake) and the release that removes it, 1.0.0 for all four. deliver pending warns the same way and names cotal pending <agent>. Stdout, behavior and exit codes are unchanged. The top-level feedback-intake entry runs again with its existing flags instead of refusing. up now starts its manager, delivery daemon and auth service through hidden twins of supervise, deliver and auth-service with the same flags and runner and no warning, so only a unit, script or container someone can change prints it. The process checks that recognise a running manager or delivery daemon accept the twins' command lines too.

    Background cotal up that is the main process of a systemd unit now names that unit and the --foreground remedy on every route it takes, including the controller-owned stack and a refresh of a running stack. It still changes no mode and no unit. A foreground run, a dry run and up -f print nothing.

    The solo container in deploy/ runs spawn scout --foreground. docs/UPGRADING.md gains the persisted-caller section: the command mapping, the deprecated entries and their removal release, the literal up --foreground replacement for systemd and launchd callers, the owned-unit and downgrade notes, and the container change.

  • Native service stop requests, previews and results can carry a preserved-exit binding (the maintenance attempt and inventory digest) for an agent-retaining manager stop. A preserved request requires withAgents: false, its receipts are read against the same key list, and the controller accepts preserved-exit-returned only for a preserved request and returned only for an ordinary one. No command submits a preserved stop yet, and ordinary stops are unchanged.

  • @cotal-ai/workspace adds the shared terminal presentation: one report view model rendered rich (color and state marks) or plain (no ANSI, no marks), tables aligned by display width that become one labeled record per row when the terminal is too narrow, and writeResult, which writes one result as the JSON envelope or as its report. presentationOf reads --json and --plain and refuses both at once. Color tokens carry meaning (blue for commands and the selected item, green for done, amber for waiting, red for failed), and a state mark must be accompanied by its word.

    Untrusted text in any report, and every value oneLine escapes, now shows bidirectional controls as \uXXXX escapes too, so a name cannot reorder what the terminal shows.

  • The rootedAt field is gone from the local-process extension contract. Nothing has read it since the
    dashboard became a service, and the web extension no longer sets it. An extension that still declares
    it has the field dropped from its cached descriptor, like any other unknown field.

  • Add a broker service preset for explicitly prepared local configurations, with a direct creation-pinned child, launch-bound native listener reports and a separate exact-process-exit stop receipt. Preserve unknown stops without force-kill or restart.

  • Help fits a narrow terminal again. A command's usage line breaks only between options and never between an option and its argument. A usage too wide for the line breaks after its own | or compact | alternatives first. A group of alternatives too wide for the line takes lines of its own and breaks after its own | the same way, so cotal help send keeps --role/-r <role> together on a 60-column terminal. A compact |, such as the one in <persona.md>|--prompt, is a break point too: the line ends right after it and no space is added or lost, so cotal help persona keeps --prompt <text> together on a 40-column terminal. A group that fits, such as [--json|--plain], stays whole. Only a single option with its argument that is wider than the line breaks at its spaces. cotal help --all wraps its title and group headings to the terminal. Examples are still never wrapped, so each stays one line to copy.

    A flag whose description would have fewer than 30 columns beside it now has its description on the lines under it. Before, the description stayed beside its flag down to about 22 columns, so cotal help spawn wrote lines wider than a 60-column terminal. A report's list of commands, such as a Next section, follows the same 30-column rule.

  • Name the mesh before and after more operations. service stop, service restart and a named service-set stop now begin the impact they show for review with Mesh: <space>, as down does. The space delete and reset space previews, the manager gate repair review, the foreground notices of up, team boot and service start, the attach picker's partial-list notice and setup's agent-joined notice name the mesh too. A classified failure raised after a command resolved its space now carries that space in target.space and begins with Mesh: <space>, even when the failing step named no space. A target that already names a space is kept as it is.

  • Compose prepared open stacks without delivery credentials, use request-bound child-local manager observations with explicit evidence labels, and compose static mixed-team removal as native agent retirement followed by revision-conditioned channel-card removal.

  • Make owned services and target selection recoverable and honest. A service start refused before its process exists, such as a manager preset for a space that is prepared and not started, now refuses under the target's own code and records the instance as failed with no process, so a later start, stop, removal or down is not blocked by it. Ctrl-D or a closed input at a service confirmation is a clean cancel instead of exit 13 with Node's unsettled-await warning. A project root with no registration whose stack journal recorded a broker is refused as not started and names that broker, so reads such as whoami, ps, who and endpoints never dial the default address there; status and status --components select no space for an unregistered root. Bare use no longer runs the connector seed. service with no space names --space in a separate remedy. Preset help marks required options and path placeholders, a missing required option or preset is named, and schema, path and space mismatches name the field or option. Service stop, restart and down report a no-op plainly, skip a confirmation that would stop nothing, name the dependants that block a stack stop, and preview a refused stop with --dry-run. service add names its next steps. Setup checks --harness against the official connectors when none is installed and names a seed step that can run from the binary. The service reference in docs/cli.md now matches the shipped command.

  • Make usage errors and prompts behave as documented. Every CLI question, including the typed-name confirmation of space delete, the --plain removal questions of channel remove and persona remove, and the manager and login questions, now treats Ctrl-D on an empty line or a closed input as the cancel Ctrl-C gives, instead of hanging or exiting 13 with Node's unsettled-await warning. up refuses an invalid --max-sessions, --max-file-store or --restore-only value, and a restore flag combination it cannot run, as a usage error before anything runs instead of an unconfirmed outcome. --json, -j and --plain may come before the command word, and a leading -- ends the leading flags. A command that takes its words raw refuses them there. A usage refusal from a command's own checks, from clean and from help with an unknown subcommand prints the error, its remedy and the command's help, like the parser's own usage errors. space delete names a prepared space that is not running and how to start or forget it, its dry run exits 0 when it reads its whole scope, space forget no longer calls a stopped space never started, and the -y help reads correctly for delete.

  • cotal status and cotal status --components read a service-run dashboard's address from its own session record. A dashboard started with cotal service start writes that record beside its service startup receipt and never writes web.session, so status found no bound address and graded a live dashboard refused. The holder of web.pid now picks the record: the web service instance whose recorded process is that PID names its own session record, and any other holder is read from web.session. Neither record is read in place of the other. The components row names the instance as service instance <id>.

  • Read and write Cotal's local records on Windows, so cotal up, status and down run there. Local records such as the stack journal, service records and deployment attempts now use the access-list model Cotal already uses for private files on Windows. A store directory Cotal creates gets the private access list, and a record is written like a private secret. Reading a record or checking its path there does not check a POSIX owner or mode and does not refuse a link: a symlink or junction is followed. Size limits, the record schema, the regular-file check and the refusal of a link inside a record store's own directories still apply. On Windows, cotal ext add and the setup seed now record a service receipt, cotal status reads the deployment-attempt inventory, the down --dry-run and team deploy previews read their records, and cotal ext remove accepts the service namespace without a POSIX owner. Starting a process service there still refuses, because the process driver needs Linux machine and boot identity. Linux and macOS are unchanged.

  • cotal setup and cotal ext seed work on Windows again. Adding an extension that declares service adapters or presets, such as the web dashboard, read its package metadata through protected file access, which Windows does not have in this release, so the seed refused UNSUPPORTED and no connector was set up. On Windows such an extension is now added with no service receipt, ext add says that its services cannot run on this platform, and any use of those services refuses UNSUPPORTED. Linux and macOS are unchanged.

  • A direct message to an agent the roster shows offline now says so, and says what happens next: the
    message is stored and delivered when that agent reconnects, and a new agent spawned under the same
    name does not receive it. cotal_dm adds the notice to its answer, cotal send -t prints it as a
    RECIPIENT_OFFLINE warning, cotal chat adds it to the view and carries recipientStatusAtSend in
    its --stdio stored result, and cotal join and the console print it after the send.

  • Declare MCP read-only and destructive-update hints on every conversation gateway tool. Message-consuming and state-changing tools remain updates; the hints do not override host permission policies.

  • Add a typed trusted-host interactiveManagerSelection: "local-primary" runtime option to runAuthService and openAuthAuthorityPlane. It selects the genuine local Manager up front for unpinned human Manager control and refuses an unavailable local Manager without remote substitution. Explicit selectors, managed and issued instance bindings, command scopes and the absent-option default stay unchanged. The policy affects all interactive Manager control, not only ps; it adds no CLI flag or automatic up/recovery wiring.

  • Refuse an interactive grant that found no row when another grant for the same actor lands while it waits for the ledger lock, instead of overwriting it.

  • Boot fresh static-auth and open manifest environments through the service controller, seed their declared channels, and pin the manifest launch spec to the stack's own manager. Resume an eligible stopped static, open or user-auth stack only from its recorded broker inputs, completed stop evidence and never-attempted manager. User-auth preparation keeps explicit login and grants. Render one receipt without an additive ownership ledger, and support foreground stack lifetime through the guarded native stop path. Keep unresolved attempts blocked. Report a known partially running user stack as partial when the manager is withheld, even when the other members were reused rather than launched by this call.

  • cotal endpoint describe --refresh refuses as unsupported and sends nothing. The CLI keeps no resolved contract between calls, so every describe already resolves and fetches the contracts again and there is no cache for the flag to bypass. The usage lines of cotal spawn and cotal status write their optional names as [<persona>] and [<agent>].

    Breaking: endpoint describe --refresh exits with UNSUPPORTED instead of running a plain describe. Drop the flag.

  • The manager service preset takes --roster <file> and runs with cotal service start <name> --foreground. The roster is an absolute path to a file only its owner or root can write. The native manager child parses it before startup and boots its agents at each launch, as supervise --roster does; a resumed manager takes none. A foreground manager stops through the same request-bound native stop as cotal service stop, keeping its agents, when the CLI receives SIGINT or SIGTERM, and exits 130 or 143.

  • Reconcile unsettled team removals from original revision-bound card observations and exact native incarnation retirement receipts, without repeating submitted deletes or stops. Bind new card intents to their registry stream, retain superseded or inconclusive members as blockers, and never continue members that were not submitted. Preserve unknown results when original stream or lifecycle evidence is unavailable.

  • Support a genuine auth-local Manager with immutable nonexecuting capability and no Runtime. Add validated public supervise execution mode. NONE refuses model inspection and caller-driven writes, and starts no transcript receiver. Autonomous native control maintenance remains active. Runtime and remote defaults, identity format, authority and managed-seat inventory stay unchanged. Local runtime admission now records identity and capability before later authentication or registration refusal, which can retain those files; malformed records refuse earlier. Invalid supervise arguments refuse before connector seeding.

  • Add the local persona command family with structured and plain reports, complete agent-file creation, prepared-space catalogs, private editor drafts and conflict-checked local CLI commits. Keep the legacy personas parser available during migration.

  • Report a targeted stop or attach refused during name resolution as a pre-submission refusal, with the actual responding manager and a remedy. Preserve the inspect error without inventing a native effect outcome; no targeted action was published. Keep failures after submission distinct.

  • Distinguish a local detach from a terminal session ended by the serving side. Preserve the native end reason through attach and managed spawn, restore the terminal before reporting it, and avoid implying the agent is still running or that a stop completed.

  • cotal backup on a broker that hosts several spaces refuses as CONFLICT (exit 2) and names the spaces, before any cut preparation. It used to report that preparation did not establish an eligible stopped preserved cut.

  • Bare cotal down on a legacy root now stops the space's service instances through the service controller before it stops the stack, where it used to refuse while any service record existed, a stopped saved service included. Each running instance gets the checks and receipt of cotal service stop <name> --instance <id> --yes. An instance already stopped is skipped, and saved definitions stay. Every instance is checked before the first stop: an unreadable record, a retained native attempt, an unsettled request, a process that cannot be observed or a record from another host refuses with nothing stopped, and the remedy names the service and the command to run. cotal down --dry-run lists what bare down would stop, skip or refuse.

  • Verify the declared broker address against its creation-pinned child's native listener report instead of accepting another host on the same port.

  • Keep open broker configuration inside the selected root's control directory even with a custom store. Carry an old journal's explicit existing-store identity through preparation and recheck it before launch instead of recreating a missing path. These checks do not provide atomic protection against an unrelated local process changing the path.

  • Write the final channel-removal receipt after confirmed terminal steps without copying the attempt-only registry binding into its strict schema. The original intent and observation steps keep that binding. Normal removal and observation-only reconciliation can settle without repeating a delete.

  • Remove unchanged channel-only deployment cards with revision-conditioned deletes and durable outcome records, while disclosing policy fallback and preserving history, grants and readers.

  • cotal chat --plain now ends on Ctrl-C, a terminate signal or a hangup, as the CLI reference says: it closes the session once and exits 130, 143 or 129. It used to stop reading input and wait without closing the session. A line typed but not ended is dropped, and a draft waiting for its y is reported and not sent. In the terminal view, Ctrl-C and Ctrl-D now work while the recipient picker is open: they leave, or ask first when there is a draft. The picker used to ignore them.

  • Handle writable output error events as well as failed write callbacks so stdio participant shutdown is not interrupted by an unhandled stream error.

  • Complete declared flags while the current shell word is --. Treat it as an end-of-options marker only after the shell commits that word. Keep aliases, subcommand flag scopes and positional completion. Stop offering options or option values after a committed separator, and stop offering option names as the value of another option.

  • Start prepared static-auth stacks through recorded service-controller members and stop their exact instances in dependency order with native manager impact and partial-outcome receipts.

  • cotal down --space <name> with no service name now refuses with USAGE_INVALID, exit 1. Its remedy is a bare cotal down from the stack's root, or cotal service stop <service-name> --space <space> for one saved service. It used to exit 3 as OPERATION_UNKNOWN and point at cotal down web --space <name>, which is now a service stop. On a root without a controller stack, cotal down --yes now says that --yes applies only to a controller stack and that a bare cotal down stops this root's stack without it. --json and --plain on a bare stop say the same in their own refusal. Both still refuse and stop nothing. cotal ext remove no longer advises cotal down <component> for a running extension process, because a named down is a service stop. It names the pid to stop, or the dead process's pidfile to delete. The component-selection code that down could no longer reach is removed.

  • cotal down with a flag combination it does not accept, such as --preserve-state --dry-run, --preserve-state --with-agents, --store-dir without --preserve-state, or --file with --space, now refuses as a usage error with USAGE_INVALID, exit 1, and stops nothing. So does --session-store naming a path that cannot be read or is not a directory. cotal down --preserve-state in a folder with no recorded stack refuses with TARGET_NOT_FOUND, exit 2, and with TARGET_AMBIGUOUS when the folder has more than one. Each used to report Outcome unconfirmed with OPERATION_UNKNOWN, exit 3, although nothing had run.

  • cotal down --dry-run in a folder with no stack now refuses with TARGET_NOT_FOUND, exit 2, and says there is no stack at the folder's root to preview. A root with no .cotal/ directory, or with no stack registered at it, counts as no stack. It used to refuse with CONFLICT and say the local records could not be inspected consistently, which suggested damaged state in a folder that simply held none. A symlinked .cotal/, an ambiguous registration and unreadable records still refuse with CONFLICT. Source comments in the CLI, delivery and web packages that described per-component cotal down stops now describe the stops that exist.

  • Keep a foreground controller stack alive while it waits for an interrupt, even after startup sockets close. The partial agent-readiness receipt no longer precedes an unintended process exit. Interrupts still use the same guarded whole-stack stop and do not add agent retirement or force killing.

  • cotal up --no-manager on a legacy stack whose manager is live no longer tells you to run cotal down manager, which is now a service stop and refuses. The refusal says this stack has no command that stops only its manager, and names the whole-stack route: cotal down, then cotal up --no-manager --space <space>. The docs that described per-component stops now say which stack kinds have a manager-only stop, and that a legacy stack has none for its manager, delivery daemon or auth service.

  • Start a project folder an earlier release created with plain cotal up after a normal down. A folder with no stack journal that is neither prepared nor registered took the controller route, because an absent prepared root compared equal to the working directory, and then refused with no route back. It now keeps its retained launcher, identity, store and history. A controller up checks that the space is prepared or locally started at its root before it writes trust, configuration, a service definition, an instance or the stack journal, so a refusal leaves the folder unchanged and a hand-added registration is a known refusal rather than an unknown outcome. space create in a stopped legacy folder names cotal up instead of only "another folder".

  • Validate controller user-auth inputs before the ordinary recovery lock creates maintenance directories. Compare an explicit IdP with the recorded pin even while the broker is running, and refuse conflicts before journal or member refreshes. Repeat the check under the stack lock before preparation.

  • Follow a managed launch's accepted goal on the caller's authorized class route unless it already selected an instance. Keep the same caller and original goal instead of attempting an unauthorized instance read or resubmitting the launch. Report a native action's missing connector as a proved pre-allocation refusal; post-allocation failures retain their existing outcome rules.

  • Show the mesh name on more refusals. A send refused for an absent or ambiguous recipient or mention now begins with Mesh: <space>, and its JSON envelope carries target.space. history clear now declares its JSON and plain output, so history clear --dry-run on a space that is prepared but not started is a standard TARGET_UNAVAILABLE refusal with exit 2 and a JSON envelope, where it printed one line and exited 1. The CLI docs and upgrade notes now show history clear --yes and --dry-run in place of the removed --force.

  • Exclude the native status request's own completed admission from service-stop impact while retaining all other pending work, and use the existing lower control tier for retained-team reads.

  • Refuse --no-manager on a controller stack whose manager is still running, before changing its journal or any member. Keep the manager's original identity and state rather than silently returning a no-op that labels it unattempted.

  • Write generated open-mode broker configuration with private permissions so controller startup does not reject it under a group-writable umask.

  • Add the native routing-only open chat adapter with fresh per-opening identity and guarded own-inbox cleanup.

  • Create local space control directories privately, refuse unprotected project paths before recording preparation, and honor JSON/plain output for classified stack-start errors.

  • The detached manager opens its log, which carries the console URL, through openPrivateAppend. A symlink planted at the log name is refused instead of receiving the URL and having its target set to 0600 by path. An earlier version's log the user owns is still set to 0600, now through the open descriptor.

  • The broker preset's readiness check sets nats-server's ports report to 0600 before reading it. nats-server writes that report under the umask it inherited, so a group-writable umask left it 0664 in the private launch directory. The change goes through a descriptor that follows no symlink and applies only to a regular file the user owns.

  • Expose the recorded process stop receipt in service stop and status results so callers can distinguish a signal-and-exit observation from an already-gone process.

  • Verify identical retained agent and mixed deployments as no-ops against their original manager and incarnations, with explicit old-policy drift waivers and no restart, adoption or uncertain replay.

  • Verify an identical settled channel-only deployment as a no-op using its original target, receipt and leader-served create revisions. Reuse its deployment ID without creating another intent, issuing a channel writer or adopting drifted cards.

  • Preserve typed adapter planning refusals and their cause and remedy before child launch instead of hiding them as generic process failures.

  • Use the controller stack's recorded broker address when restarting after a completed down without --server. Keep explicit address changes subject to the existing journal conflict check.

  • Classify contradictory up authentication flags as usage refusals with a remedy before project lookup or preparation. Do not report an unknown operation when --user-auth conflicts with --open or --idp is supplied without user auth.

  • cotal up -f with a manifest whose runtime is installed but not reachable now refuses with DEPENDENCY_UNAVAILABLE, exit 2, and says no broker was started. It used to report Outcome unconfirmed with OPERATION_UNKNOWN, exit 3, although nothing had started.

  • Refuse conflicting up output and manager-only options as classified usage errors before preparing a project or taking a maintenance lock. Do not leave a new control directory or stale lock when --json/--plain conflict or --no-manager is paired with --runtime or --max-sessions.

  • cotal up --runtime <name> refuses a runtime with no installed provider, or one whose provider does not answer, as DEPENDENCY_UNAVAILABLE (exit 2) before anything is written or started. For a known runtime the remedy names the cotal ext add <pkg> to run. A controller stack used to start its broker and delivery first, then report only that the manager exited before readiness.

  • cotal up --space <name> now refuses with TARGET_UNAVAILABLE, exit 2, when that space was prepared in another folder, and with CONFLICT, exit 2, in a folder that is already another space's root. Both refusals used to exit 3 as OPERATION_UNKNOWN, although neither changes anything. The message names the root, and error.remedy gives the next step.

  • Compose prepared plain-loopback user-auth stacks through the existing native auth service, provider readiness and delivery authority. Report first-enable manager startup as a known partial result until the user signs in and is granted; never substitute a static caller. Keep original stack mode, address, exact service instances and unknown-operation holds.

  • cotal doctor auth without --space on a root that holds several spaces refuses with TARGET_AMBIGUOUS (exit 2), names the spaces and asks for --space. It no longer reports that root's valid inventory as SCHEMA_INVALID.

  • Keep a foreground broker outside the terminal's interrupt process group on POSIX. Ctrl-C now reaches the CLI owner first, so it can finish the guarded manager and delivery shutdown before signalling the broker.

  • Report a manager refusal that happened before anything ran as a refusal. The manager now marks its control refusals not-executed when it can show no effect started: admission and permission refusals, a stale target, input or attach into an agent that was replaced or is not running, a runtime with no input, and a spawn or launch refused before the name reserve or a launch file write, such as a missing persona. cotal spawn --detach, stop, input and attach then report refused with exit 2 and print the manager's reason on one line, naming the agent. A failure after an effect may have started, such as a terminal write the runtime rejected, stays unknown with exit 3 and now shows the manager's reason too. A user-mode ps or slots read the manager refused itself keeps its own reason and no longer gets the admin-scope hint meant for a broker refusal.

  • A channel cotal send on a static or open mesh no longer leaves a channel-registry consumer on the broker for five minutes. Its channel-policy read now uses one Direct Get, as the transient endpoint and cotal channel already do. A user-auth send keeps its scan, because a user bearer has no Direct Get row.

  • Prepare or start another space without running cotal setup again.

    • cotal space create and an up that starts or refreshes a local space write the default persona into the space's .cotal/agents when it has none, as setup does. A persona you edited is left as it is. space create --json and a controller up --json list the write under result.written.
    • cotal setup also saves the application as your own harness preference when you have none, so a space you prepare later uses it. A value you already set stays.
    • With the default persona missing, cotal status, cotal spawn and cotal app-identity name the command that writes it: cotal up in the root of a space this machine started, or cotal persona create default for any other space. An invalid default points to cotal persona show default.
    • The cotal space listing suggests cotal space create and cotal space add for another space.
    • cotal up with no --space in the folder of a running open space runs that space again. It used to resolve the default space and refuse. A folder whose stack and registrations name several spaces refuses with CONFLICT and asks for --space. The refusal for another space in a space's own folder names cotal up --space <name> instead of telling you to drop a flag.
  • Redact broker URL secrets in status reports and component facts without changing saved connection values. Report unsafe stored display addresses as unknown.

  • Name the account of a space catalog that failed to refresh in the default cotal status report. status --verbose still lists every signed-in account with its refresh state.

  • cotal status reports the dashboard as installed when an installed extension provides the web service preset. It looked for the retired web command, so it said not installed even after cotal ext add @cotal-ai/web.

  • Carry explicit console, websocket and session settings through the owned manager service. Support a private, content-pinned native launch spec without reopening it after authority preparation.

  • cotal manager reconcile keeps the native guard's own sentence when it refuses before any effect. The error carries it as its native cause, so the report shows it as the native detail and --json as error.cause. That sentence names the freeze-holder and the next step for the condition, such as starting the delivery daemon or stopping the live holder.

  • Report the observed visibility, maintenance and pending-work blockers when native manager stop preflight refuses. Name the selected manager and the operator remedy for owner-filtered impact, without changing full-scope stop authorization, substituting a wider caller or submitting a stop.

What's Changed

Full Changelog: v0.90.1...v0.91.0