From 490f45f024dd75060c02c17ae1e862f1fdae0de7 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 22 Oct 2026 21:39:34 -0500 Subject: [PATCH] row 272: preserve untested session CLI and Console draft (sage-3145) --- BUILD-LOG.md | 8 + agents/huey/work/queue-272/BUILD.md | 160 ++++++++++++++ agents/huey/work/queue-272/manifest.draft.txt | 16 ++ docs/SESSIONS.md | 4 + packages/bus/src/broker.mjs | 8 +- packages/bus/tests/user-principal.test.mjs | 17 ++ packages/cli/README.md | 42 ++++ packages/cli/src/cli.mjs | 16 +- packages/cli/src/session.mjs | 94 ++++++++ packages/cli/src/thread.mjs | 23 +- packages/cli/tests/session-cli.test.mjs | 201 ++++++++++++++++++ packages/plugins/channel/cli/index.mjs | 5 + packages/plugins/channel/webui/index.mjs | 5 + packages/plugins/tests/channel.test.mjs | 4 +- packages/webui/src/chat-http.mjs | 51 ++++- packages/webui/src/chat.mjs | 11 +- packages/webui/src/public/chat.css | 6 + packages/webui/src/public/chat.js | 163 +++++++++++--- packages/webui/tests/chat-browser.test.mjs | 96 ++++++++- packages/webui/tests/chat.test.mjs | 79 +++++++ 20 files changed, 952 insertions(+), 57 deletions(-) create mode 100644 agents/huey/work/queue-272/BUILD.md create mode 100644 agents/huey/work/queue-272/manifest.draft.txt create mode 100644 packages/cli/src/session.mjs create mode 100644 packages/cli/tests/session-cli.test.mjs diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 215c8a2e2..d13ef571e 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -5389,3 +5389,11 @@ Row 299 (573, #1806, Gander, Filbert): before, the P10 band test timed a fault r 2026-10-23T11:03:46Z | Gyro Vikunja571 mos-1444 PRD d8 follow-on | Branch gyro/editor-571-d8 from origin/refactor c16e943b9. Both designs now keep library.convert outside ACTIONS/ROUTED and broker processing, retain REQ-WAIT-1/hard-wait test unchanged, constrain unmarked story eligibility to mapped book/playground scope, and add whole-host pre-import restore recovery from remote import manifests plus the Gitea archive commit. Lookups refuse until one current version is proven; VM1012 restore needs Jason present under Q185. W7 no longer owns hard-waits.test.mjs. Canonical queue next gyro returned nothing; direct Mos assignment governs. Static diff, exact replacement and append-only checks pass. No code, tests, build, browser, private-file or live action. Fenton re-check requested after authorized branch push. + +2026-10-22 | Huey | Row 272 / 264e (#1777) preparation on huey/row272, base 2d0d407ba. Before: bus session metadata and launcher isolation exist, CLI/Console expose only the saved thread default. Draft: session CLI, Console chooser with isolated drafts/cursors/receipts, metadata counts and safe-clear operation receipts against Gizmoduck's 0260 contracts; narrow deferred B6 reply fence. Tests authored, not run: Gander row 253 holds Sage's slot; no Node, claim, HTTPS git, push or live changes. This entry records preparation after the first draft, not a green acceptance result. + +2026-10-22 | Huey | Row 272 draft, 264d additive contract gizmoduck-0272 (78e14352f). Added confirmed cancellation through the human channel, cancelled receipt retirement distinction, named refusals and routed-message cancellation output. Before: cancelled was not recognized as terminal; after: draft CLI stops polling and Console shows the before/after retirement outcome. Acceptance remains unverified: no Node/tests/claim/commit/push under Sage's gate. No runtime/lifecycle authority expanded. + +2026-10-23 | Huey | Row 272 / 264e sage-3141 local rebase. Before: uncommitted draft on 2d0d407ba. After: same draft on new huey/row272-b23783f39 at b23783f39, with 270/271 landed (7328da8ca) and schema 3n. Product changes auto-merged; both append-only logs retain the full new base and original Huey additions. Checked landed session.list and clear/cancel/operation envelopes against the wired draft: no incompatible contract change. Historical unavailable-dependency cases stay as stand-ins; actual base supplies counters and lifecycle state. No tests/Node/claim/commit/push while Gander holds row 574 run 2. Existing-test fixture/assertion delta is named in the packet for Mos's ruling via Sage before execution. + +2026-10-23 | Huey | Row 272 sage-3145 preservation correction. refs/stash is shared, so it was unsafe as sole draft storage. Pinned exact stash commit 07dc9d2f7944b4781b5e80dfa18425f4749f7a45 to local huey/row272-stash-keep and left the entry untouched. Sage explicitly directed committing the rebased draft before testing to preserve it: an untested local checkpoint, no acceptance claim. No Node/test/queue/network/live action. Separate claims and test CLEARs remain pending; old-test delta is with Mos via sage-3144. diff --git a/agents/huey/work/queue-272/BUILD.md b/agents/huey/work/queue-272/BUILD.md new file mode 100644 index 000000000..355c4d03c --- /dev/null +++ b/agents/huey/work/queue-272/BUILD.md @@ -0,0 +1,160 @@ +# Row 272 / 264e (#1777): session CLI and Console chooser + +Owner Huey; reviewer Scrooge per sage-2816 / mos-1310 item 2 (supersedes sage-2796). Current base b23783f39, branch huey/row272-b23783f39 (sage-3141). Original draft base 2d0d407ba on huey/row272. +Brief: docs/plans/2026-10-21_t1-sessions.md (ff0be0c79), section 8; row 264 rulings +at 5f5b51dd6. Dependencies: 264a-d landed; 270/271 landing is 7328da8ca. +Count/clear implementation and contracts are now in the current base. No runtime, launcher, library adapter, +role, schema or queue edits belong to this slice. + +## Execution and evidence + +1. Read session/channel/HTTP/browser contracts and write isolation/validation tests. +2. Add session CLI through the existing verified human channel, preserving defaults. +3. Add authenticated Console chooser, per-session drafts/history/cursors, count and + clear status. Unavailable dependency verbs refuse explicitly; no simulated success. +4. On Sage's CLEAR: claim, run focused tests and required suites/mutants, repair and + record exact evidence. No Node, tests, HTTPS git, claim or push under Gander's gate. +5. After 253 and 269 land, rebase on a new branch name. Review packet to Scrooge, + Mos, Gizmoduck and Sage; push only when permitted. + +2026-10-22 preparation: clean worktree switched locally to the requested base. Read +approved brief and all Q1-Q7 rulings. Della notified: no startBroker/library changes. +Gizmoduck asked to pin count/clear contracts. Tests will be written first; Sage's +explicit gate restriction defers RED/GREEN execution. No test result claimed. + +Verification plan: CLI real-broker isolation and channel refusal; HTTP strict keys, +Origin/Fetch Metadata, forged selector/refusal and no retries; fixture-browser two +sessions, isolated draft/cursor/receipt, deep-link/refresh, count unknown/known, +read-only writes, clear confirmation/pending. Add selector omission and cursor/draft +sharing mutants. Broader cli/webui/plugins suites use Sage's gate only. + +264c/d contracts received gizmoduck-0260: session.list gains compactions and revision/state; +session.clear and session.operation use the pinned envelopes. CLI polls at most 30 s +then reports pending; Console status checks use GET only. Counts absent on 264b show +unavailable; unknown never becomes zero. Clear absent on 264b is disabled with a reason. +USER_VERBS and tester listener write policy remain unchanged (Q7). Existing collaborators +therefore cannot enter the new session surface until the reviewed RBAC integration. + +Consumer audit found the explicitly deferred B6 user-reply scope (DEFERRED.md:455-459, +queue-264/BUILD.md:317-322) bound to 272. Added a narrow broker predicate change from +thread to session and a sibling-session regression fixture, without widening user verbs. +This is the only planned broker change and does not overlap Della's runtime adapter. + +2026-10-22 static review: added explicit --session to thread read/open and talk/follow; +omission remains the saved default. CLI clear first reads a recorded operation, so a +repeat after a lifecycle revision change cannot become a conflicting second write. +Console deep links name both thread and session; accepted-send receipts, drafts and +history pagination use that tuple. Clear-status GETs refresh the envelope without +reissuing clear. Read failures discard private metadata; late generations cannot paint +another selection. Scrooge is reviewer per sage-2816 / mos-1310, superseding the first +assignment. CLEAR remains after 269, 275, 203 and 207. No execution evidence yet. + +## Acceptance / mutant map (prepared, unexecuted) + +| Check | Evidence file / intended kill | +| --- | --- | +| T5 legacy human, forged agent, foreign session, strict HTTP identity/Origin/site | session-cli.test.mjs, chat.test.mjs; unchanged USER_VERBS matrix in user-principal.test.mjs | +| T7 saved default, explicit CLI session selector, metadata-only create | session-cli.test.mjs real broker and thread CLI compatibility tests | +| T7 Console chooser, deep link, draft/cursor/receipt isolation, unknown count, confirmation/pending | chat-browser.test.mjs; existing history/sign-out/late-read tests run whole | +| Count/clear contract absence | CLI unavailable refusal; Console disabled clear reason; exact zero vs unknown lower bound tests | +| B6 assigned follow-up | user-principal.test.mjs sibling-session citation refusal and valid same-session reply | +| M1 omit session in chat.mjs messages forwarding | chat.test.mjs explicit selector deepEqual fails | +| M2 collapse browser state key from thread/session to thread | chooser draft isolation assertion fails | +| M3 treat known:false count:0 as exact zero | CLI label assertion and browser unknown-count assertion fail | +| M4 restore B6 mt.thread/s.thread predicate | user-principal sibling refusal assertion fails | +| M5 remove session from CLI thread.send payload | explicit --session talk assertion fails | +| M6 repeat a clear write in place of session.operation poll | CLI exactly-one-clear assertion fails | + +Intended focused commands, only after CLEAR, one process at a time: + +- `timeout -k 10 300 node --test packages/cli/tests/session-cli.test.mjs` +- `timeout -k 10 300 node --test packages/cli/tests/thread-cli.test.mjs` +- `timeout -k 10 300 node --test packages/bus/tests/user-principal.test.mjs` +- `timeout -k 10 300 node --test packages/plugins/tests/channel.test.mjs` +- `timeout -k 10 300 node --test packages/webui/tests/chat.test.mjs` +- `timeout -k 10 600 node --test packages/webui/tests/chat-browser.test.mjs` + +Whole touched suites on Sage's slot: bus (900 s), cli (1800 s, >=3x recorded 591 s), +webui (600 s), plugins (600 s), plus required integration scripts per final gate brief. +Mutants run in disposable copies of the pinned candidate, never against a live stack; +only failed assertions count as kills, never a timeout or import/setup failure. +No test process, browser, provider, credential read or live service action ran in this +preparation. `git diff --check` is the only executed draft verification so far. + +Next: Sage CLEAR for claim/focused runs; repair against actual results, then rebase on +a newly named branch once 253 and 269 land. Generate final manifest only after those +changes. Review handoff is Scrooge and Mos, copying Gizmoduck and Sage; no handoff to +Duckworth under the superseded assignment. No candidate commit or green claim yet. + +2026-10-22, gizmoduck-0272 / sage-2828 additive contract at 78e14352f: added +session.cancel to CLI/channel/Console with confirmed human writes and strict keys. +Cancelled envelopes retain `retired:null` (old active) or `true` (startup cancelled, +old retired); cancelled is terminal for polling. CLI reports routed message cancellation +with stored ID and exit 3, never waits for delivery or replays it. HTTP maps +session-name-too-long and session-clear-complete without reflecting transport text. +Added unexecuted before/after cancellation, identity/Origin, confirmation and message +receipt tests. Existing clear/create/read wiring is preserved. Asked Gizmoduck whether +the deterministic successor keeps 264a's UUID shape, as selectors currently require. +No Node, test run, claim, commit, push, provider call or live action. Static diff only. + +Gizmoduck-0274 resolves the selector compatibility check: successors are lowercase +RFC 9562 v8 UUIDs (variant 10), while 264a sessions are v4. Existing generic UUID +validators accept both and stay unchanged. CLI explicit-selector and Console chooser +fixtures now include mixed v4/v8 IDs to prevent a later v4-only regression. Unexecuted. + + +## sage-3141 rebase and landed-contract check (2026-10-23) + +Reapplied the uncommitted draft onto b23783f39 in the same isolated worktree, on new +branch huey/row272-b23783f39. No candidate commits existed to replay. Preserved the +original draft in the named local stash `huey row272 draft before sage-3141 rebase`. +Product files merged without conflict. Only append-only BUILD-LOG.md and SESSIONS.md +conflicted: kept every new-base byte and appended the original Huey entries unchanged. +No force push, fetch, Node, test, queue write or live change. No claim or candidate +commit yet. Static `git diff --check` clean after resolution. + +Checked the actual landed broker, not just the older contract packet: + +- broker.mjs:687-707 clearEnvelope supplies the same op/thread/session/successor/state/ + start/refusal/at fields and cancelled-only retired:null|true. The generic UUID + selectors still accept both original v4 and successor v8 IDs. +- broker.mjs:6227-6245 session.list supplies compactions, state, revision and successor; + count reader/unknown behavior is the landed 270 contract. Real-base tests must now + exercise these available fields; stand-ins still exercise an unavailable dependency. +- broker.mjs:6270-6330 clear/cancel/operation inputs and receipts match the wired contract. + clear repeats preserve the op; cancel also refuses a failed clear as + session-clear-complete. Our existing refusal mapping already covers it. +- queue-271/BUILD.md:225-238 clarifies cancellation after retirement cancels this clear's + startup, while later deliberate human open/send can start the fresh successor. It + does not permanently disable that new session. No frontend authority change needed. +- store.mjs:17 is 3n; migration is 3m-3n.sql. This slice adds/pins no schema step, + migration blob or schema test count. No DDL copied from an older branch. + +Plan after the Gander 574 run-2 hold: on a claims-only CLEAR, claim only; run no Node +or tests beyond the explicit scope of Sage's grant. On test CLEAR run new CLI tests +first, then new broker/HTTP/browser cases and whole touched files, sequentially under +the recorded timeouts. Place/report a first-run red only in a new test; do not alter +an old test, loosen an assertion or fix a second red without Mos's ruling via Sage. +Whole-suite/mutant execution remains on Sage's slot. Candidate commit and push follow +applicable green evidence and an allowed gap, then Scrooge/Mos handoff with final SHA, +manifest, copying Gizmoduck/Sage. + +Existing-test edits in the inherited draft need Mos's ruling through Sage before +execution: channel.test.mjs extends its existing supported-verbs table for five +session verbs; chat-browser.test.mjs extends the existing fetch fixture with session +catalog/operation responses and changes its exact send-payload assertion to include +the selected session. Assertions are not loosened. All other added test cases are +new tests. These changes were prepared before sage-3141 and have never run. Ask Sage +to forward this precise delta rather than treating a later old-test red as permission. + +sage-3145 correction: refs/stash is shared across worktrees; using it as sole draft +storage was wrong. Pinned the exact draft commit 07dc9d2f7944b4781b5e80dfa18425f4749f7a45 +on local branch huey/row272-stash-keep before any stash cleanup. The entry remains +untouched; the branch retains its tracked and untracked snapshots. Future seat draft +preservation uses owned branches/local commits, not shared stash positions. + +Sage explicitly directed a local draft commit before tests to preserve the rebased +work. This overrides the normal green-before-commit gate for this storage checkpoint +only. It is an untested draft, not an approved candidate, test result, push or landing. +Claims await the post-574-run-2 CLEAR; test execution awaits Mos's ruling and Sage's +separate test CLEAR. Old-test deltas were forwarded as sage-3144; no ruling assumed. diff --git a/agents/huey/work/queue-272/manifest.draft.txt b/agents/huey/work/queue-272/manifest.draft.txt new file mode 100644 index 000000000..0be3ac415 --- /dev/null +++ b/agents/huey/work/queue-272/manifest.draft.txt @@ -0,0 +1,16 @@ +fb518c370aeb531220de123464f0a809156fc546b51d7195f4f9ca660409cf22 packages/bus/src/broker.mjs +35d044b0904ce913b3356b02cdc5bf22babecf738b511dca80c75f704e4ef78e packages/bus/tests/user-principal.test.mjs +e795bc4ee5aa038835edfeabe3498e53fdd700df478198cac6767498e2fac0b7 packages/cli/README.md +96c4f93628964b6ea10fb87d5cf936f9ecf2e7286aa20c0914ae8b0fb32c47e7 packages/cli/src/cli.mjs +0c31ac7260e77556f30f33a9932dc59a30f394982d8556650af7c521d2bcc947 packages/cli/src/session.mjs +58888b7731f8009d4c3f8be2caf4445f13dd8f534e1633f6e2720b259fcc3f92 packages/cli/src/thread.mjs +27fb7dd91007ec5f729fbe854219f423177cf4db2d44d1f8b04c7e8c5e6db90a packages/cli/tests/session-cli.test.mjs +5e7e1ec169392ee3065f8f47d19732ebbe8bdd90f9193581425b956e66da6b73 packages/plugins/channel/cli/index.mjs +aa086c365c4a6b0eaf84359a20ef2b30e723013ada6573fb0133163d5bf98a74 packages/plugins/channel/webui/index.mjs +143bf601badf5cc2b25cb24368ace2ec34840abec858d272af239d6a4ddcdecb packages/plugins/tests/channel.test.mjs +0720f66a57d965c9275f598b7c7ac438f238a0fac52808fc8f10312b85ba2727 packages/webui/src/chat-http.mjs +65fd3fd2337aaa88245a9fb10b55fd872f9150085ff9a53fe522e758a93c64fa packages/webui/src/chat.mjs +88dd353f5df0603ed1fd43dd543ef7b45af93fee72b6bb6a03a26c068202fbd3 packages/webui/src/public/chat.css +074d570aee4e2b6cdcbd6b8be399a2a21e863f2d620f95dad8d93ffc7d9c46da packages/webui/src/public/chat.js +2161c4830a3f73f0343e76521b948b933e401f7b9ba4ef8a5c75bf99c565d6b6 packages/webui/tests/chat-browser.test.mjs +b79a8809951580187b581450cdd4012245f2d88a371bf7d2f123580af8815449 packages/webui/tests/chat.test.mjs diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 6420f21d4..6b905b0b5 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -1577,3 +1577,7 @@ are never rewritten or removed; corrections are new entries. - 2026-10-23T10:48:40Z | sage (Opus 5.5, 1ef1e4f8) | 302/295/219 landings, Docker pool diag, 590/591 briefs, 272 rebase | 302 LANDED 3ed9fd754, 295 LANDED 2efd127ce, 219 LANDED 5fdfd7275 (#1720 c31110, P19 416 c913); test-release 11/3 from exhausted Docker pools, 18 networks removed (mos-1437/1438); queue-commit 90633c864 (revs 3495-3510, 3510 Huey's); 272 rebase and fallback ruled (sage-3357) 2026-10-23T11:03:46Z | Gyro (Codex gpt-6.1-sol, mos-1444) | Vikunja571 PRD d8 docs alignment | R6 vocabulary boundary, mapped-folder eligibility and R14 whole-host recovery updated in parent/W4; static checks only, no tests or live changes. Fenton reviews; Sage lands. - 2026-10-23T11:47:32Z | filbert (Claude Opus 5.5, T3 048f3c63) | row 305 round 1 (#1812, Vikunja 591, Gizmoduck, candidate 7e8218a2e) | approve in 31127, rev 3534; static on git objects (scripts = 3bce852d5; traps kept, no compose down, ls failure fails, skip only on docker info); gate receipts read, not rerun: Gizmoduck run1 + Sage gate task 92/0, release 15/0, mutants a/b red, c survives +2026-10-22 | Huey (Codex gpt-6.1-sol, cabd45ca) | Row 272 / 264e (#1777), sage-2796, huey/row272 on 2d0d407ba | CLI/Console session work in preparation; test execution/claim/push deferred under Gander's gate, no runtime or live change. +2026-10-22 | Huey (cabd45ca) | Row 272 additive 264d contract gizmoduck-0272 at 78e14352f | Draft cancellation UI/CLI and terminal receipts added; tests authored but not run under sage-2816 gate, no commit/push/live change. +2026-10-23 | Huey (cabd45ca) | Row 272 sage-3141 local rebase | Draft reapplied from 2d0d407ba onto b23783f39 on huey/row272-b23783f39; product merge clean, append-only log conflicts retained both sides. Landed 270/271 contracts checked; no Node/tests/claim/commit/push pending CLEAR. +2026-10-23 | Huey (cabd45ca) | Row 272 sage-3145 draft preservation | Shared stash commit 07dc9d2f7 pinned to huey/row272-stash-keep; rebased draft committed locally by explicit Sage instruction before tests. Untested checkpoint only; claims/test/push CLEARs still pending. diff --git a/packages/bus/src/broker.mjs b/packages/bus/src/broker.mjs index 20da8b84c..8bc57b116 100644 --- a/packages/bus/src/broker.mjs +++ b/packages/bus/src/broker.mjs @@ -5607,13 +5607,13 @@ export class Broker { ) fail('tester-reply-required'); // FED R3 (design 3.6 item 7, B6): a run answers a user only in reply to that user's message - // in its own thread, the thread the user owns. Anything else, another user's message or one - // outside the thread included, refuses. + // in its own session of the thread the user owns (264e, deferred B6). A sibling + // session, another user or another thread cannot supply that citation. if (to === 'user') { const m = id(a.in_reply_to) && s.thread ? this.#store.get( - "SELECT m.from_run FROM messages m JOIN message_threads mt ON mt.message=m.id JOIN threads t ON t.id=mt.thread WHERE m.id=? AND m.business=? AND m.from_role='user' AND mt.thread=? AND t.owner=m.from_run", - a.in_reply_to, s.business, s.thread) + "SELECT m.from_run FROM messages m JOIN message_threads mt ON mt.message=m.id JOIN threads t ON t.id=mt.thread WHERE m.id=? AND m.business=? AND m.from_role='user' AND mt.session=? AND t.owner=m.from_run", + a.in_reply_to, s.business, s.session) : null; if (!m) fail('user-reply-required'); } diff --git a/packages/bus/tests/user-principal.test.mjs b/packages/bus/tests/user-principal.test.mjs index 8471ddf85..3b795bc8e 100644 --- a/packages/bus/tests/user-principal.test.mjs +++ b/packages/bus/tests/user-principal.test.mjs @@ -413,3 +413,20 @@ test('C2-09a: naming an instance cannot bypass its collaborator grant or disclos assert.equal(bean.instance, 'bean'); assert.equal(ctx.code('alice', 'thread.create', { project, name: 'old instance', instance: 'assistant' }), 'access-refused'); }); + +test('264e deferred B6: a reply cannot cite the same user in a sibling session', t => { + const { b, store, caps, call, A } = granted(t); + // Session writes remain off USER_VERBS (Q7). Seed the future multi-session case directly, + // without granting a collaborator new authority just to exercise the reply fence. + const sibling = 'f0000000-0000-4000-8000-000000000001'; + store.run("INSERT INTO sessions(at,business,thread,id,instance,owner,name,op) SELECT at,business,id,?,instance,owner,'sibling','264e-fixture' FROM threads WHERE id=?", sibling, A); + const original = call('alice', 'thread.send', { thread: A, body: 'original asks' }).id; + const second = call('alice', 'thread.send', { thread: A, session: sibling, body: 'sibling asks' }).id; + caps.worker = b.bindLaunch({ business:'demo', role:'assistant', run:'session-worker', harness:'pi', thread:A, session:sibling }); + call('worker', 'role.claim'); + const before = store.get('SELECT count(*) n FROM messages').n; + assert.throws(() => call('worker', 'message.send', { to:'user', in_reply_to:original, body:'wrong context' }), { code:'user-reply-required' }); + assert.equal(store.get('SELECT count(*) n FROM messages').n, before); + const reply = call('worker', 'message.send', { to:'user', in_reply_to:second, body:'right context' }); + assert.equal(store.get('SELECT session FROM message_threads WHERE message=?', reply.id).session, sibling); +}); diff --git a/packages/cli/README.md b/packages/cli/README.md index da8356659..754a74e20 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1147,3 +1147,45 @@ result. Resume refuses unconfirmed stops and a stale generation. A restarted `bus start --pm` keeps its control bus up while halted and skips the chief. The switch does not clear other launch/Discord brakes or retry tasks. Native diagnostic launch stays available. See packages/processing-control/README.md. + +### Independent thread sessions (264e) + +`mosaic session list ` lists logical sessions and the saved default. `show` +reads metadata/count; `open ` requests that session's normal guarded +launch. Reads and `create --op ` spend nothing and start no run. +Use `--json` for receipts and `--business ` as on the thread commands. A session +reference is its full ID, unambiguous ID prefix (8+ characters), or exact name in that +thread. Creating or opening a session never changes the saved default. Legacy thread +commands continue using that default. + +`mosaic session clear --yes --op ` requests safe context +replacement. The confirmation preserves old history and all old workspace files, +including dirty/untracked/unpushed work. The successor gets a fresh checkout at the +approved revision; old work is not silently copied. No forced stop is authorized. +The command waits up to 30 seconds by reading `session.operation`, then prints pending +if stop proof/capacity is outstanding. Keep the operation key: `mosaic session operation + --json` reads the recorded outcome. A transport failure never triggers an +automatic second clear. Count/clear dependencies that are not installed report +unavailable; unsupported or incomplete count evidence reports unknown, never false zero. + +The Console Chat thread pane offers the same chooser, New session and Clear context. +Links preserve the selected session; drafts, paging cursors and receipts belong only +to that session. Clear status can be checked with its operation key without another +write. Read-only listeners disable writes. Until the reviewed multi-user integration, +these operations retain the legacy human's own-thread authority; they grant neither +collaborator session writes nor organization-owner access to others' private context. + +To address a nondefault session explicitly, use `mosaic talk --thread +--session `, `mosaic follow --thread --session `, +or `mosaic thread read|open --session `. Omitting `--session` preserves the +legacy saved-default behavior; opening a chooser session never redirects later sends. + +`mosaic session cancel --yes` cancels a clear using its recorded +operation key. Before retirement this restores the old session to active without +replaying cancelled inputs. After retirement it cancels successor startup only; the +old session stays retired. A successor that already started refuses cancellation. +The Console's Check clear operation field and Cancel clear action use the same key +and require confirmation. Cancellation adds no force-stop or kill-switch authority. +Both before/after outcomes appear as `cancelled`, with `retired: null` or `true` in JSON. +If a routed message is stored but cancelled because its session is clearing/retired, +the CLI prints its ID, reports the cancellation and exits 3 without waiting for a reply. diff --git a/packages/cli/src/cli.mjs b/packages/cli/src/cli.mjs index 3ee9c9a97..6f830e0d6 100644 --- a/packages/cli/src/cli.mjs +++ b/packages/cli/src/cli.mjs @@ -15,6 +15,7 @@ import { fileURLToPath } from "node:url"; import { BINDING_NAME } from "../../discord/src/binding.mjs"; import { projectBusCommand, projectCommand, PROJECT_BUS_USAGE, PROJECT_USAGE } from "./project.mjs"; import { resolveThread, threadCommand, threadMembers, threadsCommand, THREAD_TALK_USAGE, THREAD_USAGE, THREADS_USAGE } from "./thread.mjs"; +import { sessionCommand, SESSION_USAGE } from "./session.mjs"; import { limitsCommand, LIMITS_USAGE } from "./limits.mjs"; import { pluginsCommand, PLUGINS_USAGE } from "./plugins.mjs"; import { credentialsCommand, CREDENTIALS_USAGE } from "./credentials.mjs"; @@ -50,6 +51,7 @@ export const USAGE = `usage: ${PROJECT_BUS_USAGE} ${THREADS_USAGE} ${THREAD_USAGE} + ${SESSION_USAGE} mosaic inbox [--business ] [--json] [--tester] mosaic inbox --read ... | --read-all [--business ] mosaic decide