Repository navigation
v0.79.0
Cotal 0.79.0 is out!
Grab it: npm i cotal-ai@0.79.0
Changes in this release
- Whether a consumer info or delete found no consumer is now decided by one predicate,
isConsumerNotFoundin@cotal-ai/core, which accepts only the broker's structuredConsumerNotFounderror. It no longer accepts a barenameofConsumerNotFoundErroror a stringcode, so the run journal's replay cleanup no longer swallows those shapes. The stream, KV scan, run wait, deliverypendingand auth scanner sites use it in place of their own copies, andisJetStreamMissing, the structured check it builds on, is exported beside it. - The hover docs for
CotalEndpoint.serveControlandrequestControlno longer describe manager control tiers, a manager wildcard reply grant or an agent-credential cutover that no longer exist. They now name the delivery daemon'sctl.delivery.*.*.reply.>grant as the reasonboundReplyis required, and theCONTROL_DELIVERYandrequestDeliverydocs match the bounded reply both control requests use. Comments on the session ledger, goal-writer, caller grant, invoke, endpoint-serve ledger, lease and slot-row declarations no longer cite internal planning labels that no spec or doc page defines; the mechanism text and theSPECand§13.xcitations stay. No behavior changes. - The persona catalog directory is now built in one place,
personaDirin@cotal-ai/core.agentFilePathandlistPersonaCatalogbuild on it,@cotal-ai/workspacekeeps exporting it under the same name, andcotal statusandcotal personasuse it in place of their own copies, so the directory spawn loads personas from and the directory those surfaces name cannot drift apart. reconcileEndpointGate, behindcotal reconcile-gate, the manager's boot self-heal and the auth host's remote-manager maintenance, no longer reports a completing reopen whose acknowledgement was lost asracedwith "Nothing was reopened" while the gate is open at the repair's own coordinate. It chose that refusal by matching the error text ofcompleteFrozenRegistrationFromSpec, which used one message for a lost reopen CAS and for a reopen whose outcome is unknown.completeFrozenRegistrationFromSpecnow returns a lost CAS as{ completed: false, raced: true }, and the repair refusesracedonly on that result. A reopen whose outcome is unknown fails with anunavailableerror that says it may have committed, as the same fault on the abort-reopen path already did, so the boot self-heal no longer continues past it.- Accept canonical space names containing underscores in issued-authority references, source coordinates and stores. Refuse malformed spaces without rewriting them and preserve endpoint-name validation.
- A manager call that fails with a thrown envelope error now returns the error's code and details, the same as a refusal that arrives as a reply. The CLI's control calls,
cotal spawn -fand the connector's manager tools each converted the thrown error by hand and dropped the code, and two of them also dropped the details and the lifecycle-blocked suffix. Acotal attachreconnect therefore kept retrying apermission-deniedornot-foundraised on the caller side, such as a broker refusal, instead of stopping on it. Core now exportscontrolReplyFromThrown, and each caller keeps its own message. - A failure a bridged host handler throws now crosses into the engine thread as the class it was raised as, with that class's own fields, and is rebuilt with nothing defaulted. Before, an
EffectErrormissing itscodeorkindwas journaled asL4000/handler-fault, and anEffectRefusedmissing itscodeasL5016, while the in-process walker recorded the same failure with those fields absent. A bridged failure now journals the same as an in-process one. - A manager or delivery start that refuses a record it cannot attribute now names the pidfile it read. The cutover preflight,
spawn -f, the delivery start andservice installused to resolve the record's spelling a second time while formatting the refusal, so a record that moved between its space-keyed and pre-upgrade names in between was misnamed, and one that appeared beside the record that was read replaced the refusal and itsNEXT:step with an ambiguous-record error.readProcessRecordin@cotal-ai/workspacenow returns the path it read on everyProcessRecord, andservice status --jsonreports that file asmanager.path. The config and CLI pages describe both. - An installed extension whose
package.jsonis not JSON or has noversionis no longer reported as not installed or with a bare JSON parse error.installedExtensionVersionthrowsCorruptExtensionPackageError, which names the package and itspackage.json, so loading the extension,cotal statusand thecotal setupcard report the damaged file.cotal ext seed --repairreinstalls a seeded built-in in that state, including after a corrupt extensions manifest was rebuilt. - The manager and delivery daemon records are now read and attributed by one reader,
readProcessRecordin@cotal-ai/workspace, which takes the record path and the component's attribution predicate and returns the state with the pid, content and command line behind it. The rule that a live pid is demoted to foreign only when its command line was read and is not the component's now lives in one place, and the delivery verdict keeps the command line it was decided on, as the manager's already did. No states or messages change. - The web dashboard's pidfile name is now one
WEB_PIDFILEconstant in@cotal-ai/workspace. The dashboard declares its record with it, and thecotal statusWeb processrow,cotal status --components, thecotal setupcard and thecotal clean allcrash-residue sweep read it from there. They used to spellweb.pidby hand, so renaming the dashboard's record would still typecheck while those readers reported a running dashboard as down or absent andclean allleft its pidfile behind. The file is still.cotal/web.pid. cotal logout, the account switch incotal login,cotal downandcotal clean allnow remove their registry entries as one batch that scans the registry for pre-hex records once. Before, each removed entry ran its own scan over the whole registry, so removing K entries from a registry of R records read about K × R record files. The removed entries and the pointer outcome are unchanged, also when a removal fails partway through the batch or a concurrentcotal usemoves the pointer during it.- A seat writer generation file is now keyed by
spaceKeyof the space and of the seat name, joined by00, and one builder names it for both the claim and the load. An empty space, a name with an unpaired surrogate and a space or seat name containing NUL are refused instead of written, so two different seats can no longer share one generation file and refuse each other's claim. Every key a valid seat already has is unchanged. The account record filename is also built in one place now, for both its file path and its store key. - The Claude Code AG-UI mapper's comments no longer restate its origin tables by hand. The module header listed
humanandchannelas the only origins that open a run, whileORIGIN_RULEalso opensauto-continuation; it now points toORIGIN_RULEandABSENT_ORIGIN_RULEas the only list. ThepromptSourcefield doc no longer says only"sdk"is read, and the run-opening comment no longer callschannelthe only change from the plan's table. No behavior changes. - A Codex seat that stops while its event plane is armed but not yet bound to a rollout file no longer binds on the way out. A bind that resumes after the seat began stopping now stands down, whether it was looking for the file or reading where to start in it, and whether shutdown's own drain, the turn boundary from shutdown's interrupt, or the launch started it. The seat no longer logs another
no rollout file yetline while it exits, and no longer adopts an emitter that nothing closes while it leaves the mesh. - The AG-UI emitter builds an error close's
RUN_ERRORdirectly from the fixedrun failedmessage, andpackUnitsbounds the closing frame as it does every other. The helper that could shorten an upstream failure detail behind a notice is gone: the close has passed only the fixed message since upstream detail stopped reaching the wire, so its truncation search never ran, and its notice-only fallback was larger than the event it replaced. A close whose envelope cannot fit still fails loud, now withpackUnits' refusal.takeCodePointsis no longer exported, since the preview splitter is its only user. Code that imported it takes a string's firstncode points withArray.from(s).slice(0, n).join(""). - Remove the unused
KNOWN_AGUI_EVENT_TYPESset from the AG-UI module. Its doc comment described a classification role thatparseAguiFramealready plays without it. The egress-guard differential cell that carried its name now says it counts the event typesAGUI_EVENT_TYPEdefines. - The
completionsection of the CLI page, which ships in the bundled docs, now shows how to enable completion in the current bash, zsh, fish or PowerShell session, lists the filescotal completion installwrites for each shell along with theXDG_CONFIG_HOMEandZDOTDIRoverrides it honors, and explains that the installed stub resolves candidates through the localcotal __completedispatcher. No behavior changes. - The CLI reference now says what running
pnpm cotalfrom a dev clone needs: apnpm buildfirst, becausebin/loads the other packages from their builtdist/, andCOTAL_SKIP_CONNECTOR_SEED=1for everyday commands, which otherwise refuse the operator-global seed store from a checkout. It also notes that pointingXDG_CONFIG_HOMEat a scratch dir is not enough on its own. Docs only. - The connector's capacity limits now say what they bound. The inbox size, the overflow-evicted classification memory, the focus exclusion limit and the protected-disposition limit carry doc comments naming the structures each one caps, including that the focus limit bounds the exclusion list and the id-less copy tally separately. The in-flight hold ceiling, which was an unnamed twice-the-inbox expression, is now its own constant derived from the inbox size, and the endpoint notice log's cap of 16 is a named constant. No values or behavior change.
- The auth service now builds its data account's signing context in one place. The authority plane's own mints, the remote manager credentials it issues and the delivery-admin endpoint all sign through it, where before the delivery-admin endpoint and the manager-service issue path each spelled their own copy. Credentials are unchanged.
- The run attempt and run revoke parsers now parse their own registered-manager envelope. They used to rewrite the request into a run admission with a placeholder
runand hand it to the admission parser. Amanager-run-attemptthat carries arunfield is now refused as an unknown field, where it was accepted and the field dropped. Attempt and revoke refusals name their own kind and carry themanager run attempt requestormanager run revoke requestprefix. The manager-service authority parser also refuses asessionrequest whosesessioncarries a key other thanid,endpoint,sessionId,epochandexp, and returns a session built from the checked fields, where it returned the caller's own object. cotal completionnow skips the connector-seeding boot gate alongside__completeandhelp. Sourcing completion in shell startup profiles no longer acquires the operator-global reconcile lock or rewritesstamp.json, and runningcotal completion <shell>from a development checkout no longer fails on the source checkout guard.cotal consoleandcotal joinnow print a seat's harness-reported condition and its ages the waycotal endpointsandcotal statusdo. The console roster, NEEDS YOU rail and detail pane, the--plainline stream, and thecotal joinpresence lines,Present:line and/whoshowwaiting (rate_limit for 40m) · unchanged for 5s · active 40m agoand the activity's(set <age> ago)instead of a barewaiting. The roster and each NEEDS YOU card put the status and these facts on rows of their own under the seat's name, wrapped to the pane's width at any terminal size, so neither a long name nor a narrow terminal cuts them and they no longer push the activity out of view. A seat that needs more rows than a short terminal leaves its pane takes the title's row and is cut at the bottom, keeping its name row, and Enter opens its detail pane with every fact. The console's ages use the shared compact format, so a heartbeat nine hours old reads9hrather than540m, and an age floors rather than rounds.cotal spawnwithCOTAL_ENROLLMENT_URLorCOTAL_ENROLLMENT_FILEagainst a registered remote user-mode mesh whose record pins no exchange URL now refuses before it redeems the enrollment, with the same "records no exchange endpoint" sentence and re-registration step the provisioning path gives. It used to spend the one-time enrollment and then refuse with "the enrollment's authServiceUrl does not match the registered mesh exchange", which hid the missing pin.- The delivery cutover preflight now checks the delivery-aware marker against the manager pid it attributed, without reading the manager pidfile a second time, and its stop signals only that pid. A delivery-aware manager that exits while
cotal upruns the preflight is no longer reported as an old Plane-3-hosting manager, and a manager that replaces the record meanwhile is no longer stopped in place of the one the preflight judged.cotal statusand thecotal up --runtimereuse warning check the marker against the pid from their own record read. - A spawn rolled back as an orphan on a user-auth manager no longer logs
despawn <name>: retirement confirmed for a prior lifecycle of "<name>"; the current hold is left intact. That lifecycle was never despawned and has neither a successor nor a hold on its name, so the manager now logsretire <name>: lifecycle <uid> retired; the name had no hold to clear. A late answer that arrives while a successor holds the name keeps the prior-lifecycle line, and a despawn that clears its own hold keeps the retirement-completed line. - The
cotal supervise --ws-porthelp and the user-mode session redemption refusal no longer cite internal plan labels. The manager's service endpoint, spawn action, session plane and console comments drop the same labels and their slice, checklist, ruling, pin and milestone tags, keeping the mechanism text and the SPEC references. The console page and client served to the browser carry the same cleanup. Only text changes.
What's Changed
- fix(connector-core): say what each MeshAgent capacity limit bounds by @davidfarah2003 in #3689
- fix(core): build the persona catalog directory in one place by @davidfarah2003 in #3690
- docs(cli): say what running from a dev clone needs by @MehulNegi in #2383
- docs(cli): document shell completion evaluation and persistent install by @apsian4352-coder in #2389
- fix(auth): build the data account's signing context in one place by @davidfarah2003 in #3696
- fix(core): decide reconcile-gate's raced refusal from the reopen outcome, not its message by @davidfarah2003 in #3699
- fix(connector-core): remove the unused AG-UI event type set by @davidfarah2003 in #3703
- fix(cli): refuse an enrollment spawn on a record with no exchange pin before redeeming it by @davidfarah2003 in #3706
- fix(core): classify a missing consumer by one structured rule by @davidfarah2003 in #3709
- fix(connector-core)!: remove unreachable RUN_ERROR detail bounding from the AG-UI emitter by @davidfarah2003 in #3710
- fix(cli): read the manager and delivery records through one attribution reader by @davidfarah2003 in #3712
- fix(lang): rebuild bridged failures from a class-keyed union with no defaults by @davidfarah2003 in #3717
- fix(cli): skip connector reconcile on shell completion stub generation by @apsian4352-coder in #2388
- fix(workspace): key seat writer generations through spaceKey by @davidfarah2003 in #3719
- fix(manager): stop reporting a prior lifecycle and a hold for an orphaned spawn's retirement by @davidfarah2003 in #3724
- fix(workspace): report a corrupt installed package.json instead of not installed by @davidfarah2003 in #3725
- fix(manager): drop internal plan labels from the --ws-port help and manager comments by @davidfarah2003 in #3729
- fix(core): drop deleted manager ctl tiers and plan labels from shipped comments by @davidfarah2003 in #3732
- fix(auth): parse run attempt and revoke requests with their own envelope by @davidfarah2003 in #3734
- fix(connector-claude-code): point the mapper header at its origin tables instead of a partial list by @davidfarah2003 in #3733
- fix(remotion): frame the header reel's mode cards at MODE_STAGE by @davidfarah2003 in #3739
- fix: keep a thrown envelope error's code and details in the control reply by @davidfarah2003 in #3742
- fix(web): name the dashboard pidfile through one workspace constant by @davidfarah2003 in #3756
- fix(cli): name the pidfile a start refusal read instead of re-resolving it by @davidfarah2003 in #3757
- fix(connector-codex): keep a stopping seat from binding its event plane by @davidfarah2003 in #3758
- fix(workspace): remove an account's or a root's registry entries in one batch by @davidfarah2003 in #3763
- fix(cli): show the presence condition and its ages in the console and join by @davidfarah2003 in #3765
- fix(cli): check the cutover preflight's delivery-aware marker against the attributed manager pid by @davidfarah2003 in #3766
- fix(core): validate issued spaces with canonical routing grammar by @davidfarah2003 in #3768
New Contributors
- @apsian4352-coder made their first contribution in #2389
Full Changelog: v0.78.1...v0.79.0