Repository navigation
v0.91.0
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--plainlines, or as the--stdioNDJSON 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'scligrant 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 readcotal senduses, and says whether the channel is registered, unregistered or could not be read; it never creates the channel.--namesets the display label, which defaults to the OS login and host with a short suffix. The terminal view refuses without a terminal and names--plainand--stdio;--stdiorefuses with--plain, and the command declares no--json.--kind endpointis accepted and changes nothing, since every admission presents the session as an endpoint;--kind agentand any other kind refuse as a usage error.--role,--link,--token,--credsand--lifecycle-uidare 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 exportsconnectTargetOrThrow, the connect half ofconnectOrThrowfor 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
cotalnames the selected space, lists the common commands and points a machine with no selected space tocotal setup. It starts nothing. cotal help [command] [subcommand] [--all]prints the command list or one command's or subcommand's help;--helpand-hprint the same.cotal versionprints the version, as do--versionand-V. Breaking:-vno 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) andcotal ext rm. A word is never matched by prefix. The registry refuses a name or alias another command already claims, andcotal ext addrefuses an extension whose name or alias an installed extension claims, naming both. - Completion resolves an alias as dispatch does.
- Bare
-
cotal completionreports 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 wherecompletion installwired it in (the startup file holding its install line, or fish's completions directory).--jsonwrites the report as one document and--plainas plain text. A stub or startup file it cannot read is reported with a warning, and the run ispartialand exits 4.cotal completion script <shell>prints the stub as raw shell code.Breaking:
cotal completion <shell>is replaced bycotal completion script <shell>. The old form exits 1 with nothing on stdout, so a hand-writtensource <(cotal completion bash)loads nothing, and names its replacement on stderr. Stubs installed bycotal completion installkeep 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 installreads an install line only when it is a line of its own, not one that ends in a carriage return, ignores a relativeXDG_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 relativeZDOTDIRis refused with nothing changed, and a line it cannot add after writing the stub fails with exit 5, naming the stub.writeResultin@cotal-ai/workspacecan report a partial read. -
Add
cotal configfor personal preferences:harness,persona,detach-key,colorandeditor. Bareconfigandconfig get <key>show the value each key resolves to, where it came from and the values it outranks;config setandconfig unsetchange your defaults, or your values for one space with--space(harnessandpersonaonly). All four forms take--jsonand--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_COLORthenNO_COLOR,VISUALthenEDITOR), your value for the space, your own value, then the default.spawn(both paths),attach,personas editand 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.jsonin the configuration directory, private to their owner and versioned. A write holds a lock, refuses withCONFLICTwhen 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/workspaceexports the preferences store and resolver, andwriteResultcan report ano-op.
- One resolver decides each key: an explicit flag, the persona's pin, the named variable (
-
On a controller-owned stack,
down --preserve-state,backup create,backup restoreandup --restorenow refuseUNSUPPORTED(exit 2) while validating, before the confirmation, the connector seed, any write or any manager request, in every stack mode. The remedy names plaincotal down, which keeps the stack's store, channels and history for the nextcotal 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(andext list) writes one structured document with--jsonand a plain report with--plain:result.rootis the install prefix andresult.itemsthe installed extensions. This replaces one JSON line per extension.--jsonand--plainon the otherextsubcommands are refused withUSAGE_INVALID, andext rootstays a raw path.A subcommand can declare its own structured outputs (
Subcommand.outputsin@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 ownstructured outputline, soext add,ext removeandext seedkeep exiting 1 on any failure.Add
cotal docs [<page>], the installed version's own protocol and CLI docs, offline: baredocslists the pages, a page prints its Markdown,--search <query>shows the best-matching sections, and--refreshalso tries the version-pinned copy on docs.cotal.ai and says which copy it served.@cotal-ai/connector-coreexports the docs reads it uses (docsIndex,readDocsPage,searchDocs,capSection) through a new./docssubpath, so the bundle loads only whendocsruns. -
cotal history [<channel>]reads the newest retained messages in the selected space within the identity's read grant, newest last.--limitbounds the read (default 50, at most 1000);--since(a time, an age or a stream sequence),--fromand--grepfilter that window, and--dmsadds 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.--followkeeps listening; with--jsonit 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 withPERMISSION_DENIED, and a part that could not be read makes the runpartial(exit 4).history clearpurges the whole selected space after a confirmation, or with--yesin a script. Extra channel names and read filters are refused before a purge;--dmsremains an explicit extension.CotalEndpoint.multiChannelHistorynow 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, andchannelReplayPolicy(channel)reads a channel's effective replay policy from the registry.--sincerejects 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.channelHistoryPagereads 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.stopImpactreports the preservation attempt and inventory digest. A preserved-exit stop request names that binding withwithAgents: false, and the manager accepts it only when fully preserved and quiescent, returningpreserved-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 deprecatedsupervise --resume-commit-tokeninput 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 exportsrecompileContractClosure. -
cotal ps,cotal modelsandcotal runtimeswrite one structured document with--jsonand 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, ispartialand 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_UNAVAILABLEand others) and exits 2, and under--jsonthat 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 --jsonwith an unreadable extensions manifest is nowpartialand exits 4. A connector'slistModelscan returnunavailablewith a reason when its install has no catalog to list; the manager then reports itsupported: falseinstead of a failed read, and OpenCode 2.x does so instead of failingcotal models. An installed connector the manager cannot load makescotal modelspartial 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 --jsonwrites one envelope whoseresult.itemsare the manager rows, instead of one row per line. An incomplete manager census exits 4 instead of 1, and a meshpsormodelscannot reach exits 2 instead of 1. The human reports ofps,modelsandruntimesare tables, andps --wideprints 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 onCommandandSubcommandin@cotal-ai/core), and the dispatcher skips the seed for it:status,ps,who,whoami,models,runtimes,history,docs,endpoints,describe, barespaceandspace show, bareconfigandconfig get, and bareext,ext listandext 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 andcotal ext seedinstead. On a fresh machinestatuspoints atcotal setupfor the connectors.Breaking: a read run right after an install, such as
cotal ext list, no longer installs the built-ins. Runcotal ext seed,cotal setupor any command that is not a read. See the upgrade notes. -
cotal setuptakes 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-inputor--json, every input is a flag and a missing one isUSAGE_INVALIDbefore anything is written;--destination cloudisUNSUPPORTED. A local space is prepared ascotal space createprepares it; a self-hosted space is one registered here whose root is the project, or one--connection-fileregisters. Setup seeds the default persona into the project's.cotal/agents, records the application as the space'sharnesspreference, runs that application's own setup actions, and writes one envelope with--jsonlisting 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-onlyis accepted and is the default.recordPreparedSpacein@cotal-ai/workspacereturns the file it wrote, andmeshFilenames a space's registry file.Breaking:
cotal setup --yeswithout 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 statusreports the same state). See the upgrade notes. -
cotal setupsets up the runtimes your agents run in. On a terminal it asks which runtimes to set up after the application question:ptyis 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 beyondpty. An unknown name isUSAGE_INVALIDand an official runtime whose host tool is not on PATH isDEPENDENCY_UNAVAILABLE, both before anything is written.Setup installs each chosen runtime as
cotal ext adddoes, at the running cotal's version, then asks its provider whether it answers, ascotal runtimesreports. 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 resultpartial(exit 4). Setup never removes a runtime left out;cotal ext removedoes.result.runtimeslists 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--jsonor--plainthe install progress goes to stderr.cotal ext addof 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 addandcotal space forgetregister 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:CONFLICTfor a registered name or a broker that enforces another mode,TARGET_UNAVAILABLEfor a broker that does not answer,DEPENDENCY_UNAVAILABLEfor missing trust,UNSUPPORTEDfor an address credentials may not cross. On a terminal it shows what it will trust and asks;--yesskips that question. It never changes the selection.--forcereplaces 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/workspacecan carry its refusal code, andpreflightCodeis 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/, socotal upin that root starts the space under that name and drops the prepared record. It starts nothing and keeps the selection. It refuses withCONFLICTa name that is registered or prepared, a folder that is already a space's root, and the home folder. cotal spacelists prepared spaces under their own heading, andcotal space show,cotal useandcotal space forgetaccept one.cotal space addrefuses 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/workspacekeeps prepared spaces in their own store under~/.cotal/prepared, apart from the mesh registry, and target resolution reports one with thenot-startedcode.
- It records the name and root, and makes
-
Add
cotal spaceandcotal space show [<name>], and putcotal useon the structured output contract.spacelists the registered spaces with each broker's state, server, mode, origin and root, and never dials a discovered space;space showgives one in full, the selected one by default, without its credential paths. Both take--jsonand--plain, and their rows matchcotal status --json.cotal use <space>selects any registered space without checking its broker, refuses a name that is not registered withTARGET_NOT_FOUND(exit 2), reports a repeat as ano-op, and barecotal usereports the selection. A selection that names no registration is reported with aSELECTION_NOT_REGISTEREDwarning.- A command run without
--spacetargets the selection: when its broker is down it refuses withTARGET_UNAVAILABLE, and a selection that names a space no longer registered refuses withTARGET_NOT_FOUND. Neither falls back to another mesh. @cotal-ai/workspaceexportsbrokerAnswers, and aMeshTargetErrorfor a dangling selection carriesselected: true.
-
cotal statuswrites one structured document with--jsonand 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--allasks for every recorded one, and a part status cannot read is named on its row and makes the runpartial. 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/workspaceaddsreadMeshRegistry,readCurrentandMeshRegistryErrorfor those reads.Breaking: bare
statusexits 4 when it could not read part of what it reports, instead of 0. The recorded meshes other than the selected one readnot checkedwithout--all. The report lists no roster, and--componentsis refused with--json,--plainor--all. See the upgrade notes. -
Commands share one structured output contract, and every command takes
--no-colorand--no-input.cotal version --json(or-j) writes one JSON document on stdout:schemaVersion1, the command, anulltarget, the outcome, completeness, the result (the version and each installed extension's), and warnings. A usage error under--jsonis onerefuseddocument with codeUSAGE_INVALIDand a remedy, and the help it names stays off stdout. A command with no JSON output refuses--jsonas 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/workspaceexports the envelope and NDJSON record types, the stable error codes, the outcome-to-exit table, andCommandFailure, which keeps an endpoint's own code and outcome undererror.cause.--no-colorturns color off for that run, including the setup prompts and the console, whateverFORCE_COLORsays; the programs it starts are no longer forced into color byFORCE_COLOR.--no-inputmeans no prompt, editor or browser: a prompt behaves as it does without a terminal,cotal webprints its link without opening it, andcotal personas editis refused.--jsonimplies--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, andcotalexits 1 before running any command.cotal consolenow follows a non-emptyNO_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,--serveror--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,--jsonand--no-inputstill refuse withTARGET_AMBIGUOUS. - A refused target, a broker that does not answer and refused credentials carry what to run next in
error.remedy, apart fromerror.message. The one-line wording elsewhere is unchanged apart from punctuation. cotal up -fandcotal spawn -frefuse a--spacethat names another space than the manifest's, before anything is written. Before,--spacereplaced the manifest's space.cotal syncwrites one envelope with--jsonand a plain report with--plain. An account whose catalog could not be refreshed is named in aCATALOG_UNAVAILABLEwarning and makes the result partial (exit 4); when none could be refreshed it refuses withDEPENDENCY_UNAVAILABLE.@cotal-ai/workspaceexportsworkspaceErrorParts, and aConnectRefusalcan carry its message and remedy apart.
- With no
-
Add
cotal whoandcotal whoami.wholists 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;--waitingkeeps rows that are waiting or report a condition and--alladds infrastructure endpoints.whoamireports 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--jsonand a plain report with--plain; a part they could not read makes the runpartial(exit 4), and a roster the identity may not read is refused withPERMISSION_DENIED.whowatches 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.
whoamireports 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.whoamialso 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
whoamiwithout 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_INVALIDbefore any read request, without printing its stored field values. Include the roster suite in the Linux, macOS and Windows platform matrix. -
Report
cotal actor grantandcotal actor revokehonestly 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 endspartial(exit 4) with the retired lifecycle underchangedand a remedy to re-readcotal actor list, instead ofunknown(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 withCONFLICT, 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 endsunknownbefore 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,grantandrevokenow resolve their space and root ascotal auth grants,grantandrevokedo. With no space to resolve they refuse withTARGET_NOT_FOUNDinstead of assumingmain, and on a root without the space's user-auth ledgeractor listrefuses withUNSUPPORTEDinstead of reporting no rows.- Grant usage is checked before any space or authority is read, under both spellings. A grant or revoke missing
--subor--owner, or a grant missing an ACL flag without--full, refuses withUSAGE_INVALID(exit 1) and names every missing input in one refusal, whereactor grantused to end with exit 5 andauth grantnamed one input per run.actoralso refuses a flag that does not belong to its verb, asauthdoes. cotal loginagainst a provider that cannot be reached or stops answering refuses withDEPENDENCY_UNAVAILABLE(exit 2) and a--idpremedy, instead of printing the raw transport error with exit 1. No session is cached.cotal doctor authreports every credential with no expiry claim as a finding, including an agent credential thatcotal auth mintwrote without--expires-inor--expires-at, so that root no longer reads as having no findings. The mint default is unchanged.
-
Refuse
cotal actor grantandcotal actor revokeplainly 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) withDEPENDENCY_UNAVAILABLE,PERMISSION_DENIED,CONFLICTorUNSUPPORTED, says the actor row was not changed, and names the recovery, usuallycotal up. It used to report every such failure asunknown(exit 3). The auth service's/interactive-lifecycle/retiredoor now answers every refusal it makes before the retirement barrier, its token checks and authority head read included, withoutcome: "not-executed". A retirement request that may have reached the barrier, such as a timeout or an error answered without that outcome, staysunknown, 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 addand 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--umasksetting 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-openandchat-session-retire(cluster revision 34): it draws achat_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 assealTo, 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 withchat_. The workspace exportsmintControlInstrument, which mints a control-caller instrument for a target the caller already resolved. Core addssealJson,SealRecipientandisCurvePublicKey, 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.
--plainwrites punctuation in ASCII:·and long dashes as-,…as...,→and↳as->, and§assection. 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 --widelabels its records the same way. history --followwraps each new message to the terminal, as the window above it is.- The
statusmembership feed row says how long ago the feed was updated instead of printing its ISO time;--jsonkeeps the time. cotal completionfills every cell: a shell with no install line saysnot wired in, and PowerShell's file saysnone.- The help for
--onandps --slotssays 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,
getentmust show that the group is the caller's primary group, lists no other member and is no other account's primary group, andgetfaclmust show no extended ACL on the entry. The account list counts only when/etc/nsswitch.confnamesfilesandsystemdalone 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 achmodremedy, and says what kind of path was checked instead of calling every path a credential reference. The installer setsumask 022before 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.INFOpublish 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, bareup,backup restoreandup --restoregain 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
downruns, 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 answersstatusas a counted read, so the preview and resume readiness can attribute it.Bare
upresumes 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-dirit 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 controllerdownorup, includingup --no-manager, or the broker and manager services;downandupname 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 managerservice restartwhose start would be refused refuses before it stops anything.down --preserve-stateandteam bootstill refuse an active restore and now say why: a new cut needs the restore journal retired withbackup 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/coreexportsbrokerJetStreamBlock. -
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
cligrant, serves/chat-session/open,/chat-session/bearerand/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. WithdmOnly: { handler }, an endpoint whose credential grants only its own DM durable binds that existingdm_durable and reads nothing else: no presence, channel registry, channel subscription, delivery durable, history or JetStream account lookup. A missing durable fails start withDmDurableMissingError(dm-durable-missing) and a refused bind withDmBindRefusedError(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 afterstop()began or after a reconnect replaced the connection is left unacked for redelivery, and an ack on a closed connection throws. -
Add the
dm-readerexchange 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 owndm_durable plus its connection inbox, and nothing else; core gains the matchingdm-readerprofile. The view is loopback-only and needs no ledger scope. It is exchanged only for a proof on the newdmReaderAudienceIdP pin field, which must differ fromaudience, carryingpurpose: "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
purposeclaim on ordinary IdP tokens: the ordinary verifier now refuses any token carryingpurpose, at every door that takes a human proof. -
startMembershipFeednow accepts a source forobserverCreds, as it already does forrwCreds. 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 upwrites the authenticated broker configurationserver.confowner-private (0600), and creates.cotaland the broker store owner-private (0700), whatever the umask. Under a group-writable umask the stack's own broker preset no longer refuses the filesupjust made. The broker, auth service and delivery logs are created 0600, and the pid, identity pin and manager marker recordsupwrites are created 0600. A private file written in place, throughwriteSecretFileor the newopenPrivateAppend, is never opened through a symlink: on POSIX a symlink, a non-regular file or a file another user owns is refused withEPERMand 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 namecotal service --space <space>, which lists every member with no definition name needed, in place of a barecotal 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/coreaddswritePrivateRecordandcreatePrivateRecord, which takewriteSecretFile's private open without its Windows ACL step. The manager's delivery-aware marker and a pid identity pin are rewritten withwritePrivateRecord, so a symlink at either name is refused withEPERMand left unchanged. The pid, pin and bridge temporarieswritePidPairpublishes are created withcreatePrivateRecord, exclusively and owner-private, and only the temporaries a call created are removed afterwards. -
Files written in place under
~/.cotalor a project's.cotalare no longer written through a symlink. The manager's own delivery-aware marker, theagent-bearerhealth file, the onboarding marker, thesetuplog and personas, the web session file and detached log, the feedback store, persona files saved bysaveAgentFile, the seat custody record, payload, exit record and log, the Claude seat home and plugin marketplace, the Codex host log, the Jcode launch record, theextextensions prefixpackage.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 to0600through the open file.hardenPrivateon a file now uses the same no-follow descriptor. A directory is still hardened to0700by its path, so a symlinked~/.cotalor.cotalis not refused there. The manager and native service custody no longer chmod their pid records by path, since those are created0600. 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-exitreceipt on a service instance that a generic stop signalled and saw exit. Stack journals acceptpreserveandresumeoperations 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-exitevidence when a member carries its own stop receipt. Older readers refuse journals that carry these fields. -
Deprecate the daemon entries
supervise,deliver,auth-serviceandfeedback-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.0for all four.deliver pendingwarns the same way and namescotal pending <agent>. Stdout, behavior and exit codes are unchanged. The top-levelfeedback-intakeentry runs again with its existing flags instead of refusing.upnow starts its manager, delivery daemon and auth service through hidden twins ofsupervise,deliverandauth-servicewith 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 upthat is the main process of a systemd unit now names that unit and the--foregroundremedy 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 andup -fprint nothing.The
solocontainer indeploy/runsspawn scout --foreground.docs/UPGRADING.mdgains the persisted-caller section: the command mapping, the deprecated entries and their removal release, the literalup --foregroundreplacement 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 acceptspreserved-exit-returnedonly for a preserved request andreturnedonly for an ordinary one. No command submits a preserved stop yet, and ordinary stops are unchanged. -
@cotal-ai/workspaceadds 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, andwriteResult, which writes one result as the JSON envelope or as its report.presentationOfreads--jsonand--plainand 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
oneLineescapes, now shows bidirectional controls as\uXXXXescapes too, so a name cannot reorder what the terminal shows. -
The
rootedAtfield 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, socotal help sendkeeps--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, socotal help personakeeps--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 --allwraps 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 spawnwrote lines wider than a 60-column terminal. A report's list of commands, such as aNextsection, follows the same 30-column rule. -
Name the mesh before and after more operations.
service stop,service restartand a named service-set stop now begin the impact they show for review withMesh: <space>, asdowndoes. Thespace deleteandreset spacepreviews, the manager gate repair review, the foreground notices ofup,team bootandservice 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 intarget.spaceand begins withMesh: <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
downis 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 aswhoami,ps,whoandendpointsnever dial the default address there;statusandstatus --componentsselect no space for an unregistered root. Bareuseno longer runs the connector seed.servicewith no space names--spacein 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 anddownreport 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 addnames its next steps. Setup checks--harnessagainst 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--plainremoval questions ofchannel removeandpersona remove, and themanagerandloginquestions, 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.uprefuses an invalid--max-sessions,--max-file-storeor--restore-onlyvalue, and a restore flag combination it cannot run, as a usage error before anything runs instead of an unconfirmed outcome.--json,-jand--plainmay 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, fromcleanand fromhelpwith an unknown subcommand prints the error, its remedy and the command's help, like the parser's own usage errors.space deletenames 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 forgetno longer calls a stopped space never started, and the-yhelp reads correctly for delete. -
cotal statusandcotal status --componentsread a service-run dashboard's address from its own session record. A dashboard started withcotal service startwrites that record beside its service startup receipt and never writesweb.session, so status found no bound address and graded a live dashboardrefused. The holder ofweb.pidnow picks the record: the web service instance whose recorded process is that PID names its own session record, and any other holder is read fromweb.session. Neither record is read in place of the other. The components row names the instance asservice instance <id>. -
Read and write Cotal's local records on Windows, so
cotal up,statusanddownrun 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 addand the setup seed now record a service receipt,cotal statusreads the deployment-attempt inventory, thedown --dry-runandteam deploypreviews read their records, andcotal ext removeaccepts 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 setupandcotal ext seedwork 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 refusedUNSUPPORTEDand no connector was set up. On Windows such an extension is now added with no service receipt,ext addsays that its services cannot run on this platform, and any use of those services refusesUNSUPPORTED. 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_dmadds the notice to its answer,cotal send -tprints it as a
RECIPIENT_OFFLINEwarning,cotal chatadds it to the view and carriesrecipientStatusAtSendin
its--stdiostored result, andcotal joinand 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 torunAuthServiceandopenAuthAuthorityPlane. 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 --refreshrefuses 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 ofcotal spawnandcotal statuswrite their optional names as[<persona>]and[<agent>].Breaking:
endpoint describe --refreshexits withUNSUPPORTEDinstead of running a plain describe. Drop the flag. -
The
managerservice preset takes--roster <file>and runs withcotal 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, assupervise --rosterdoes; a resumed manager takes none. A foreground manager stops through the same request-bound native stop ascotal 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 backupon a broker that hosts several spaces refuses asCONFLICT(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 downon 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 ofcotal 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-runlists what baredownwould 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 --plainnow 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 itsyis 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 withUSAGE_INVALID, exit 1. Its remedy is a barecotal downfrom the stack's root, orcotal service stop <service-name> --space <space>for one saved service. It used to exit 3 asOPERATION_UNKNOWNand point atcotal down web --space <name>, which is now a service stop. On a root without a controller stack,cotal down --yesnow says that--yesapplies only to a controller stack and that a barecotal downstops this root's stack without it.--jsonand--plainon a bare stop say the same in their own refusal. Both still refuse and stop nothing.cotal ext removeno longer advisescotal down <component>for a running extension process, because a nameddownis a service stop. It names the pid to stop, or the dead process's pidfile to delete. The component-selection code thatdowncould no longer reach is removed. -
cotal downwith a flag combination it does not accept, such as--preserve-state --dry-run,--preserve-state --with-agents,--store-dirwithout--preserve-state, or--filewith--space, now refuses as a usage error withUSAGE_INVALID, exit 1, and stops nothing. So does--session-storenaming a path that cannot be read or is not a directory.cotal down --preserve-statein a folder with no recorded stack refuses withTARGET_NOT_FOUND, exit 2, and withTARGET_AMBIGUOUSwhen the folder has more than one. Each used to reportOutcome unconfirmedwithOPERATION_UNKNOWN, exit 3, although nothing had run. -
cotal down --dry-runin a folder with no stack now refuses withTARGET_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 withCONFLICTand 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 withCONFLICT. Source comments in the CLI, delivery and web packages that described per-componentcotal downstops 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-manageron a legacy stack whose manager is live no longer tells you to runcotal 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, thencotal 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 upafter a normaldown. 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 controllerupchecks 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 createin a stopped legacy folder namescotal upinstead 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
sendrefused for an absent or ambiguous recipient or mention now begins withMesh: <space>, and its JSON envelope carriestarget.space.history clearnow declares its JSON and plain output, sohistory clear --dry-runon a space that is prepared but not started is a standardTARGET_UNAVAILABLErefusal with exit 2 and a JSON envelope, where it printed one line and exited 1. The CLI docs and upgrade notes now showhistory clear --yesand--dry-runin 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 -fwith a manifest whose runtime is installed but not reachable now refuses withDEPENDENCY_UNAVAILABLE, exit 2, and says no broker was started. It used to reportOutcome unconfirmedwithOPERATION_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, asDEPENDENCY_UNAVAILABLE(exit 2) before anything is written or started. For a known runtime the remedy names thecotal 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 withTARGET_UNAVAILABLE, exit 2, when that space was prepared in another folder, and withCONFLICT, exit 2, in a folder that is already another space's root. Both refusals used to exit 3 asOPERATION_UNKNOWN, although neither changes anything. The message names the root, anderror.remedygives 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 authwithout--spaceon a root that holds several spaces refuses withTARGET_AMBIGUOUS(exit 2), names the spaces and asks for--space. It no longer reports that root's valid inventory asSCHEMA_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-executedwhen 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,inputandattachthen reportrefusedwith 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, staysunknownwith exit 3 and now shows the manager's reason too. A user-modepsorslotsread the manager refused itself keeps its own reason and no longer gets the admin-scope hint meant for a broker refusal. -
A channel
cotal sendon 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 andcotal channelalready 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 setupagain.cotal space createand anupthat starts or refreshes a local space write thedefaultpersona into the space's.cotal/agentswhen it has none, as setup does. A persona you edited is left as it is.space create --jsonand a controllerup --jsonlist the write underresult.written.cotal setupalso saves the application as your ownharnesspreference 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 spawnandcotal app-identityname the command that writes it:cotal upin the root of a space this machine started, orcotal persona create defaultfor any other space. An invalid default points tocotal persona show default. - The
cotal spacelisting suggestscotal space createandcotal space addfor another space. cotal upwith no--spacein 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 withCONFLICTand asks for--space. The refusal for another space in a space's own folder namescotal 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 statusreport.status --verbosestill lists every signed-in account with its refresh state. -
cotal statusreports the dashboard as installed when an installed extension provides thewebservice preset. It looked for the retiredwebcommand, so it saidnot installedeven aftercotal 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 reconcilekeeps 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--jsonaserror.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
- feat(cli)!: redesign the command line by @davidfarah2003 in #4216
- feat(core): renew the membership observer cred from a source by @davidfarah2003 in #4221
- fix(cli): follow-ups to the CLI redesign by @davidfarah2003 in #4220
- feat: tell the sender when a direct message goes to an offline agent by @davidfarah2003 in #4224
- feat!: remove rootedAt from the local-process contract by @davidfarah2003 in #4225
- fix(cli): second round of follow-ups to the CLI redesign by @davidfarah2003 in #4226
- fix(cli): stop the space's services in a bare down instead of refusing by @davidfarah2003 in #4227
- fix(manager): mark a control refusal not executed when nothing ran by @davidfarah2003 in #4229
- feat(auth)!: add a purpose-bound DM reader by @davidfarah2003 in #4222
- ci: stop automatic mutation infrastructure in smoke shards by @davidfarah2003 in #4228
- test(web): strip COTAL_ variables before the echo-escaping web child starts by @davidfarah2003 in #4232
- fix(cli): set up once, then prepare, start or switch spaces without running setup again by @davidfarah2003 in #4233
- fix(cli): preserve the broker until guarded foreground teardown by @davidfarah2003 in #4230
- test: match the browser view and console status smokes to the current grants and peer labels by @davidfarah2003 in #4234
- test: refresh runner and DM-reader fixture anchors by @davidfarah2003 in #4236
- fix(workspace): read and write local records on Windows through the access-list model by @davidfarah2003 in #4235
- test(manager): stop the no-execution suite's managers with their agents by @davidfarah2003 in #4237
- test(auth): build the duplicate-principal row as a valid interactive row by @davidfarah2003 in #4238
- fix(cli): fit help and reports to a narrow terminal by @davidfarah2003 in #4239
- fix(claude): deliver native messages and refresh installed integrations by @davidfarah2003 in #4231
- feat(manager): support control-only local management by @davidfarah2003 in #4240
- docs(cli): use a non-home path in the service credential example by @davidfarah2003 in #4241
Full Changelog: v0.90.1...v0.91.0