Compare commits

...
3 changed files with 388 additions and 0 deletions

No files matched your search

+6
View File
@@ -5213,3 +5213,9 @@ Before: managed project/thread verbs had no Console conversation area. After: fi
2026-10-21T21:43:02Z | Della mos-1223 / Vikunja 460 phase C synthesis | Before: independent plans/reviews complete, Mos selected Della base. After: docs/plans/2026-10-21_email-plan.md merges Ludwig grafts and accepted corrections, with 16 post-v1 rows (eight READY, eight WAIT/optional), eleven deduplicated Jason questions, per-row test paths and explicit Q210 non-v1 scheduling. Original Della plan/review preserved; Ludwig originals remain on their branch. Static checks cover graft/row/question/citation anchors and original blobs. No source code, suite, mailbox, secret file, service, MVP or queue change. Candidate goes to Ludwig before Sage landing/queue handoff, copying Mos.
2026-10-21T21:45:20Z | Della mos-1223 / ludwig-0004 focused corrections | Before: b096a16cc left content-key location implicit and E05 core registration marked ready. After: merged plan 399 lines fixes external configDir secret key/lifecycle namespace outside dataRoot backup/restore, E01 schema and E03 missing/expired-key restore tests, and E05/E06 test-local registry readiness with core kinds.mjs registration gated on approved E01/Q4. Sixteen rows and eleven questions retained; originals unchanged. Focused static checks and queue guard apply, no product/live changes. Reviewer will check changed lines only.
2026-10-21T22:24:12Z | Huey | T1 item 7 sessions design r1, mos-1232, Vikunja 463 | Before: origin/refactor cca206cdc keys assistant claims/stores/messages by thread and renders Pi compaction markers; row 194 r4 excludes thread context clear. After: docs/plans/2026-10-21_t1-sessions.md proposes independent per-agent sessions within threads on Pi/Claude, scoped claims/stores/messages/workspaces, completed compaction counts, owner-write/RBAC matrix, idempotent proven-stop/fresh-successor clear, common admission/kill checks, migration and seven acceptance groups, replacement REQ-ROLE-2/REQ-THREAD-2 text and three owner questions. PRD 1.12 USER-3/4 candidate 1509c7cc5 cited separately from base. Verification: 22 pinned references resolve, eight-line summary and three exact owner quotes; manual source/consistency review, whitespace and installed queue guard checked. No code, queue/PRD edits, builds, suites, credential reads, live changes or paid calls. MVP priority ahead of Q198 S1. Review via Scrooge, then Sage/Ludwig as Mos authorized.
2026-10-21T22:28:56Z | Huey | T1 sessions design r2, scrooge-0006, mos-1235/1236, Vikunja 463 | Before: r1 347278044 lacked the exact per-session checkout/single-writer invariant and safe runner drain ordering, and admitted other role instances. After: F1 exact workspace path, fenced checkout setup, legacy shared-workspace quiescence, clear retains old dirty/untracked/unpushed checkout and creates fresh approved checkout, T2 mutant; F2 dequeue fence and generation-bound turn-boundary idle proof before runner signal, busy drain stays clearing, T4 cases; F3 THREAD_DEFINITION only per Mos scope ruling, no role eligibility change; N1 private titles/history vs owner-visible count/activity projection; N2 Claude offline adapter/managed-store-reader dependency flagged as MVP risk. Section 8 records Mos’s Q1–Q3 readings, no questions to Jason. Verification: 27 pinned references resolve, summary within 15 lines, source/delta consistency review, whitespace and installed queue guard checked. No code, queue/PRD edits, builds/suites/live changes/provider calls/credential reads.
2026-10-21T22:30:20Z | Huey | T1 sessions design r3, scrooge-0007 R1, Vikunja 463 | Before: r2 e19e30df2 nested new session checkouts under the retained legacy instance workspace, allowing project-name collision or historical parent inspection to reach live siblings. After: exact path is dataRoot/session-workspaces/business/instance/session, outside the legacy root; canonicalized ancestor/descendant overlap refuses; T2 nesting mutant covers historical mount/inspection and a legacy project named sessions. All other r2 content retained as approved, revision label updated. Verification: old nested path absent, manual R1-only delta, whitespace and installed queue guard checked; no code/builds/suites/live changes/provider calls/credential reads.
+3
View File
@@ -1444,3 +1444,6 @@ are never rewritten or removed; corrections are new entries.
2026-10-21T21:37:07Z | Della (GPT-6.1-Sol, mos-1220) | Vikunja 460 phase B email cross-review, della/email-plan | Ludwig plan 4a27b73ac and review 143415779 read in full. Cross-review has ten findings and eleven merged questions; original Della plan unchanged. Canonical queue next della: nothing. Static verification only; review push followed by direct della-0002 handoff to both threads under Q210. Phase C base choice remains with Mos.
2026-10-21T21:43:02Z | Della (GPT-6.1-Sol, mos-1223) | Vikunja 460 phase C merged email plan, della/email-plan | Mos-selected base plus Ludwig grafts; original plans/reviews unchanged. Sixteen post-v1 rows, eight READY and eight WAIT/optional; eleven Jason questions. Canonical queue next della: nothing. Docs-only checks. Commit/push then immediate della-0003 handoff to Ludwig/Mos; Sage landing/queueing follows approval.
2026-10-21T21:45:20Z | Della (GPT-6.1-Sol, mos-1223 / ludwig-0004) | merged email plan focused review fixes | External content-key/expiry location and restore tests specified; fake registry work READY, production registry gated on PRD approval/Q4. Merged plan 399 lines, original plans/reviews unchanged. Commit/push and focused Ludwig review before Sage handoff.
2026-10-21T22:24:12Z | Huey (gpt-6.1-sol) | mos-1232, MVP T1 item 7 sessions design, Vikunja 463, huey/t1-sessions-design from cca206cdc | design with pinned code/row194/PRD candidate evidence and acceptance proposals; doc checks only, no builds/suites/live changes/provider calls; review then Sage/Ludwig handoff
2026-10-21T22:28:56Z | Huey (gpt-6.1-sol) | T1 item 7 r2, Vikunja 463, scrooge-0006 F1–F3/N1/N2, mos-1235/1236 | workspace/drain fixes and THREAD_DEFINITION scope recorded; Mos rulings in section 8; doc-only verification, re-review via Scrooge/Mos
2026-10-21T22:30:20Z | Huey (gpt-6.1-sol) | T1 item 7 r3, scrooge-0007 R1, Vikunja 463 | isolated session-workspaces root and nesting mutant recorded; R1-only confirmation requested, other r2 findings closed; doc-only checks
+379
View File
@@ -0,0 +1,379 @@
# T1 item 7: independent sessions, compaction counts and clear context
Give each thread several independent agent sessions on Pi and Claude Code.
Each session has its own context, inbox, claims, native store and compaction count.
Clear context retires one session and creates a fresh successor, preserving history.
Only the thread’s human owner with current write access may create or clear sessions.
Read-only shares permit viewing counts/history, never starting or clearing work.
Every new/successor run passes normal launch, limits, admission and kill checks.
This is MVP work under Q176 and Mos’s Q211 reading, ahead of Q198 S1.
No runtime changes, provider calls or activation are authorized by this document.
Brief: **mos-1232**, Vikunja **463**. Owner Huey, reviewer Scrooge, gate/landing Sage.
Design r3, scrooge-0007 R1; all other r2 content approved. Section 8 records Mos’s rulings.
Other proposed choices below are **Huey’s readings**, pending review.
## 1. Authority and pinned evidence
Jason, verbatim, `/mnt/storage/src/jason-master-restart/TARGET.md`:
> Agents can have multiple independent sessions within a given project (thread)
Line 57 above outranks the narrower PRD thread/session relationship under Mos’s Q211
reading. Lines 104–105, verbatim:
> User must be able to see the number of compactions that have occurred for a session
> User must be able to easily clear the context for the agent to trigger a new session
Q176 places the Given list and Cases 1/2 on the MVP path. Q211 says the PRD is partly
stale, with Mos’s reading retaining v1 requirements and giving the 10-27 rulings priority
(`/mnt/storage/src/jason-master-restart/DECISIONS.md:1414-1430,2048-2062`). This design
changes the PRD text explicitly, rather than silently retaining one session per thread.
All repository code citations below are at **`cca206cdce9e9726c7b491173c096a4ca6455d8d`**,
the fetched `origin/refactor` used for this branch. Two additional committed references
are labelled separately. Documentation proves a requirement/design, not implementation.
| Ref | Verified fact | Reuse or required change |
| --- | --- | --- |
| F1 | PRD requires one assistant holder per thread and one assistant session per thread: `docs/prd/mosaic-stack.md:254-267,960-966`. | Replace those two requirements in section 7. Keep role and assistant authority protections. |
| F2 | Thread rows bind project/instance/owner; claims and message links key on thread: `packages/bus/schema.sql:240-271`. Broker refuses a second thread holder: `packages/bus/src/broker.mjs:2646-2665`. | Add explicit session identity below a thread. A second process cannot simply reuse the current claim. |
| F3 | Create chooses exactly one assistant instance, and open/send/read target thread: `packages/bus/src/broker.mjs:3460-3557`. Thread eligibility is definition-based: `packages/cli/src/launcher.mjs:237-239`, `packages/bus/src/broker.mjs:389-390`. | Preserve that thread agent and eligibility policy. Add only a session selector, not other role instances. |
| F4 | Persistent Pi and Claude transcript locations are per thread, with ownership/mode/symlink checks: `packages/seat/src/session.mjs:51-74`. Registry running key is business/instance/thread: `packages/seat/src/session.mjs:215-218`. | Add session to storage and liveness keys, retaining path safety. |
| F5 | Pi adapter resumes the most recent native session in its supplied directory; Claude persists a native ID and later uses resume: `adapters/pi/adapter.sh:39-53`, `adapters/claude/adapter.sh:49-59,87-101`. Both harness plugins resolve transcripts through the supplied store: `packages/plugins/harness/pi/index.mjs:73-75`, `packages/plugins/harness/claude-code/index.mjs:128-130`. | Separate directories and pinned native IDs, never “most recent across the thread”. |
| F6 | Sandbox mounts the supplied thread store read-write and gives each run a fresh HOME: `packages/seat/src/sandbox.mjs:101-121,159-164`. | Mount only the selected session’s store. Do not expose siblings’ native stores or scratch HOME. |
| F7 | Pi stream compaction start/end events are known but unshown, summaries map to compaction blocks: `packages/conversation/src/events.mjs:23-34,40-49,74-76`. Native history entries become compaction markers: `packages/conversation/src/pi.mjs:180-191,254-257`. | Count completed durable compactions, not stream fragments or starts. |
| F8 | Console labels compaction blocks but the cited app.js:104 is now control-character handling; labels/fields are at `packages/webui/src/public/app.js:104-111`. Reader supports Pi histories and marks other harnesses unsupported: `packages/conversation/src/reader.mjs:1-12,22-24,36-51`. | The gap-map pointers still demonstrate markers, not a numeric counter or Claude support. Add a host counter for both harnesses. |
| F9 | Launcher refuses duplicate instance/thread runs, checks limits and feeds the supplied store into start: `packages/cli/src/launcher.mjs:233-240,313-341,364-367`. Workspace is per instance and hostile-clone checks assume no session writes during setup: `packages/cli/src/launcher.mjs:345-354`, mounted rw at `packages/seat/src/sandbox.mjs:110-111`. | Add a per-session workspace and single-writer fence, not just a narrower duplicate-run key. The current per-thread registry key does not prove single writer across different threads. |
| F10 | Conversation controller is explicitly fixture-only: `packages/conversation/src/controller.mjs:1-13`. Runner stop signals its child group TERM then KILL: `packages/harness/src/runner.mjs:396-418`. | Do not claim the Pi controller already supplies a production stop proof for both harnesses. Integrate the reviewed managed-run stop owner, and require its proof before replacement. |
| F11 | State injected at a turn includes current launch state and task titles: `packages/harness/src/runner.mjs:109-122`. | Scope state, deliveries, task details and reply routing to the session’s permissions. A new native file alone does not clear copied prompt/context. |
**F12 Row 194 r4**, separate commit **`646cd493af525712568994e61c0ccccc1712bd60`**,
`agents/honker/work/queue-194/DESIGN.md:131-140,447-452,485-494`: non-thread regenerate
waits for old exit, preserves workspace and refuses `regenerate-thread`; T1 item 7 owns
thread context clearing. Its r4 changes are recorded at `:694-707`. This document does
not repurpose whole-instance regenerate to clear one session.
**F13 Human requirements**, separate PRD 1.12 candidate commit
**`1509c7cc5747d4927323615afe29f87bfdbb1818`**, `docs/prd/mosaic-stack.md:1027-1052`:
REQ-USER-3 gives collaborators project/instance-scoped writes and viewers read-only
access. REQ-USER-4 makes shares read-only and requires current grants, including the
thread owner’s grant for access to their shared thread. These IDs are absent from the
pinned base PRD. Chain on row 193’s reviewed authorization hook and Ludwig’s PRD update,
not an ad hoc role system or a claim that the candidate is already landed.
**F14 Q198 is a landed design**, `docs/plans/2026-10-21_q198-system-manager.md:76-98,110-124,156-161,396-412`.
It specifies durable admission/claims, kill boundaries and centralized route authority.
It does not prove a running manager. The branch history includes its documentation
landing at `3a853f35d`. T1 does not wait for post-MVP manager implementation to exist.
## 2. Session identity and independence
**D1 Model.** A project contains threads. A thread retains its owner, sharing and
configured agent, and contains N named sessions for that same agent. **Per mos-1236,
only THREAD_DEFINITION instances may hold thread sessions**. Keep the eligibility
predicates at launcher.mjs:237-239 and broker.mjs:390 unchanged. Other roles holding
thread sessions would change launch policy and are outside Vikunja 463. Several sessions
for the thread’s agent may run independently, on either supported harness.
Session = durable logical identity/context. Run = one process execution. Idle/restart
resumes that session. Clear = a new logical session, not another run of the old context.
Concurrency is allowed subject to instance/model/account/host limits, not promised as
unlimited. This changes claim/schema granularity for the already-eligible thread agent,
not role eligibility or authority. No roles/ declaration is added or widened.
One holder per `(organization, thread, agent instance, session)` with generation fencing.
Run capabilities, deliveries, reply correlation, task/approval consumption and native
stores all bind that tuple. Role-instance authority remains the ceiling, and tokens,
credentials, quotas and grants remain constrained by their original scopes. A pending
approval bound to an old holder/session does not transfer to a successor or sibling.
An instance-wide terminate/fire still stops all its owned runs without deleting context.
No new hire/fire/revoke grant is introduced by concurrent sessions.
**D2 Isolation.** Add immutable session creation records and append-only session events,
claims and message-to-session mappings through a reviewed bus migration. Record opaque
session ID, organization/project/thread/instance, owner, harness, creation operation,
predecessor (clear only), revision, native binding and lifecycle state. One current
holder per session. A UI’s selected session is a request parameter, never global state.
Every turn/request names session ID and expected generation. Late old-run replies remain
attached to the old session and never appear as a successor’s answer.
Generated safe native storage: `<dataRoot>/threads/<business>/<thread>/sessions/<session>/`,
with separate `session/` and `claude-projects/` directories. The exact workspace is
`<dataRoot>/session-workspaces/<business>/<instance>/<session>/`, with the broker-bound
session ID globally unique in that business and checked against its thread/instance.
Scratch/HOME remains per run inside its selected session’s execution environment.
**Workspace invariant (F9):** exactly one owned writer per session workspace, including
across thread IDs and concurrent launcher instances. Hold the session generation/start
fence through checkout validation/setup and spawn. No old session run may write while
host git performs hostile-clone checks. A restart waits for proven prior-run exit, not
only claim release. Reject an alias/hardlink/shared checkout or unsafe path that would
bind two session IDs to one mutable repository. A private per-session lock plus the
broker’s unique holder/generation fence covers concurrent host-launcher processes.
Do not treat the old per-thread `instance-running` check as proof of single writer.
Keep non-thread work on its existing exclusive instance path. T2 covers cross-thread
and same-thread sessions and malicious workspace substitution. The session-workspaces root
is outside retained legacy workspaces. Refuse ancestor/descendant overlap with legacy
workspaces, historical workspaces or another live session workspace after canonicalization.
Derive paths server-side from validated IDs, verify ownership/private mode and refuse
symlinks/escapes. Mount only that session’s stores. Project files remain accessible only
through existing project grants and isolated checkouts, not by mounting sibling stores.
Concurrent sessions never share a harness HOME, auto-memory, native “latest” pointer,
inbox/history cursor or mutable workspace checkout. Shared project facts stay explicit
project sources. Conversation history and scratch files are never ambient context.
**D3 Message routing.** New APIs take an explicit session ID. The existing thread-only
CLI/API maps to one persisted default session for that caller/thread’s primary assistant.
Creating another session does not silently change that default. Legacy history remains
associated with the original default. New sends bind session at acceptance, so a later
UI selection cannot redirect an accepted message. Read/list/open enforce the same owner
and sharing boundary as send and count. No implicit fan-out or inter-session context
sharing. The agent remains the thread’s configured THREAD_DEFINITION instance. A request
selecting another role/instance refuses rather than changing thread launch policy.
## 3. Human authorization and Console
**D4 Authorization matrix**, applying REQ-USER-2/3/4 to every request and again at effect:
| Ref/caller | Read session/history/count | Create/open/send/clear |
| --- | --- | --- |
| A1 Thread-owning organization owner | Yes | Yes, subject to instance policy |
| A2 Thread-owning collaborator | Yes while current project/instance grant covers it | Yes while that write grant covers it |
| A3 Viewer or read-only share recipient, including organization owner viewing someone else’s share | Only with current read/share access | No. Opening a UI history pane is a read, not the side-effecting session-open verb. |
| A4 Organization owner without a share to another human’s private thread | No messages, transcript/history or user-chosen title. May read compaction count as narrowly scoped agent-activity metadata under existing administrative authority, without its summary/content. | No context clear. Authorized administrative run-stop activity remains separate. |
| A5 Agent/model output or unverified identity | Only existing scoped agent reads | Cannot issue human session-create/clear writes. No new agent grant. |
Titles/names are user content, so they follow private-message access. A compaction
count is agent activity, not message content. For A4 provide a separately scoped
`session.activity` read with opaque session/run IDs and count/status only, never names,
user identity text, compaction summaries or transcript links. This aligns with F13’s
owner-visible decisions, inbox entries, claims, tasks and project files. Ordinary
history/count views still require thread read access. Admin activity access does not
open the private thread or grant clear/send. T5 tests both projections independently.
Revocation, expiry or unshare invalidates the next read, stream poll and write. A queued
clear/new-session launch rechecks the initiating human’s write grant before each effect.
No `user` field chosen by the client substitutes for verified identity. Until row 193
lands, the legacy single human may use its own threads only; collaborator/shared paths
remain disabled. Tester writes are not implicitly granted and use fixtures only.
**D5 Proposed surface.** Session chooser under the current thread shows name, agent,
harness, running/idle/held/clearing/retired/uncertain status and `Compactions: N` (or
`unknown`, with reason). “New session” opens blank context for the thread’s existing agent.
“Clear context” names the selected session in one confirmation: ends that session,
keeps its history/project files, starts fresh context, and may wait for safe stop/capacity.
Read-only viewers see disabled write actions with the reason. Refresh/deep links preserve
thread/session selection. Old history remains readable under the same current grants.
Proposed broker verbs: `session.list`, `session.get`, `session.create`, `session.open`,
`session.send`, `session.clear`, `session.operation`. Proposed CLI: `mosaic session
list|show|create|open|clear` with thread/session identifiers, JSON output and operation ID.
Thread APIs gain an explicit optional session selector; omission uses D3’s default.
The Console routes these through its authenticated human writer with exact Origin,
Fetch Metadata/JSON limits, strict keys and current RBAC. No new listener or direct PID,
filesystem path or native harness command from a browser. CLI uses the same verified
human identity transport. Retries query the recorded operation, never resend blindly.
## 4. Compaction count on both harnesses
**D6 Meaning (Q1 ruled by Mos).** Count completed compactions over the lifetime of the logical session,
across its runs and native branches. Starts, failed/aborted compactions, branch summaries,
stream fragments and repeated reads do not increment it. Idle/restart leaves it alone.
New independent session and clear successor start at zero. The retired session retains
its count. Count is a server projection, never the number of visible markers on a page.
A host collector normalizes each completed native event to session/native ID, stable
event ID, harness/version, source position/digest and completion time. Append once using
a unique `(session, native stream identity, event ID)` key. Durable input is authoritative;
a live stream is only a refresh hint, since F7’s stream IDs cannot establish the history
seam. Do not count both the compaction entry and its rendered summary as two events.
Rebuild count from recorded events and validated source cursors. Partial trailing records
wait for completion. Truncation, unsupported format or an unreadable source produces
`unknown`/a lower bound, never a fabricated zero, and never restarts the agent.
| Harness | Proposed source contract and verification |
| --- | --- |
| Pi | Read completed native compaction records from the selected session only, deduplicate by native entry ID. Explicitly resume the pinned native session, and handle its tree without counting a retained summary twice (F5/F7). |
| Claude Code | Add a pinned-version native transcript/compaction adapter. The text-output adapter and Pi-only reader (F5/F8) do not supply this contract today. Establish its native completed-compaction format and stable identity from pinned offline source/fixtures before implementation relies on it. Do not infer compaction from prose, token drops or provider errors. No invented native event name in this design. |
Collector runs in the managed host, scoped to authorized session stores, reconciles
at turn end and on resume, and publishes a timestamped count for the Console. Proposed
active-view refresh is at most every 2 seconds, with host resource bounds and pagination
independent of total history size. Known zero requires a fresh known-empty native store
or a complete validated scan. Existing stores with incomplete evidence show unknown.
Acceptance requires exact known counts for supported new Pi **and** Claude sessions.
If the Claude format cannot be established offline, report that implementation dependency
rather than ship a false counter or silently drop one harness from MVP. **MVP risk N2:**
T3 cannot pass until the Claude format is pinned offline and a new managed-store reader
works for both harnesses. The existing .pi/state reader is not that dataRoot reader (F8).
Sage/Mos must track this as a build dependency, not assume Pi marker support covers it.
## 5. Clear context: end, retain, replace
**D7 One idempotent operation.** Human write contains old session ID, expected revision,
confirmation and caller operation key. Persist `clear-requested`, fence new sends/launches
to that session and bind a deterministic successor ID before asynchronous work. A repeat
with the same payload returns the original operation. A changed payload/key conflict
refuses. Two different clears of the same revision cannot both create successors.
1. Recheck ownership/write grant and lifecycle policy under the session fence. Mark
undelivered old inputs cancelled-with-receipt, never silently replay them to the new
session. Keep old messages, results and run evidence unchanged.
2. Fence the runner’s next-turn dequeue first and request **cooperative drain to a
completed turn boundary** for exactly this session. Do not invoke the runner stop
while a harness child/tool is running: F10’s handler escalates TERM to KILL after
5 seconds. Obtain a generation-bound idle/drained acknowledgement and verify no
child remains. Keep the dequeue fence held so no child can start between that
acknowledgement and stop. **Only then** stop the idle polling runner through the
reviewed lifecycle path and collect process/namespace exit proof. If drain does
not finish, leave `clearing`, keep reservations, and do not signal the runner.
A stop/kill from an independently authorized human safety action remains separate.
Do not stop siblings or use whole-instance regenerate. Reconcile external effects
and join applicable existing stop evidence. F10’s Pi fixture controller is not a
production Claude stop path. A signal/revoked claim/dead socket is not exit proof.
3. Until stop/quiescence is proven, keep `clearing`/`uncertain`, old capacity reserved,
successor unstarted and an actionable status. No automatic force-stop, kill clear or
duplicate effect. Proposed CLI wait is 30 seconds, then reports pending with operation
ID. Timeout does not mean completed or authorize a second clear. Recovery resumes the
same operation after evidence is available and authorization remains valid.
4. After proof, append old-session `retired` and a fresh successor creation/binding in
one bus transaction. Allocate fresh native stores/IDs, scratch HOME and a new
successor workspace under its own session ID. **Clear never copies or reuses the
predecessor checkout.** Retain the old workspace at its original path with no new
writer mount, including untracked files, dirty files and unpushed commits, associated
with the retired session. It is not deleted, reset or automatically pushed. The
successor checks out only the configured approved repository revision through the
normal hostile-clone setup, never an implicit commit from that retained checkout.
Source project files and old unpushed work are preserved, but the latter are not
silently carried into fresh context. The confirmation names this distinction and
offers authorized historical workspace inspection separately. Importing retained
work requires an explicit later authorized project operation, not context clear.
No old native history, compaction summary, dialogue, old prompt, draft or pending input is copied.
Retain role/system policy and currently authorized project sources. Clear is context
replacement, not deletion of project files, credentials or evidence.
5. Request successor startup through D8. A held launch shows `fresh session created,
waiting for capacity` or the precise refusal. Activate default-session replacement
only if the old session was that default. A clear of another session cannot change
the caller’s default. The new runner can be idle with no model call until new input.
Its first model turn must carry only the new input and allowed bootstrap context.
Crash before/after retirement, allocation, spawn or completion replays journal stages,
not old prompts. Reconcile generation, native binding and recorded process identity
before retrying startup. At most one successor/run can become current. Old late outputs
remain historical. A failed launch leaves an empty successor and retryable operation,
never restores old context implicitly. Human cancel before retirement stops replacement;
after retirement it cancels startup and leaves both historical identities intact.
**D8 Admission/kill contract.** Fresh session create records metadata only. Any open,
first send, restart, idle wake or clear-successor start must pass the same shared launcher:
current human/instance authority → configured role/harness route → launch revocation,
kill switch, resource/token/account limits → admission reservation → claim/generation
recheck immediately before spawn. No session marks itself system priority or chooses
its own route. Recheck the kill while binding so a halt racing spawn cannot escape its
stop sweep. An enabled but unavailable admission service fails closed. A held request
retains its operation ID without spending or consuming a work attempt.
The landed Q198 document is a contract, not a prerequisite to build the entire manager.
Before its runtime admission slice exists, use the existing launcher/limit path (F9),
plus row 191’s reviewed kill checks when integrated. Do not introduce an enabled manager
setting that silently bypasses a missing service. Once configured, Q198’s admission and
protected-mode holds apply to all session starts through this hook. Lifecycle/kill and
RBAC candidates may be merge-chained under Sage’s gate. A clear never sets/clears the
human kill switch. If halted, a clear/new-start write refuses `processing-halted` without
changing context. The separately authorized stop remains available while halted.
## 6. Compatibility, review and acceptance
**D9 Migration.** Old thread-only stores/messages become a default legacy session through
an immutable mapping to their existing native locations, without rewriting transcripts
or run records. Before any migrated session launches, drain all possible writers to
its old per-instance workspace, prove quiescence and retain that workspace as historical
work. Provision unique workspaces for migrated sessions through approved-revision setup.
Do not map the shared old instance checkout into several legacy sessions. Report any
unpushed work left in that retained checkout to its authorized user without exposing
private transcript data. Activation waits if quiescence cannot be established. New stores use D2’s layout. Do not bind legacy stores to more than one session.
Existing thread-only clients continue through D3’s default until explicitly selecting
a session. New session selectors on cursors, streams and tools must reject mismatched
session/generation, not fall back to another session. Preserve existing non-thread role
claims; thread-scoped managed sessions use the new tuple. All broker holder/agents/end,
usage, thread routing, reply correlation, pending approvals, limits, launcher registry,
checkout/workspace and Console consumers need an audited update list in the build brief.
Unknown consumers block that build’s acceptance, rather than silently using thread IDs.
Schema rollback needs a version refusal once multi-session state exists. Keep a verified
pre-migration backup and an activation/rollback plan before any live re-pin. Never make
an old binary resume a session from the wrong store. This design makes no live change.
| Ref | Required acceptance evidence (future fixtures on Sage’s grant) |
| --- | --- |
| T1 | Pi and Claude each run two sessions for the same agent in one thread with distinct sentinel histories/native IDs. Stop/restart one resumes only itself. Non-THREAD_DEFINITION roles refuse thread-session creation/launch. Cross-thread and cross-organization sentinels never appear. |
| T2 | Two concurrent dispatchers claim the same session: one holder. Different sessions can run subject to aggregate limits. Approval/delivery/cursor replay from a sibling or retired generation refuses. Workspace/native-store symlink or path escape refuses. Mutant: map two session IDs to the same writable checkout (within one thread and across threads), and prove the single-writer fence prevents setup while another run can write. Nesting mutant: place a live session below a retained legacy workspace or a legacy project named sessions, then attempt its historical inspection/mount; reject the overlapping layout. |
| T3 | Both harness compaction fixtures: zero, one, three, duplicate history/live hints, failed start, partial write, branches, resume and clear. Full lifetime count is stable across pagination/restart, old count remains, successor zero, unsupported legacy count unknown. Pin Claude’s source contract before claiming this test proves native compatibility. |
| T4 | Clear busy and idle sessions, two concurrent clears, delayed stop, ambiguous remote write, late output and every journal crash boundary. No replacement starts before proof; one successor; sibling session untouched; old input never replayed. A busy child ignores drain: no runner signal or forced kill, operation remains clearing. Idle acknowledgement racing new dequeue is fenced. Clear preserves dirty/untracked/unpushed old workspace bytes and starts from an independent approved checkout. Held startup remains visible and first new turn contains no old sentinel. |
| T5 | Owner/collaborator/viewer/shared-owner/private-owner matrix, expired/revoked grants before read and after clear acceptance, forged identity and cross-instance IDs. Private messages/history/titles never leak without a share. A4’s separately authorized activity projection exposes count/opaque IDs only, without summaries or transcript access. Clear/open/send require current owner write grant at effect. |
| T6 | Fresh start/clear/restart under kill, grant revocation, limits and Q198 hold; halt between reservation/spawn/bind; manager configured but unavailable. No hidden launch, model call, route choice or capacity release from an unproven stop. |
| T7 | Legacy thread clients/default migration, old claim semantics for non-thread roles, exact native store binding, schema rollback refusal and no rewritten evidence. Console selection/clear confirmation/status, disabled viewer writes and count refresh work for both harnesses. |
Named review: new bus schema and public session selectors/verbs, claim key changes,
RBAC/activity projections, explicit per-session workspace layout and single-writer setup,
clear-workspace retention, idle-only runner stop, harness store/binding/counter contracts,
stop evidence, launcher admission hook, approval/delivery correlation, migration/rollback and CLI/Console writes. Add
mutants for shared thread store, omitted session filter, double compaction increment,
clear-before-stop-proof, copied old prompt, forged human, missing kill check and duplicate
successor. No tests/builds run for this design assignment.
## 7. Proposed PRD 1.13 text (Ludwig owns IDs and final wording)
**REQ-ROLE-2 replacement**, preserving its existing revoke/assistant protections:
> Each role instance has one holder at a time outside thread-scoped sessions. Within
> a thread, its configured THREAD_DEFINITION agent may have several independent sessions, each
> with at most one holder. Claims bind organization, thread, agent instance and session
> identity. Release/end frees only that holder. Aggregate authority, limits and the
> existing assistant end/revoke protections still apply. Creating or clearing a session
> grants no role authority and transfers no pending approval to another session.
Retain the current requirement’s remaining chief-of-staff and human-resolved revoke
clauses verbatim. This changes holder granularity, not who may end/revoke the assistant.
**REQ-THREAD-2 replacement:**
> The user creates projects and named threads from the CLI or Console. A thread may
> contain several independent sessions for its configured THREAD_DEFINITION agent, on
> Pi or Claude Code. Other role definitions are not admitted to thread sessions.
> Messages, native context and compaction counts belong to the selected session.
> Returning after idle stop or restart resumes that session, never a sibling. Thread-only
> clients use an explicit persisted default. History is retained and isolation holds
> across sessions, threads and organizations under REQ-USER-2, REQ-USER-3 and REQ-USER-4.
Proposed new requirement subjects, **IDs reserved by Ludwig**, not asserted existing:
completed-compaction count per session, context-clear retirement/successor operation,
and admission/kill/authorization parity for every start. D4–D8 and T1–T7 define their
acceptance. No edit to `docs/prd/mosaic-stack.md` is made in this design branch.
## 8. Mos’s rulings (mos-1235, 2026-10-21)
These are **Mos’s readings** of Jason’s lines and the existing record, not additional
verbatim rulings by Jason. They do not go back to Jason as questions. Ludwig reports
them in the PRD 1.13 change list after landing.
- **Q1 Lifetime count: yes.** TARGET.md:104 asks for “the number of compactions that
have occurred for a session”. Count lifetime completed compactions for the selected
session, across native branches. Under :105 a clear successor is a new session and
starts at zero. D6 retains this meaning.
- **Q2 Proven safe stop: yes.** Clear waits for proof and shows pending status. It adds
no force-stop authority. The human kill switch remains separate, following Q198 D1
and D13. D7/D8 retain those boundaries.
- **Q3 Owner access to another user’s context: no.** PRD 1.12 at `1509c7cc5`,
`docs/prd/mosaic-stack.md:1048` says “A user's messages stay private from the owner.”
The organization owner cannot clear another user’s session without that user’s write
authority. D4’s read-only-share and private-thread restrictions remain.
## Verification and handoff
Read pinned code, row 194 r4 and the explicitly named PRD 1.12 candidate. The old
compaction pointers were rechecked against the fetched tree, including the app.js line
shift. Source citations and design consistency are checked without running builds,
suites, a model or a live stack action. Queue/PRD ownership stays with Sage/Ludwig.
Scrooge reviews this design, then Sage assigns the MVP row and lands it, and Ludwig
assigns PRD 1.13 IDs. MVP priority is ahead of Q198 S1, with no live re-pin implied.