23 KiB
Row 219 / C2-09a: one thread per creative instance
Assignment sage-2793, base aca16404c; branch rocko/row219, own worktree /mnt/storage/scratch/rocko-r219. Claim waits for Sage's gap. No Node, tests, HTTPS git or push while Gander's row253 gate holds the slot.
Read both C2-09a and C2-09b briefs at aca16404c and 51cc0445c: the two
sections are byte-identical. The newer brief changes C2-06's reply limits
under Q222, not C2-09a. This row introduces no M5 limit, writer or setting.
Row265 rooms chains on this row and stays separate.
Implementation plan
Broker: replace assistant-only #threaded with THREAD_DEFINITIONS membership. thread.create gains optional instance, validates it as a declared thread instance, and binds both the thread and default session to it. Omitted instance retains single-instance fallback and ambiguous/missing refusals. User grants must still cover the selected instance and project before project lookup; an explicit selector cannot bypass FED R3. Existing tester ownership and per-thread/per-session holder checks remain.
Launcher: import shared THREAD_DEFINITIONS and replace its two assistant checks (check and ending), preserving launch admission, quotas, session isolation and stop policy. No runtime.mjs, bundle or library adapter change; Della row224 was notified of these narrow launcher hunks.
Console: actual shipped new-thread UI is in public/chat.js, with transport mapping in chat.mjs and HTTP validation in chat-http.mjs, not public/bus.js. These three files need Sage's scope addition before their edits. Proposed metadata read GET /api/chat/instances in serve.mjs uses the existing bus.instances read, filters using shared THREAD_DEFINITIONS, and returns only {instance,name}, with vars['persona.name'] or instance as the label. It adds no channel operation or bus verb; send still traverses createChat and the existing channel dispatch. The new select sends optional instance through chat-http validation and chat.mjs. It is disabled when metadata cannot be read, so the UI never silently chooses between agents.
Acceptance evidence to build (runs await CLEAR)
Bus: explicit creative selection binds the requested thread and default session; omitted selector preserves assistant compatibility, missing and ambiguous cases. Unknown/non-thread/malformed selectors refuse without new threads; user grants cover only the selected instance, with prior non-disclosure order intact. Real creative role definition messaging still holds. A creative thread claims/receives independently of its peer.
CLI: real fixture launcher starts a creative thread on pending input and keeps peer thread/session stores separate. Direct non-thread launch of a creative instance refuses thread-required. Existing assistant tests remain.
WebUI: metadata lists thread definitions only with persona/name labels; selection survives refresh and reaches thread.create exactly. Malformed instance fails before a write, old omitted instance still works. Browser asserts two creative options, inert hostile labels and read-only disablement. Keep all identity/origin/content/SSO fences. Named mutants cover each new acceptance guard; no runs until Sage's announced gap/CLEAR.
Before review: grep source readers/hash pins, update only pins required by owned changes, rebase onto row253 landing under a new branch, then rerun touched files on the new tree. No schema, role-policy, live or canonical product-path change. Handoff directly to Dewey, Mos and Sage when ready.
Scope ruling and picker design before UI edits
Sage-2807 adds public/chat.js, chat.mjs and chat-http.mjs because the shipped form is chat.js:55/235, its forwarding is chat.mjs:23, and POST validation is chat-http.mjs:80-82. bus.js stays byte-identical. The new route sits after existing auth/session checks and uses startServer's own bus, so the tester socket's separately supplied testerBus is used too (Dewey U1). No new bus or channel operation. The route projects only instance/name and keeps the THREAD_DEFINITIONS filter server-side, rather than making the browser read all /api/bus/instances vars (Dewey route note).
Dewey-0849 U2-U5: multiple choices start with a required placeholder; exactly one starts chosen and is sent explicitly; none disables Create and says no thread instances are configured. Failed metadata reads disable Create with "Couldn't read the thread instances; reload to try again" and recover on a good read. Labels show persona name plus instance key when different. Picks live in form(key); a removed pick is cleared with a status and never moved to another option, even if only one remains. Repaints retain selection. U6 is deferred: thread-list/header still show their existing instance keys. The shared sign-out/redirect handling and strict HTTP write key validation remain in force. Add unauthenticated metadata and selected-instance user grant refusal tests as Sage requires.
Existing fixture adaptations (unrun)
C2-08 creative.test's setup previously bound creative roles without threads and sent human input with message.send. This row makes those roles threaded: setup now selects assistant explicitly, creates each creative instance's thread and binds its claim there; the human uses thread.send. Existing M6/messaging refusal and count assertions stay in place. The user-principal fixture gains optional extra threadRoles for the selected-grant regression.
The browser fixture now answers /api/chat/instances with its one assistant. Its existing create receipt assertion gains instance:'assistant', since the new picker explicitly sends its single preselected choice. No existing assertion is dropped. New tests cover multiple/empty/failed metadata, duplicate hostile labels, selected-instance POST, refresh and disappearing choices. No Node or test has been run under Gander's hold.
The existing launcher.test C2-08 persona-mismatch regression cannot keep
requesting a standalone creative launch: C2-09a now correctly refuses it
thread-required before bundle construction. Its trigger is therefore the
thread pass, with an injected host threadsState snapshot (the persona
mismatch occurs before any bind). The exact mismatch reason, no persona
content leak, one refusal and no running session assertions remain. The
old per-run ['session'] directory assertion changes to [] and gains an
assertion for the thread-owned session directory, matching row121's actual
thread-store layout. A new e.thread assertion pins the path. This is a
fixture/expected-layout adaptation, not a product exception for that test.
Old-test approval: mos-1316
Mos approved the three adaptations in OLD-TEST-CHANGES.md (sha256 9a1e51e6b43040593a3dd517c4a0c71f5ac42b6b57d66d474cd0517f06e97ed6) and old-persona-test.diff (sha256 6aaca9820b692ec659058e9b044f7f60872cdecb16fe3ac1321c2c0ed530701d). The source commit must name mos-1316 and carry OLD-TEST-CHANGES.md. Dewey checks each changed line against that record.
Keep the new thread-launch test's fromSession(chief.cap, 'bean') refusal (thread-required), and the threads test's direct human message.send refusal for each creative definition (thread-required-use-thread-send). The former is sandbox-dependent: its gate record must show it ran without a skip; otherwise report to Mos rather than claiming the pin. T06 restores the old assistant-only launcher check; T22 restores the ending check separately. The persona mismatch fixture wraps only threadsState; all other host ops remain real. Under mos-1272, a first-run red in launcher.test.mjs, creative.test.mjs or chat-browser.test.mjs goes to Mos before any fix. No run has occurred as of this approval record.
mos-1317: always-running standalone admission pin
Added a separate new test next to the assistant standalone refusal:
C2-09a: fromSession refuses a creative instance outside a thread without a sandbox.
It has no sandbox skip. The real fixture host binds/claims the chief, and
fromSession must refuse Bean with thread-required before bundle/sandbox
construction. The existing sandbox-dependent pin remains unchanged.
T23 restores both launcher assistant-only comparisons and targets this new
exact refusal assertion. T06 and T22 remain as separate launch/ending checks:
23 mutants total. No tests run; slot scope amendment sent to Sage.
Keep the Mos-approved threadsState wrap as the only persona-test host override.
Inspection candidate under sage-3113 (2026-10-23)
Explicitly UNVERIFIED. Sage authorized a local inspection commit before
runs; no claim of review readiness or green tests. Base remains aca16404c,
branch rocko/row219. No rebase has been performed. No Node, browser, test,
mutant or suite has run; the earlier gate holds and subsequent row219 hold
were honored. Static Python exact-once preparation named 23 mutant sites;
git diff --check passes. The mutant execution runner is not yet written.
14 source/test paths: six product files and eight whole test files. The candidate manifest excludes this packet. The new no-sandbox fromSession Bean test and T23 record mos-1317; old test adaptations stay governed by mos-1316 and OLD-TEST-CHANGES.md. First-run reds in launcher, creative and chat-browser must go to Mos before any fix. Run evidence must prove the sandbox-dependent pin ran, or report its skip to Mos.
Remaining: Sage-directed rebase to current landing base/new branch; slot CLEAR and claim; eight whole test files and 23 mutants with process-group cleanup; path/hash-reader sweep, acceptance evidence and final review packet. No product behavior is verified. Push waits for Sage's named gap; reviewers and dependent rows may inspect this commit but must not treat it as approved.
Rebase under sage-3127 / exact resolution sage-3128
Rebased the unverified c4b4fab98 inspection candidate from aca16404c onto
0626464874. The only conflict was broker.mjs's
thread.create user guard: row206 added verb-sensitive #granted(s, verb,
project, instance). Sage-3128 supplied the exact resolution: retain the
selected-instance validation and call #granted(s, 'thread.create',
identifier(a.project), instance). No guessed conflict resolution. The merged
broker has no remaining three-argument #granted(s, ...) call (static balanced
argument scan). T05 now matches that four-argument call and substitutes null
only for instance; all 23 mutant old anchors, including T23's second edit,
remain exact-once. Rebuild manifest/base/patch on this base. Other auto-merges
were user-principal.test, launcher and thread-launch.test. No tests, Node,
mutants or reader audit run: CLEAR still required after 574, covering every
touched test file whole. This branch remains UNVERIFIED.
Full gate preparation: sage-3174
Clean rebase onto 4a9c536e86, after rows270+271.
No conflicts or manual product changes. All 23 anchors remain exact-once,
including T05 and T23's second edit. All 14 candidate hashes rebuilt.
Before first run: eight files whole, then bus/cli/webui whole, then all ten scripts/test-.sh, then 23 mutants, then reader audit with positive control. Singles timeout 300s; suites 1800s; mutants 180s, each in its own process group, TERM then KILL after 10s and restore in finally. Every stage gets a fresh short TMPDIR under /mnt/storage/scratch/tmp/r. DOCKER_HOST is dead for Node runs; shell fixtures may use Docker, with project rocko-r219-gate and owned network cleanup in finally. Live provider cases are not enabled.
Each of the ten shell files uses timeout -k 10 3600, comfortably above 3x
the longest entire earlier observed builder gate (roughly 25min -> 75min
would exceed 3600; use 7200 seconds instead below). To avoid relying on
old skip-fast samples, the actual shell command is timeout -k 10 7200,
more than 3x that 25-minute conservative baseline for any individual shell.
No shell run silently retries. Log each skip verbatim. Initial timings are
in historical queue114/r1/out/full/gate-results.json (old task run skipped
live cases, so not used as the Docker worst-case estimate).
Mos1316/1317 first-run launcher/creative/chat-browser reds, any old-test red or a second red stop before fixes and go to Sage/Mos. No run evidence yet.
First red and approved test-only correction: mos-1408 / sage-3178-3179
Run c7bf3622d stopped at launcher.test's row213 persona-mismatch assertion:
04:07:22.895-04:07:51.870Z, creative 4/0/0, threads 19/0/0,
user-principal 23/0/0, launcher 33/1/0: total 79 pass, 1 fail, 0 skip.
The approved threadsState snapshot had no session; row269's session-required
admission fired before bundle/persona reading. Original logs remain in
run-4a9c/ and derived-counts-first-stop.json reads their default spec output.
No retry or fix occurred before Mos's ruling. Slot returned after empty
Node/Chromium cwd sweep and all 14 source hashes checked.
Mos-1408 permits only an explicit SESSION in that snapshot and literal-path assertions: the native threads/acme//sessions//session exists, and the legacy threads/acme//session does not. No sessionStore() call in the assertion: it creates directories and could manufacture the evidence. Every other assertion stays exactly as before; no second host op is wrapped. No product change. Runner explicitly selects --test-reporter=tap (packet-only) and uses new run-4a9c-mos1408/ output, preserving the failed first attempt. The next CLEAR reruns from the beginning: whole files, suites, shells, all 23 mutants, reader audit. Any red or second edit must return to Sage/Mos.
Sage-3179: commit/push during the current gap; hold re-claim until our own slot, after 292 then 294. No tests or queue writes under another seat's slot.
Restart scope: sage-3224
Run HEAD b97a3ff97, source/test manifest a973912f, unchanged. Start every
stage from the beginning; no prior passing test carry. Sage-3224 explicitly
requires timeout -k 10 per stage, so the packet driver now wraps each Node
stage in that command too (shell stages already had it); the existing process
group timeout/cleanup remains a second bound. No source or test edit.
Singles 300s, suites 1800s, shells 7200s, mutants 180s, TERM-to-KILL 10s.
Fresh short stage TMPDIR. Explicit TAP. Separate run-4a9c-mos1408 output.
Second old-test edit: mos-1418 / sage-3232 (no restart yet)
The b97a restart at 05:48:57.418-05:49:26.296Z stopped at row213 again: creative4/0/0, threads19/0/0, user-principal23/0/0, launcher33/1/0. Original TAP is run-4a9c-mos1408/single-cli-launcher.test.tap. Row270 now records compactions before the persona refusal: captured tuple was ['compactions',undefined,2], not the full compactions object. Static inference of count0/known true/reason null was explicitly identified as inference. No edit or rerun occurred before Mos's approval; slot returned after empty cwd sweep and 14-hash check. Remaining stages unrun.
Mos-1418 permits this exact second edit: move run-directory lookup above the pin, require exactly two rows, deepEqual row0 minus at to event compactions, instance bean, thread, SESSION, run runs[0], count0, known true, reason null; then take e from row1 and require refused/launch-failed. Later e.thread, e.why, content nonleak, no sessions, one run, empty run directory and native/ legacy store assertions stay unchanged. Only the specified comment changes. No product bytes change. If inference is wrong, report red, no third edit. Dewey must inspect this test diff before the next full restart. Local commit only while294 holds; push waits for Sage's named gap. No runs after this edit.
Third edit and new manifest round r2: mos-1420 / sage-3243
Full restart on7cbd839d0 began06:09:43.706Z and stopped06:10:30.695Z: creative4/0/0, threads19/0/0, user-principal23/0/0, launcher34/0/0, thread-launch13/1/0, total93 pass/1 fail/0 skip. Persona's exact two-row pin passed. The new creative-history test failed ENOENT on its obsolete legacy history path, after its real send/reply checks. Always-running Bean refusal passed; sandbox-dependent Bean assertion followed the failed read and was not reached. No coverage claim for that assertion. Slot returned after empty cwd sweep and14 hashes checked. Original earlier red output was archived byte-identically before this restart; all later stages unrun.
Mos-1420 authorizes exactly the two history-path corrections in that new test: obtain each default session from the real runtime threadsState and read the literal threads/acme/T/sessions//session/history path. Contents remain exactly Bean input\nBean again\n and Chet input\n. Add one literal legacy-path nonexistence assertion per thread, no mkdir helper. Every other file line stays unchanged. No product change. The new r2/ manifest/patch snapshot is this third-edit round; root manifest is refreshed to the same digest for the next claimant/review handoff. Local commit only; Dewey checks mos1420 items1-3 before push/restart, and Sage names a gap/CLEAR after294 round4. No runs after this edit. Any further red, including later lines in this test, returns to Mos through Sage.
Rebase round r3 after row294: sage-3250 / sage-3254
Rebased five commits from4a9c536e8..5f2ef92e5 onto
80793d824e, new branch
rocko/row219-on-80793d824. No conflicts and no manual product edits.
Row294's shared chat-http status refusals, chat owner-only channel-settings
transport, and serve's user rebinding/route fencing/static federation assets
remain. Row219 still forwards the selected instance over the bound caller;
its metadata route follows the listener/session bus after row294 rebinding.
r3/range-diff.txt records all five pairs: four are '='; the first is '!' only because createChat's surrounding signature now includes owner=null. No hunk body changed. Per-path patch IDs and row294 carry delta IDs are in r3/path-patch-ids.json and r3/294-carry-patch-ids.json; conflict list is empty. r3/overlap-readers.json lists exact source readers and whole tests via their test-helper import closure, refreshed on this base. Root and r3 manifest, base and build.patch are refreshed. Old r2 packet is historical and unchanged.
Dewey's checked mos1418 and mos1420 test edits stand; this handoff requests rebase-only static review. No tests, Node, mutants, reader gate audit or push performed while preparing this local rebase. Full no-carry restart waits for Sage's CLEAR. Any new red returns to Mos through Sage before fixes.
Round r4: mos-1429 / sage-3291 old-test corrections, no runs yet
bfa421 restart began08:08:37.137Z; eight whole files137/0/0, then bus 873/2/1 stopped08:10:07.389Z. Old failures: creative ops bound without a thread in grant-executor's sage1908 test; project-runtime exact import pin still singular THREAD_DEFINITION. Skip X-G3: no Docker/local Gitea image, never pulls (Node stages used a dead Docker socket). No later stages ran. Both Bean pins ran in the green thread-launch14/14; persona pin green34/34. Returned slot with empty cwd sweep and14 hashes intact. No edit/retry before Mos1429 approved the old-test changes. Original logs remain recorded.
Only test changes: create a real project/thread on the restarted broker, bind creative ops with it, preserve the host.run/refusal/request-count/sudo/ record and restart lines byte-for-byte. Exact import pin singular->plural; add one row219 comment, preserve all doesNotMatch checks. No product edit. r4/assertion-preservation.json stores old/new text and preserved exact lines.
No pre-existing bus test bound a creative role without a thread: condition6 requires the new test in threads.test, covering all six creative definitions. T01 retargets the old assistant-only #threaded mutant to this direct broker pin; T24 drops only #hostAccess's creative guard and must fail the corrected sage1908 assertion with ERR_ASSERTION. 24 mutants total;16 source/test paths, 10 whole changed test files. Source paths are the previous14 plus the two old test files. New manifest round r4 and root snapshots match.
Short slot plan: focused red sage1908 + exact import pin on detached bfa421, then three whole green files (grant-executor, project-runtime, threads), then T24 on fixed bytes (ERR_ASSERTION required), restore/hash/sweep and push only after authorized. Estimate3-5min. No tests/mutants/Node/push until Sage CLEAR. Dewey delta review follows; later full no-carry restart includes all10 changed files, bus/cli/webui, all10 shells, all24 mutants and reader control/audit. Further old-test red stops and goes to Mos through Sage.
Full restart r6, sage-3345 / mos-1439
Merge 054da642f9, parents 2efd127ce6 and b899095e4.
Tree e86a84a852 matches Sage before any run.
No conflicts or manual product/test edits. Same16 paths, new manifest
4a2271ddbd4212324f39e608c3a35a4ae834c045cb0d13a619715017ded0ffef.
Fresh worktree /mnt/storage/scratch/rocko-r219-g3345, node_modules linked immediately.
Runner uses mktemp -d /mnt/storage/scratch/tmp/rXXXXXX and validates
[A-Za-z0-9/.-] for each stage; no previous results carry.
10 whole singles; bus,cli,webui,harness suites; all10 shell scripts
including test-task with Docker;24 mutants;reader audit.
Timeout -k10: singles300s,suites1800s,shells7200s,mutants180s;
7200s exceeds3x the prior conservative25min shell baseline.
Every child has a process group; any red stops, no retry/edit.
Finally remove owned networks including rocko-r219-g3345_default,
sweep, preserve packet evidence, remove node_modules link and this worktree.
Post-295 gate result
Completed gate, sage-3345
Full run 2026-10-23 10:12:57Z-10:29:22Z on merge054da642f9. Ten singles183/0/0; bus889/0/1; cli927/0/0; webui373/0/1; harness151/0/0. Node total2523pass/0fail/2skip,0cancelled. All10 shell files green,449pass/0fail.24 assertion kills,0timeout kills, 0survivors,0invalid. T15 finished in66.9s with ERR_ASSERTION on the missing 'no longer available' status; T24 got decision-required instead of host-creative-role (same exact later-fence mismatch as r4). Both Bean pins and the sandbox-dependent native-history test ran, no skip.
Skips: X-G3 scratch Gitea1.27.1 unavailable (Node stage uses deadDocker); WebUI rebuild needs esbuild0.28.2 but host has0.28.1; queue verify/render requires canonical checkout; test-task live provider cases intentionally skipped twice (row244, no provider call). GATE-RESULTS.json quotes all5 skip lines, including the duplicated live-provider line.
Reader audit: all16 changed paths plus unchanged public/bus.js,237 reader hits and22 64-hex lines. None of those pins freezes a changed file. Positive control channel-proof.test.mjs webui bus.mjs pin matches actual bytes; public/bus.js stays unchanged. Full audit in reader-audit.json.
16 candidate hashes restored. Driver cwd node/chromium sweep empty. Owned rocko-r219-gate_default removed; worktree-basename network rocko-r219-g3345_default already absent (rm attempted as instructed). No retries, unexpected reds or guard interventions in this run. Results from prior environmental failures were not carried.
Historical environmental failures remain in run-0780-mos1429/ (harness underscore TMPDIR) and run-0780-mos1432/ (Docker address pool exhaustion). Mos1432 required alphanumeric paths; Mos1437/Mos1439 and sage3339/3345 resolved the network issue outside this candidate. No product/test fix for either. Tests and source remain byte-identical to the checked merge.