From 200dd396c442529bb8091ed59afdca9309f83942 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Fri, 23 Oct 2026 23:37:51 -0500 Subject: [PATCH] feat(bus): add human project rooms with addressed sends (cherry picked from commit ef4c93853209b88aad53aa25677d5e69fd188070) --- BUILD-LOG.md | 6 + agents/goldie/work/queue-265/BUILD.md | 134 ++++++++++ agents/goldie/work/queue-265/MANIFEST.sha256 | 51 ++++ .../work/queue-265/logs/01-address.log.gz | Bin 0 -> 434 bytes .../work/queue-265/logs/02-rooms.log.gz | Bin 0 -> 1211 bytes .../goldie/work/queue-265/logs/03-bus.log.gz | Bin 0 -> 32317 bytes .../goldie/work/queue-265/logs/M01-human.diff | 10 + .../work/queue-265/logs/M01-human.log.gz | Bin 0 -> 1963 bytes .../work/queue-265/logs/M02-tester.diff | 12 + .../work/queue-265/logs/M02-tester.log.gz | Bin 0 -> 1716 bytes .../work/queue-265/logs/M03-project.diff | 10 + .../work/queue-265/logs/M03-project.log.gz | Bin 0 -> 1909 bytes .../work/queue-265/logs/M04-members.diff | 10 + .../work/queue-265/logs/M04-members.log.gz | Bin 0 -> 1672 bytes .../work/queue-265/logs/M05-collision.diff | 11 + .../work/queue-265/logs/M05-collision.log.gz | Bin 0 -> 1778 bytes .../goldie/work/queue-265/logs/M06-open.diff | 10 + .../work/queue-265/logs/M06-open.log.gz | Bin 0 -> 1864 bytes .../goldie/work/queue-265/logs/M07-body.diff | 10 + .../work/queue-265/logs/M07-body.log.gz | Bin 0 -> 1683 bytes .../work/queue-265/logs/M08-unknown.diff | 10 + .../work/queue-265/logs/M08-unknown.log.gz | Bin 0 -> 1708 bytes .../work/queue-265/logs/M09-ambiguous.diff | 10 + .../work/queue-265/logs/M09-ambiguous.log.gz | Bin 0 -> 1679 bytes .../work/queue-265/logs/M10-messaging.diff | 10 + .../work/queue-265/logs/M10-messaging.log.gz | Bin 0 -> 1693 bytes .../work/queue-265/logs/M11-cursor.diff | 11 + .../work/queue-265/logs/M11-cursor.log.gz | Bin 0 -> 1683 bytes .../goldie/work/queue-265/logs/M12-fence.diff | 10 + .../work/queue-265/logs/M12-fence.log.gz | Bin 0 -> 1678 bytes .../queue-265/logs/rerun-00-sandbox.log.gz | Bin 0 -> 935 bytes .../queue-265/logs/rerun-01-address.log.gz | Bin 0 -> 603 bytes .../work/queue-265/logs/rerun-02-rooms.log.gz | Bin 0 -> 1213 bytes .../work/queue-265/logs/rerun-03-bus.log.gz | Bin 0 -> 47299 bytes .../logs/rerun-04-mutants-driver.log.gz | Bin 0 -> 270 bytes .../logs/rerun-05-restored-address.log.gz | Bin 0 -> 606 bytes .../logs/rerun-05-restored-rooms.log.gz | Bin 0 -> 1217 bytes agents/goldie/work/queue-265/mutants.py | 67 +++++ .../work/queue-265/pin-context-grep.txt | 1 + .../queue-265/pin-context-with-sandbox.txt | 1 + .../work/queue-265/pin-positive-control.txt | 6 + agents/goldie/work/queue-265/reader-grep.txt | 133 ++++++++++ docs/SESSIONS.md | 2 + packages/bus/README.md | 3 + packages/bus/src/address.mjs | 14 + packages/bus/src/broker.mjs | 94 +++++++ packages/bus/src/index.mjs | 1 + packages/bus/tests/address-cases.mjs | 16 ++ packages/bus/tests/address.test.mjs | 17 ++ packages/bus/tests/project-runtime.test.mjs | 2 + packages/bus/tests/rooms.test.mjs | 247 ++++++++++++++++++ packages/seat/src/sandbox.mjs | 1 + 52 files changed, 920 insertions(+) create mode 100644 agents/goldie/work/queue-265/BUILD.md create mode 100644 agents/goldie/work/queue-265/MANIFEST.sha256 create mode 100644 agents/goldie/work/queue-265/logs/01-address.log.gz create mode 100644 agents/goldie/work/queue-265/logs/02-rooms.log.gz create mode 100644 agents/goldie/work/queue-265/logs/03-bus.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M01-human.diff create mode 100644 agents/goldie/work/queue-265/logs/M01-human.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M02-tester.diff create mode 100644 agents/goldie/work/queue-265/logs/M02-tester.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M03-project.diff create mode 100644 agents/goldie/work/queue-265/logs/M03-project.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M04-members.diff create mode 100644 agents/goldie/work/queue-265/logs/M04-members.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M05-collision.diff create mode 100644 agents/goldie/work/queue-265/logs/M05-collision.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M06-open.diff create mode 100644 agents/goldie/work/queue-265/logs/M06-open.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M07-body.diff create mode 100644 agents/goldie/work/queue-265/logs/M07-body.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M08-unknown.diff create mode 100644 agents/goldie/work/queue-265/logs/M08-unknown.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M09-ambiguous.diff create mode 100644 agents/goldie/work/queue-265/logs/M09-ambiguous.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M10-messaging.diff create mode 100644 agents/goldie/work/queue-265/logs/M10-messaging.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M11-cursor.diff create mode 100644 agents/goldie/work/queue-265/logs/M11-cursor.log.gz create mode 100644 agents/goldie/work/queue-265/logs/M12-fence.diff create mode 100644 agents/goldie/work/queue-265/logs/M12-fence.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-00-sandbox.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-01-address.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-02-rooms.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-03-bus.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-04-mutants-driver.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-05-restored-address.log.gz create mode 100644 agents/goldie/work/queue-265/logs/rerun-05-restored-rooms.log.gz create mode 100644 agents/goldie/work/queue-265/mutants.py create mode 100644 agents/goldie/work/queue-265/pin-context-grep.txt create mode 100644 agents/goldie/work/queue-265/pin-context-with-sandbox.txt create mode 100644 agents/goldie/work/queue-265/pin-positive-control.txt create mode 100644 agents/goldie/work/queue-265/reader-grep.txt create mode 100644 packages/bus/src/address.mjs create mode 100644 packages/bus/tests/address-cases.mjs create mode 100644 packages/bus/tests/address.test.mjs create mode 100644 packages/bus/tests/rooms.test.mjs diff --git a/BUILD-LOG.md b/BUILD-LOG.md index ab642b9b4..d1378aa56 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -5469,3 +5469,9 @@ bus bypass refusals. Prior old-test draft regression fixed under sage-3918; missing root oauth4webapi corrected by pinned npm ci under sage-3924. Evidence: agents/poe/work/queue-208/BUILD.md. Independent reviews and Sage's global gate remain; no live state, schema or bus policy change. + +2026-10-24 | Goldie | Row265 / #1770 before, recorded during authorized verification | C2-09b has no project room verbs. On goldie/row265 at ec86f2c84, add only room.open/send/read, pure exported leading-tag parser, README verb rows and new bus tests. Sage-3921 fixes EOF-tag and message-only timestamp readings; tester list/helpers/schema stay unchanged. Claim rev3814; Sage-3932 CLEAR for serialized new files, whole bus and twelve refusal mutants. No old-test edits authorized; stop rules apply. + +2026-10-24 | Goldie | Row265 / #1770 first slot STOP (sage-3932) | New parser14/14, rooms18/18 green; serialized bus stops at old project-runtime.test.mjs:14 import-closure pin, partial619 ok/1 not ok. New pure address.mjs import is absent from expected imports. Static trace also needs address.mjs in seat RUNNER_FILES. No old-test/product correction, no mutant/restored run, no green commit/push; old-pin and out-of-owned-files mount change sent to Sage for ruling. Audit prose missed the direct source pin despite raw grep hit; correction recorded in BUILD.md. + +2026-10-24 | Goldie | Row265 / #1770 verified (mos-1567, sage-3942) | Approved correction adds solely address import pin + Row265 comment to project-runtime.test and one pure-source RUNNER_FILES mount; new block checks parser has no imports. Serialized fresh-short-TMP timeout-k10: unchanged sandbox10/10, parser15/15, rooms18/18, full bus957/957, twelve named refusal mutants killed (each Node1, driver0), restored parser15/15 + rooms18/18. All positives zero fail/skip/cancel; every mutation restored full broker SHA71b32ee4. Old first-red evidence retained, no other old-test change. Slot returned goldie-0034; Boyd packet explicitly includes mount-list review, candidate push next. diff --git a/agents/goldie/work/queue-265/BUILD.md b/agents/goldie/work/queue-265/BUILD.md new file mode 100644 index 000000000..1a1b1f503 --- /dev/null +++ b/agents/goldie/work/queue-265/BUILD.md @@ -0,0 +1,134 @@ +# Row 265 / #1770 — project rooms + +Current result: verified under sage-3942; slot returned in goldie-0034. Full bus 957/957, sandbox 10/10, parser 15/15, rooms 18/18, twelve mutants killed, restored files green. Review/push packet below includes mos-1567 closure scope. + +Goldie, 2026-10-24. Branch goldie/row265, base ec86f2c847f6154a0677c6ed23c87dabc2c665d0. Brief docs/plans/2026-10-20_case2-rows.md § C2-09b rooms at blob3a5ed91a4fb3462df67e6939ae6f18290ac9b453; design agents/gosalyn/work/case2/DESIGN.md §6. Sage-3915 transfers ownership from Rocko to Goldie and review from Dewey to Boyd. No old test edit authorized. All tests/mutants wait for Sage CLEAR; queued behind Poe, Bentina and Sage's326 gate. + +## Design and clarified readings + +A room is a bus project. Members are all loaded business instances whose definitions are in THREAD_DEFINITIONS, sorted by key. Canonical room threads have those keys as names and belong to the requesting human. open checks all name/instance/owner collisions before creating anything; it delegates missing inserts to existing thread.create dispatch, including default session metadata. send/read require the complete canonical set. No schema or migration change. + +Sage-3921 settles two brief readings: the single captured timestamp applies to the room.send MESSAGE rows; existing route/delivery/event helpers keep their own timestamps in the same dispatch transaction. They are unchanged. A final EOF-terminated @name is a tag, so bare @continuity is invalid-request rather than a broadcast. Leading whitespace is accepted. Pure parseAddress returns {tags,body}, where body is the unaddressed remainder; room.send stores the ORIGINAL input unchanged. Export it from the bus index and expose a separate reusable test table for C2-10c parity. + +send resolves tags against current #named results and member instance keys, deduplicates recipients, and refuses multiple member matches. It checks each target's current default-session fence and messaging rule, then inserts one normal INFO message, route and human.input per target under the existing request transaction. All message rows share one at. No tag broadcasts; tags after the first non-tag token remain plain text. + +read includes all sessions of the caller's canonical threads, globally ordered by messages.seq. Each entry retains first-message fields plus thread/session/instance and adds ids (every grouped message id) and to (each instance once). Only consecutive human rows with identical at/body/class group, and a repeated instance starts a new entry, so same-millisecond identical sends remain separate. Paging limit counts merged entries (THREAD_PAGE defaults/max); clients continue after the last ids element. Cursor must belong to a room thread. Bounded raw scan limit*memberCount+1 completes requested groups without reading unbounded history. Sage-3921 accepts these routine choices as proposed in goldie-0030. + +## Scope / steps + +1. Read current thread.create/send/messages, transaction wrapper, naming and messaging helpers; audit source readers/pins. Claim265 via queue after next. Done/read, claim recorded at rev 3814 with op goldie-0265-start-1 (same-op replay confirmed). +2. Add parser + index export, only three room cases in broker, README verb rows and new bus tests/fixtures. Do not modify existing thread/messaging/ACL/helper behavior. +3. New tests cover all brief cases, atomicity across message/route/input rows, ownership/projects, permissions, paging/grouping and session fences. No suites or test runs before CLEAR. +4. Record exact refusal→test→mutant matrix here before requesting the slot; one targeted killed mutant per named refusal, restoration byte-checks. New files whole then bus suite under CLEAR, serial timeout-k10, fresh31-byte mktemp TMPDIR plus UTC/load/busy header. +5. Before in-review, grep packages/*/tests for broker.mjs/TESTER_VERBS and changed-file pins. Push own branch and hand tip/base/manifest directly to Sage/Boyd. Sage owns request posting/landing. + +No Console/Discord/CLI room surface or cross-agent reply visibility added. No tester verb, role, schema or secret change. No host action or credential access. + +## New tests and refusal / mutant matrix + +Only new test files and a new reusable vector fixture are added. No pre-existing test changes. Parser table: address.test.mjs consumes address-cases.mjs, including final EOF tags, leading whitespace, tags after the first word, repetition and blank/tag-only remainder. Broker cases: rooms.test.mjs covers sorted/reused canonical threads, other-instance and other-owner collisions, all three verbs' human/tester gates, missing projects/member set, partial/foreign/wrong-instance rooms, key and current-name addressing, ambiguity/same-member name+key, unknown/non-member/old-name tags, tags-only bodies, one/many/broadcast targets, original bytes, shared message timestamp, routes/deliveries/human.input, denied last recipient, clearing last session, all-session merged reads, agent reply metadata, merged paging/default/max, foreign/noncanonical/absent cursors, and same-at repeated sends. Synthetic historical rows append valid rows; they do not rewrite evidence or clocks. The same-at batches repeat the first recipient at each boundary, proving identical sends remain distinct. + +Each named refusal has one mutation of its enforcement, run against the entire new rooms.test.mjs file. The driver mutants.py stores the exact original→mutant diff in logs/Mxx-*.diff, logs UTC/load/busy/TMPDIR, accepts only Node exit 1 with the named target test failing, and restores/verifies full broker bytes and SHA256 in finally. No mutation is retained. Generic pre-existing request/schema/argument policies are exercised through existing code; the matrix names the refusals added or deliberately inherited by these room cases. + +| Mutant | Refusal | Guard relaxed | Required failing new test | +| --- | --- | --- | --- | +| M01-human | human-required | remove common room human check | room verbs require the human | +| M02-tester | tester-refused | add the three room verbs to TESTER_VERBS | room verbs require the human (explicit absence pin) | +| M03-project | project-not-found | remove room project lookup check | room verbs refuse missing projects | +| M04-members | thread-instance-missing | allow empty member set | room verbs refuse missing projects | +| M05-collision | room-thread-name-taken | remove canonical owner/instance collision check | room.open preflights instance collisions | +| M06-open | room-not-open | remove missing canonical thread check | send/read refuse a missing canonical member | +| M07-body | invalid-request | allow empty parsed remainder | unknown or non-member addressees and tags-only bodies | +| M08-unknown | unknown-addressee | allow zero member matches | unknown or non-member addressees and tags-only bodies | +| M09-ambiguous | addressee-ambiguous | allow multiple member matches | a legacy name colliding with another member key | +| M10-messaging | message-sender-refused | omit room target messaging check | messaging denial on the last target | +| M11-cursor | message-not-found | unknown room cursor falls back to seq zero | room.read groups one send, pages | +| M12-fence | session-clearing | omit room target session fence | a clearing last member fences the whole send | + +For M02, the existing human check remains a second barrier: the mutant deliberately relaxes only the tester allowlist; the new explicit absence assertion kills it without loosening or running the old pin. Existing helpers keep their full session-state behavior. No helper or schema mutation ships. + +## Reader / hash audit + +`rg -n 'broker\.mjs|TESTER_VERBS' packages/*/tests --glob '!fixtures/*'` produced reader-grep.txt (133 hits at audit time). These are imports except the concrete source read at bus/tests/limit-checks.test.mjs:323-326 (forbidden limit-check/token-limit imports) and the tester set assertions at bus/tests/tester-writes.test.mjs:18-32. The latter stays byte-for-byte unchanged. bus/tests/viewer.test.mjs:116 builds its coverage set from exported verb lists; rooms do not widen those lists. No old test needs an edit. + +Pin check: recursively inspect packages/*/tests plus scripts/test-*.sh for changed-file mentions (broker.mjs, address.mjs, packages/bus/README.md, packages/bus/src/index.mjs) with literal 64-hex values within eight lines: pin-context-grep.txt records no hits. A direct same-line hash/digest/sha256 grep finds registrySha256 imports only, which hash host registry data rather than broker bytes. The independent channel-proof.test.mjs baselines cover proof/transport files, none changed here. Positive control: pin-positive-control.txt records actual schema.sql / SCHEMA_SHA256 / createHash references in bus/tests/schema.test.mjs and bus/src/store.mjs. Schema bytes are unchanged. + +## Requested serialized slot plan (not run) + +At each run: fresh `TMPDIR=$(mktemp -d /mnt/storage/scratch/tmp/XXXXXX)`, date -u, uptime, and `bash /mnt/storage/scratch/sage-busy-now.sh 2>/dev/null | tail -1` in the log. No concurrent test runs. Ignored root node_modules symlink targets the canonical checkout; it will not be committed. + +1. `timeout -k 10 120 node --test packages/bus/tests/address.test.mjs` whole. +2. `timeout -k 10 120 node --test packages/bus/tests/rooms.test.mjs` whole. +3. `timeout -k 10 600 node --test --test-concurrency=1 packages/bus/tests/*.test.mjs` bus suite whole. +4. `python3 agents/goldie/work/queue-265/mutants.py`: M01 through M12 serially, each runs `timeout -k 10 120 node --test packages/bus/tests/rooms.test.mjs` whole, fresh TMPDIR/header; stop on a live mutant or wrong failure. Record each diff and restoration digest. +5. Restored address.test.mjs whole and rooms.test.mjs whole separately, same commands as 1/2 and fresh directories/header each. + +Estimate 5–10 minutes; bus timeout ceiling 10 minutes, individual new/mutant ceilings 2 minutes each. On first new-test red, record/report it. On any old-test red or need for old-test change, stop and ask Sage. Static node --check for new modules/tests and git diff --check passed; no tests or mutants run yet. + +## First slot STOP — sage-3932 + +2026-10-24T04:27Z: stopped on an old-test red. No old test changed or rerun, no mutant executed, no product adjustment after the failure, no commit/push claiming verification. + +| Step | Exit | Counts / disposition | Log | +| --- | --- | --- | --- | +| 1 address whole | 0 | 14 pass, 0 fail/skip/cancel; 58.559 ms | logs/01-address.log | +| 2 rooms whole | 0 | 18 pass, 0 fail/skip/cancel; 1067.524 ms | logs/02-rooms.log | +| 3 bus whole | 1 (stopped) | partial 619 top-level ok, 1 not ok; not a completed-suite result | logs/03-bus.log | +| 4 twelve mutants | not run | stop rule | none | +| 5 restored files | not run | stop rule; no mutations were applied | none | + +All three run headers use UTC/date, uptime, helper CLEAR and distinct 31-byte scratch TMPDIRs. Bus began04:25:22Z at load2.80/2.91/2.61, TMPDIR /mnt/storage/scratch/tmp/LaZAaK. Parser used /mnt/storage/scratch/tmp/rqcTH7; rooms has its own header. Explicit TAP reporter was selected for rooms/bus and the mutant driver so failure detection/counts are stable across Node26's default spec reporter; this changes reporting only. + +The old red is project-runtime.test.mjs:12, assertion:14, test620, “Broker keeps the sandbox client import closure: only the listed imports, no lazy project import”. Actual imports include the new `import { parseAddress } from './address.mjs';`; the pinned array omits it. ERR_ASSERTION deepStrictEqual; individual duration2.469251ms. The full expected/actual/stack is in 03-bus.log. No other red was observed before stopping. + +Reader-audit correction: reader-grep.txt:100 already contains project-runtime.test.mjs:13, a direct broker source read. The earlier prose incorrectly described the import-closure assertion as a normal import; I missed this old source pin during inspection. This is not a hash pin. Follow-up static trace finds seat/src/sandbox.mjs:50-60 RUNNER_FILES includes broker and landing but not address; seat/tests/sandbox.test.mjs:45-53 compares this mount list to the recursively imported source closure. A parser dependency therefore also needs the one new RUNNER_FILES path. Both an old-test pin change and this out-of-owned-files product change require Sage/Mos approval before edits. Recommended bounded change: add only the parser import to the project-runtime expected imports, add only packages/bus/src/address.mjs beside broker in RUNNER_FILES, and leave the generic sandbox closure test unchanged. + +Broker bytes remain SHA256 71b32ee4afa322793aad81231441ee7badc3e5aff65ff008c6cc0f7f63b72781. git diff --check still passes. Slot returned in goldie-0032, pending ruling/new CLEAR; no reruns. + +## mos-1567 approved closure correction / second slot request + +Sage-3940 relays Mos's mos-1567 and widened row scope (sage-3939). Applied exactly the approved pre-existing-file edits: project-runtime.test.mjs adds two lines at17-18, one Row265 comment and the parser import in the pinned array, no other line changed (numstat2 added/0 deleted); seat/src/sandbox.mjs adds only `packages/bus/src/address.mjs` immediately after broker in RUNNER_FILES. seat/tests/sandbox.test.mjs stays byte-for-byte unchanged. The parser remains a separate pure module. A NEW block in address.test.mjs asserts `doesNotMatch(/\bimport\b/)` on its source, with a node:fs import in that new test file; no existing assertion is moved or weakened. + +Review packet must explicitly call out the RUNNER_FILES mount-list entry for Boyd's review. This is a read-only source-file mount needed by the broker's static dependency, with no new module dependency or role/verb authority. The first-run import pin failure remains recorded above and in logs/03-bus.log; new logs will have rerun-prefixed names, preserving first-slot bytes. + +Requested rerun order, awaiting CLEAR after Bentina: first `timeout -k 10 180 node --test --test-reporter=tap packages/seat/tests/sandbox.test.mjs` whole, then the original five steps again from step1: address whole (now15 cases), rooms whole, bus whole with concurrency1 (includes project-runtime whole), M01–M12 whole-room-file mutants, then restored address and rooms files separately. Explicit TAP reporter is used throughout for stable logs/kill matching; timeouts otherwise120 per new/mutant run and600 for bus. Each run still gets fresh short mktemp TMPDIR, date/uptime/busy header, serialized with the same stop rule. Estimate5–10minutes. Only static node --check and git diff --check run since the STOP; all pass. No new test run yet. + +## Verified result — sage-3942 CLEAR, slot returned goldie-0034 + +All rerun positives exit 0 with zero failures, skips or cancellations. Full bus suite passed 957/957, including the approved project-runtime import pin. The unchanged sandbox test passed 10/10, including its recursive mount/import-closure assertion. New parser cases passed 15/15, rooms 18/18, and both passed again after restoration. No tests run after slot return. + +| Run | Exit | Pass / fail | Duration ms | UTC / load / helper | Log | +| --- | --- | --- | --- | --- | --- | +| rerun-00-sandbox | 0 | 10 / 0 | 5526.027699 | Sat Oct 24 04:31:35 UTC 2026; 23:31:35 up 10 days, 14:51, 2 users, load average: 2.83, 2.91, 2.73; CLEAR | [log](logs/rerun-00-sandbox.log.gz) | +| rerun-01-address | 0 | 15 / 0 | 54.634817 | Sat Oct 24 04:31:45 UTC 2026; 23:31:45 up 10 days, 14:51, 2 users, load average: 2.54, 2.84, 2.71; CLEAR | [log](logs/rerun-01-address.log.gz) | +| rerun-02-rooms | 0 | 18 / 0 | 921.788987 | Sat Oct 24 04:31:52 UTC 2026; 23:31:52 up 10 days, 14:51, 2 users, load average: 2.42, 2.81, 2.70; CLEAR | [log](logs/rerun-02-rooms.log.gz) | +| rerun-03-bus | 0 | 957 / 0 | 118397.418425 | Sat Oct 24 04:32:01 UTC 2026; 23:32:01 up 10 days, 14:51, 2 users, load average: 2.28, 2.77, 2.68; CLEAR | [log](logs/rerun-03-bus.log.gz) | +| rerun-05-restored-address | 0 | 15 / 0 | 54.587943 | Sat Oct 24 04:35:02 UTC 2026; 23:35:02 up 10 days, 14:54, 2 users, load average: 3.10, 3.07, 2.83; CLEAR | [log](logs/rerun-05-restored-address.log.gz) | +| rerun-05-restored-rooms | 0 | 18 / 0 | 991.877991 | Sat Oct 24 04:35:11 UTC 2026; 23:35:11 up 10 days, 14:55, 2 users, load average: 3.17, 3.09, 2.84; CLEAR | [log](logs/rerun-05-restored-rooms.log.gz) | + +Mutant driver exit 0; all twelve target tests killed their guard relaxation with Node exit 1. Every mutant log records exact bytes restored to broker SHA256 `71b32ee4afa322793aad81231441ee7badc3e5aff65ff008c6cc0f7f63b72781`. Driver receipt: [rerun-04-mutants-driver.log](logs/rerun-04-mutants-driver.log.gz). + +| Mutant | Node exit | Pass / fail | Exact diff | Raw log | +| --- | --- | --- | --- | --- | +| M01-human | 1, killed | 16 / 2 | [diff](logs/M01-human.diff) | [log](logs/M01-human.log.gz) | +| M02-tester | 1, killed | 17 / 1 | [diff](logs/M02-tester.diff) | [log](logs/M02-tester.log.gz) | +| M03-project | 1, killed | 17 / 1 | [diff](logs/M03-project.diff) | [log](logs/M03-project.log.gz) | +| M04-members | 1, killed | 17 / 1 | [diff](logs/M04-members.diff) | [log](logs/M04-members.log.gz) | +| M05-collision | 1, killed | 14 / 4 | [diff](logs/M05-collision.diff) | [log](logs/M05-collision.log.gz) | +| M06-open | 1, killed | 17 / 1 | [diff](logs/M06-open.diff) | [log](logs/M06-open.log.gz) | +| M07-body | 1, killed | 17 / 1 | [diff](logs/M07-body.diff) | [log](logs/M07-body.log.gz) | +| M08-unknown | 1, killed | 16 / 2 | [diff](logs/M08-unknown.diff) | [log](logs/M08-unknown.log.gz) | +| M09-ambiguous | 1, killed | 17 / 1 | [diff](logs/M09-ambiguous.diff) | [log](logs/M09-ambiguous.log.gz) | +| M10-messaging | 1, killed | 17 / 1 | [diff](logs/M10-messaging.diff) | [log](logs/M10-messaging.log.gz) | +| M11-cursor | 1, killed | 17 / 1 | [diff](logs/M11-cursor.diff) | [log](logs/M11-cursor.log.gz) | +| M12-fence | 1, killed | 17 / 1 | [diff](logs/M12-fence.diff) | [log](logs/M12-fence.log.gz) | + +## Final review scope and packet + +Boyd reviews the three room cases, pure parser/export, README rows, new parser/room tests, and **the added read-only RUNNER_FILES mount for packages/bus/src/address.mjs**. mos-1567 authorizes that one sandbox source line and the sole old-test delta: project-runtime.test.mjs:17-18 adds exactly the Row265 comment and parser import pin (numstat 2 added / 0 deleted). Byte comparison against base after removing those additions proves all other old-test bytes unchanged. Removing the single RUNNER_FILES addition likewise restores sandbox.mjs to base. sandbox.test.mjs has no byte change. New address.test.mjs block proves the mounted parser source has no import word. + +The widened changed-file hash-context audit includes sandbox.mjs: [pin-context-with-sandbox.txt](pin-context-with-sandbox.txt), zero 64-hex-near-reference hits. The original reader and positive-control receipts remain alongside it; the missed source pin and first STOP remain recorded, not concealed. No role/schema/tester allowlist or helper change ships. BUILD-LOG and SESSIONS only append tracking entries. + +Base: `ec86f2c847f6154a0677c6ed23c87dabc2c665d0`. Branch: `goldie/row265`. MANIFEST.sha256 lists every changed source/test/tracking/evidence file except itself, with repository-relative paths, and is verified before commit/push. Raw first-red logs are retained separately from green reruns. + +Evidence packaging: logs are stored losslessly as `.log.gz`; decompress with `gzip -cd`. Decompression was byte-compared with each raw run log before packing. This preserves the original failure/Node whitespace while keeping the committed diff whitespace-clean. The run driver recreates raw `.log` files when used. Mutant busy-check headers identify only their own Python driver PID3686656 as BUSY; positive runs report CLEAR. The driver held the assigned slot throughout, with serialized child tests. diff --git a/agents/goldie/work/queue-265/MANIFEST.sha256 b/agents/goldie/work/queue-265/MANIFEST.sha256 new file mode 100644 index 000000000..f4f022649 --- /dev/null +++ b/agents/goldie/work/queue-265/MANIFEST.sha256 @@ -0,0 +1,51 @@ +996e9d0c1e7a8436691ce5d5d89b4eb940b07aafb3386f63a9847d203f43d998 BUILD-LOG.md +26b5821895a152ddac66a26f16585c6c48ec71d99ca7e7c2b9a4d5a71943c5b4 agents/goldie/work/queue-265/BUILD.md +1289c0f9f4e857590490a0972b5300cc8fb1a86e3ef79fe63e47472709e982f6 agents/goldie/work/queue-265/logs/01-address.log.gz +bc0ac95454ca4a4478641832e68caeb82bfe8b1fdc9abc0b80f1126ef42b7be5 agents/goldie/work/queue-265/logs/02-rooms.log.gz +459a45bd772576847338a438b27f4f578a2a660be744e1404fd239d192c6957c agents/goldie/work/queue-265/logs/03-bus.log.gz +c30cecb149e98d64f285e81a82d07a0a89dad5ea223f9031b543230615663bb5 agents/goldie/work/queue-265/logs/M01-human.diff +a75e02d91ff46fbfaf627beea943183b769e417bcb572bf11f778f0fca7fcf29 agents/goldie/work/queue-265/logs/M01-human.log.gz +b78b1c5b205272411710f56a981acf58dc09c46333369924b98c4c8657dc949c agents/goldie/work/queue-265/logs/M02-tester.diff +6a680dcb1db461cce3a3a2e066aa1245e4f84aa6754354058009bc0f6ebf4185 agents/goldie/work/queue-265/logs/M02-tester.log.gz +02a6cfab404405099fc39eb83413614c67a0c4c3f87cd23c3849a35d1055ddb0 agents/goldie/work/queue-265/logs/M03-project.diff +8b7cd0c568510e49b61fa14fce7b2680025b773eda884e0a84163d240a124e39 agents/goldie/work/queue-265/logs/M03-project.log.gz +18b2cb43f2799301cf934e4c327bc1a03e08ff8d11ff590cb9677c86dfd43ff0 agents/goldie/work/queue-265/logs/M04-members.diff +195f9ec57c9494552566d2f8b87f3b17a210b811f8b556dd65db89814e237816 agents/goldie/work/queue-265/logs/M04-members.log.gz +a773e214c76acf5285ac4ca17cdd90dd552ddc79157abe75ef6de7f67a0b6a70 agents/goldie/work/queue-265/logs/M05-collision.diff +1148cda3f6aaa7f6aeaab2f95c932114ddeac5bfd9318a6b77a4148079d486ed agents/goldie/work/queue-265/logs/M05-collision.log.gz +56400065c9cdb6305763b2bff8c0e06e9ae1223fa89b4467634a9951622d3fbe agents/goldie/work/queue-265/logs/M06-open.diff +b8f9bd9a5c488e604d0afe3feda4a2602359a94a49c7fdbd2f0f6a421b0ca1ce agents/goldie/work/queue-265/logs/M06-open.log.gz +2c1b745a15602cdcaf194131e4d6e0f8fa349e9712ce2e8cb6e695699e4ec19d agents/goldie/work/queue-265/logs/M07-body.diff +4857461e7a2ceb01a6446acb4708a732949a0d8d1a85fa2f6d10bedde6b9e11b agents/goldie/work/queue-265/logs/M07-body.log.gz +e3480e69d016caea6c1fbcdfa022b18214a10e8deca4409d0dc2f72261d2ee92 agents/goldie/work/queue-265/logs/M08-unknown.diff +3d0f347f21df3c388a4f39679d4694aadc9684ae8b8ad2d30bf0bb316e48dcb0 agents/goldie/work/queue-265/logs/M08-unknown.log.gz +62420ed20affcab256facee05414b8b760a4c79a60f60be0c06c88abb61ec6ae agents/goldie/work/queue-265/logs/M09-ambiguous.diff +14a18d61344df592e885c46ace34e0c59914f4fbe591fa99eeb3d81fa8ef8bf1 agents/goldie/work/queue-265/logs/M09-ambiguous.log.gz +0671bf77394f82df92252275171fd9edea2e5b2e7143387840d03bda544676bf agents/goldie/work/queue-265/logs/M10-messaging.diff +4202215d40999e0d1cc98ebfb5445f0c8fd4688e6ca968e85d225723076ca8a7 agents/goldie/work/queue-265/logs/M10-messaging.log.gz +042598ecb551e761d37af898f69e17ec137d2f39687dbf81ce5e1eeb98a38202 agents/goldie/work/queue-265/logs/M11-cursor.diff +deff3d0514c379bd3d9c6f6bbc60db59b9dce2baaafd6fa611711c98cc8365ce agents/goldie/work/queue-265/logs/M11-cursor.log.gz +780e70fbcb2328006c8d9ace75aa62fcd0d935b4d758b50b0f5c5d5c55604122 agents/goldie/work/queue-265/logs/M12-fence.diff +b629b41a39c028b70d4b847c351d248d6d70e8175d6d27f563b0ed8817f89642 agents/goldie/work/queue-265/logs/M12-fence.log.gz +1b8c3cec31b44ff018a1bc74fef95996bcbdd21d340e2d2605154ba645648040 agents/goldie/work/queue-265/logs/rerun-00-sandbox.log.gz +d18c5a9432de06ebec36c937da7dfb1a3e79dc397b33ff624058af351eee24dd agents/goldie/work/queue-265/logs/rerun-01-address.log.gz +d10b83ccec56e47d8c7c74d8304fc4fc87b8ea92a50098380cd02b8012c32d09 agents/goldie/work/queue-265/logs/rerun-02-rooms.log.gz +6ff5955fe5c85f51c1cf4daeb8eddd61ef1a30e170221f99bfb08da8304d7e4a agents/goldie/work/queue-265/logs/rerun-03-bus.log.gz +eeba0182f06cee0c06cd15ecf7ef43aaeffd7149b2202cc0653078c20bb46198 agents/goldie/work/queue-265/logs/rerun-04-mutants-driver.log.gz +5fe9fe35af60ef951c5c68b040aa9bb6067d9c746e143bb5782eb428acd4e4fe agents/goldie/work/queue-265/logs/rerun-05-restored-address.log.gz +2b3f3305ff5f6926a0269bd6c88d5f2e4a89727eefcf99625bebb51a70abb649 agents/goldie/work/queue-265/logs/rerun-05-restored-rooms.log.gz +f11ae40d923affad1936fe51d05981ac201a1051bc9f877d75fc1d544c6e38f1 agents/goldie/work/queue-265/mutants.py +e9cdf16670a16a14f3dd722a69c63a1785e4deb3608ee05d519b0ec8c1a9ca0b agents/goldie/work/queue-265/pin-context-grep.txt +491ba3bb25e918049249178f3c6a67b2b4f56a197f0a67059acb2420cd03b73c agents/goldie/work/queue-265/pin-context-with-sandbox.txt +784fb42bff187c0eebcf7756942ec3cf56f8faa7b54ce4ad96181b81fe46f0e9 agents/goldie/work/queue-265/pin-positive-control.txt +766ead519eefbde958bbdbf77bf858b10dd1e3d9dee8ab5d356fe821ce7602fe agents/goldie/work/queue-265/reader-grep.txt +6c3c44eb943f33d5bb547f542c77da4d6f04e738056466bc491c2f6fd5f67946 docs/SESSIONS.md +1ba33af1f42c88a5346d25fe915a44ee70a27fbc6b9ab880db0866cbdad5d45d packages/bus/README.md +232a1c77c2f17011c53b55fc6052f70985598210769d41d7c2c0b535328aad23 packages/bus/src/address.mjs +71b32ee4afa322793aad81231441ee7badc3e5aff65ff008c6cc0f7f63b72781 packages/bus/src/broker.mjs +ed57d48d2af4a225259e0a44c86a30b12792ec9f725dd9c89251569b7dc89e5a packages/bus/src/index.mjs +a6725ffe30d44981a9b9d3a3c319f7e96a46ec7bd74f0c8d869d9a798eca1a81 packages/bus/tests/address-cases.mjs +fae431bc3743b224f69da33c4cebe376b47257d67f52d25d3ab0cb59f224a607 packages/bus/tests/address.test.mjs +8594e94384c1c8b7234cfa8bbc17456cff86d9adef936cd1059a0d5a60e4546b packages/bus/tests/project-runtime.test.mjs +892c3709393fa8962710bc07565d1097bbd79ea1fbfda34af5f9385db34ed0fa packages/bus/tests/rooms.test.mjs +83019fa6b39ad9fd79b84627856b4dec82683d8261b8cba9b9ac840e0c489268 packages/seat/src/sandbox.mjs diff --git a/agents/goldie/work/queue-265/logs/01-address.log.gz b/agents/goldie/work/queue-265/logs/01-address.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..df11d7b412eb79aaebc36b6cd3e5db0b1c6f7584 GIT binary patch literal 434 zcmV;j0ZslNiwFP!0000219g$jj?*v@$M1QHIWAIZ{1NA)(jHbz5i5Zf?G}j}8l0gG zB#yBimfm>;j=Tu3!;`F=L_MJNVtK~DnfcG(j~L)y2M`&sY$LKwR>6neEeIy^1caPZ zg9Xl@#-m>WkC|)*AYkz1VglM8Yrr4ma8DZ$YtC2kEamA`MRNOgd-IU&-o1Zy_i&wd zCZs;}CpPukVbF&(bT)P0_3llP{QL78EILm&b?wOe4fKZKimyv9xhgvUVgc#U9N~(s zx!@wtml;Qv;hXF&=8)!Tr80=^&5~^DK#`ue0Ne2(6H!lPI4Di&1Lq7!2Jvn{q z6zip8`RwAazYs;o0-lY5A5KdE8v~2}{O|>vc1~+Fn%b7?IriTgYtK>W>wdo0gB#U< c>O81&tyEc+D%pO#+g-Ed88gsAjamZ$008FD`Tzg` literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/02-rooms.log.gz b/agents/goldie/work/queue-265/logs/02-rooms.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..f2c4752a2037805d879588b1827aaab727f25d7e GIT binary patch literal 1211 zcmV;s1VsBEiwFP!000021HD&GkJ~m7z57=X$RU@ttZ&)7$RS9AB0!4<$rk9Xpe5R7 zEs-iot>gUqzMaj?zr zt(P1=qv#&2?xfr3&M~oC5h}u;1OI>7Vq7&v5Qa&TWG_L#(niR&nhsh$fkQFQ;mnPW zF^Ti2h~_V0vNKw(rw{4j1S<1!D(CJr&Sep#VLVSyI~4)JV2+!$ApNqf*k7@wL2W9z z#mK>=E0M~FA8>pQ_TLUsc>n5}t<*~behqjhSl zAW~mAL-^ui296O=(kw2XPc@v?V$I88UtdKkN)i+oz|%(sqtzad;uiPmy>D4;#Yg5e-pU3F=in zn%zd%!sqCldrk7vNknCU-^1Z$DcT|2sTcQa?|d}k$$YUmEyw#Rvqpk!>8SL^uUHFR z!T$cf1tJ0+;2v|9I&05Af5QK@EsRq~=Uc>Q zF+be9yseVAy%<&J<*8Q?DzsP8DKwJqYfvTvQ_5CSAPzM=DxQ#ig-u8KWyJ#5yhWC0 zXE3~XAXf~UBLk?E`@XJF+2}8pgR_So>(FcvQaZHK_22s&$ph{A6WW)uG=9_zl6jWq zxO*_P6%k40@;#E8BK>cDmC3;gNl`DtQrP Zak7Y`$*12x-@Xece*^6n2a^8~003DEV$c8p literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/03-bus.log.gz b/agents/goldie/work/queue-265/logs/03-bus.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..8a240914589e799f56aa3cbf9f6982de2c1394cd GIT binary patch literal 32317 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 literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M01-human.diff b/agents/goldie/work/queue-265/logs/M01-human.diff new file mode 100644 index 000000000..851cfd33c --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M01-human.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M01-human +@@ -6423,7 +6423,6 @@ + case 'room.open': + case 'room.send': + case 'room.read': { +- this.#human(s); + const opening = verb === 'room.open'; + const sending = verb === 'room.send'; + keys(a, opening ? ['project'] : sending ? ['project', 'body'] : ['project', 'after', 'limit'], diff --git a/agents/goldie/work/queue-265/logs/M01-human.log.gz b/agents/goldie/work/queue-265/logs/M01-human.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..7be6068a3bec493817da3140253ed132f40e64ce GIT binary patch literal 1963 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 z this.#threaded(s.business, instance)).sort(); + if (!members.length) fail('thread-instance-missing'); + const owner = this.#owner(s); diff --git a/agents/goldie/work/queue-265/logs/M03-project.log.gz b/agents/goldie/work/queue-265/logs/M03-project.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..e4fdb31c1a45d35a60987ee57c664dc60f64370d GIT binary patch literal 1909 zcmV-*2a5O~iwFP!000021HD<>a^uDkeb-k^l^=Fp5pln7HdXRkuG+-TZb|Y(o>W6% zNMZ$G;F*DFCeFX-^Z?YwA}wi6=0ye0tFI7=a>G8Ah6NGxq9TlnAZ0&aePDqX zBquBgr=g)|zQ-!Q(WlIhia0uDEMS8c3InW>ykh)TD83X03!Mnlq2v3fEO4^$Lp!70rEIEN zxNE6y++PMUh*^-tZaWx`SscSou73Lb{l|;Sa@DmCS~a@(nS)^(;&_KldH4OY+}p&@Z=kIIn0gF zreI3S){(vFn3l?D#+!zjl@h!X6{|Z9)TMyBOAKKLtHgp2jll>9P$ggu%}VSNY9`km zHjTUWiM(Mxn;lUAW3$-|f2#r72D9r{7jP*j4)QF@F<~}6JmU=!eS@El!G<^mk2t-2>rS+O<|H{>H2gZWqz|u$-W%c-sGe+wm9E8024&Iim34eva`#bv-B{~rIV58BNlcJegO;`AwtMwWIR zhJF{|OlV`4Q9@|9m73S(4DMOpOc8CSAZwB08BiURqZB$*FW`kQU`WXz& zo5C*t3*)81FQ`yVJMFmr!`KJe_FUB(;p;!sdItZk2nyk~v6H;~jh&s{&prvRZ>A&v zyFGtecz$tleRg?yesT5j(?4lZ$6FddgJl#c`JDJ!q7%Ro`5(y{ITiQHc?#AV8$O4386z?<~fS%k#^V3#>HE5O>K`^rW zZiGW|6Swo2N{zB8DS~7aOV7qZh3yPOVSxPa;8xrn@$w?ft)!(eXJc4;+tD@WHWn0d z<`pqv!6inZwig>oiCpWaH+p&nj;^05Ed0q2u54`XjQG_!4=&yDF+g$gJp@M$-N)`s zZ@Tibgr@Fvh=J>slsE9+0FO)bc+0e`27ZMU*h;#_I5HOdjSXH<1P=uv_9BJUpG8;U zrJWvi{p>+`8Wn!_@Eobl#Y+&xQBe5#t8pjkosFy({xtgZ+o!3F#yKt}$XnOrcPU6o z&OmA2HuYH7D0T+J#9~3I2_<0(9?w5>#O@R(L4g(JS@vuqwnOv+v94ZrvngqP0f%%q zhgTl7k4cnyQS?VDz80hAD1jf?UBB$_#ha}aD|{q+4qguoHD!# zs69FP>sF-U%c*ul!GUmji{x)x&oYWhc1|idJ69VVJs9EEU5~94L5Xy}ty}(2BKH*! zQ643}|EzY(K`Ar~7^O1}-`K=aPt|KrMQvpf;+K}qtzZ%+dj~q0ZFq^Pe zPHHP?54t#-fZfDXC->t#e%>uOYs8Y5)48^sq!4E90(cUYo7#FLY-g*sc3v+BJV)pAML;kWAFJ=e9|5qii*+M1b|nSqAG5(3>jo5JCr(eiAPj} z3VK!80Ki(~9esGqeQGKk_}Jau5g%)q^>`dkrb6UUab&(S_Obcq-Y|9v_3x@}n{MoFOiwKNFo!7+vk<$`_Zw+%8ze^*vr`9Q=;VRt zhtVsPaDxT~dU_Q(8$GN9k@{p7oThkWYWS|BP2g8h-*#ZFu#)$qH+F;dPq~1n!ucw?hN`B{Ew#UtDC@o^OKcx; zKYhgZ0Eg}*80CrM`FWIwuV8qmLEepxe*08z#)pO8jj_c%X?setw%G-FMw{QqRxwJ;wGO$IqaUvA(dMdZ?-A?%}gXaSNm2%Qm5We3XO+jrYnf v&^LA8Pv1sX(tbRU&+;I2yfpF92Dv!Dy!v!;{yjU?KQR6W;3B~RG8zB?x~sV_ literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M04-members.diff b/agents/goldie/work/queue-265/logs/M04-members.diff new file mode 100644 index 000000000..49b81344a --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M04-members.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M04-members +@@ -6431,7 +6431,6 @@ + const project = identifier(a.project); + if (!this.#store.get('SELECT 1 FROM projects WHERE id=? AND business=?', project, s.business)) fail('project-not-found'); + const members = Object.keys(b.roles).filter((instance) => this.#threaded(s.business, instance)).sort(); +- if (!members.length) fail('thread-instance-missing'); + const owner = this.#owner(s); + // Preflight all collisions/missing threads before open creates or send writes anything. + const threads = members.map((instance) => { diff --git a/agents/goldie/work/queue-265/logs/M04-members.log.gz b/agents/goldie/work/queue-265/logs/M04-members.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..268dd9f5fef11477419107967a19582e3b1a40ea GIT binary patch literal 1672 zcmV;326y=%iwFP!000021HD*nZ`(Ey{_bBvU?187v0kYcJIjEq&46O)S|sU*eF|ua zvKdRHN>Xt>?8onplJnBZOWY;{f`BG@$LBfT9q)9(EcsYi5>XP+c?^F6`F#17L_w5J zNE8oKT}#4%lx%B`NJ!@iJt8C`o#7fLNUc~&*bUcg$>${YXnq9$!{~@aUQQ>!e!lpV z#A%+UNjfL~N;TZS-l*DMbKh&XT;BK~YlM=w=7ee~&)~=L{2`H7;_)Arng8Lh# z*Z!A|cYGS9iQjaV!78XBlgkgE-n~CR@f&GdHRVAoJkl@ej*p$!g6Eh zL@U*Js^yXxrL7^Xu1ODzmt+SFj9$PLNRX0Otg9`|Fj)c-xD!JPkm7o(HWGw-X){r4 z5|Zf)9ze)+I)(pb2Q~+0SB(L0$h?%&D5bDqw=MX`DDsKs&x=yrfe zq3T*VA0f=DMj(PMa*7^sdb;Q++9>tnAW5?CM2q&&`=Q4Bp#GQKD9&)^Wl20slPBRs zS6iT$f9Ztga9^CPx`xUAN~MyV2so3V1mM8k2$v3UzejxBy0I6`@+1xqLk+RX$u1OI zt*&{2ehX*+#kC@R5R*j*>)e2MPNcE~@F(BmKUmSYM<*T)vos#@ky;gQA549d=4|XT zm(`pbzfp#XVhZkAtcScd)oO$Jtc5AaTgC?zKB_f7QZOElz2@4?^K>5KSrrp?r}^a_ zg14&VzxA`YforWaEPWUV^RF%Ng?Qy(3*I7354RN{1-s79&#z7|F3!#`-+%lA=Ot@! z{uB(Maq}6fb9x6oa~R)>@5!9FADkVm=b*qYwJ|v9xX;PoQ>Wz8p_i6_wcgJRJZjsh z&iq1NSEA-~-+wV<&Z2o3yt&2T=}x|vr)DdQivnT?J)yUD6(p)U%bja&Z;E;`TI8f1e)=j)P3nThHL^fK<<@D|)eFBqwoXMe@ z_C3!jO=scL9uN;<5XvFvr>bn-p zzS1FtUq;n8oG7@mW1s`8H7j8Cz92sSom@-sQCDLIV2c+!V6TSBwU>{Ze;*&9CAk+YwMTNKh8SxVkoWS>`~f- z@xY(3S{u3^!pc%(nKN7r-p5qQdP^1x-cSQnprr!=0Bj6AqxXY6#H#z5)sB;-UYye` zNgpNIt3zv-TnY#yXsxhRts(G+h=kawYeN=L7PuwwP%LO~2vnobr5GXN}u531z1=kK8I+ym5O6m=g@3cs^%_5AK&^UE3AN98Q}MD zSb=3?PnfJyPz}fdGA_?7d&RX$ACU`mZw2>fDzW512|Elx8cKz5V4bV;0z`tE5Laz zYg$-q863wQMj?y3D}e}yMrjLc2AfdFKYhUexlb6U4iTT_S#rqz@4ivE!wS~+?kGFw zpsE5_1@9{{4z<8<8`vOfUWiuUP3#`=FnhrE8I+C^gfR9Z8q+vEfZ?qLne0D^xuOKLAKu6#xK>5-arp literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M05-collision.diff b/agents/goldie/work/queue-265/logs/M05-collision.diff new file mode 100644 index 000000000..4de439e9b --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M05-collision.diff @@ -0,0 +1,11 @@ +--- broker.original ++++ M05-collision +@@ -6436,8 +6436,6 @@ + // Preflight all collisions/missing threads before open creates or send writes anything. + const threads = members.map((instance) => { + const t = this.#store.get('SELECT * FROM threads WHERE project=? AND name=?', project, instance); +- if (t && (t.instance !== instance || t.owner !== owner)) +- fail(opening ? 'room-thread-name-taken' : 'room-not-open'); + if (!t && !opening) fail('room-not-open'); + return t ?? { instance, name: instance }; + }); diff --git a/agents/goldie/work/queue-265/logs/M05-collision.log.gz b/agents/goldie/work/queue-265/logs/M05-collision.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..ead833b9229727c3fbe2403ffbaf386b42b67e0b GIT binary patch literal 1778 zcmVf1uIG9ruh;453(Z?x_LT#{_gB| z5~X>XCTU5$rR?rN6?NrhOU?(Qt<^Bw7t+v8YbzpESN_jV=--L6oy$5 zQCjCg7zJ@0FqX|}T}3RRO_L@~!4Oc8nl*H24UAAxgC1}wnp8l=lq1&yh(>BX zlPeMs=N<(R;y4ccuLsz4(CnhqB?(hENE6r^m@u0j4CE0i`UrlyuDf6J9*(2sizT4j z0wTM!0>nmk91(10LK*^kg;(^tIr(11LE-vI5%|U55x26k>tN^$J2sIuO`{moUMDr> zl>?%y)nvGil4~^B9)`d$wKpHMhitWnz_p9tZuef7X;MZgtD(Fd6g&Tn;DxN&uj42# zU`j~^Q?I$!Tr3Ft)U(RKd9Y6v>k+1l%POFPRVSyX7sqF3C#UDH-u#B+Xx=b>tig+M z@d>iCd?!97eDBEjI|eR?Er-psNMK&BH4a+UOY)~-e%9mRo*rIagOhGAL;@l}#(83zRv1OY4R z0>%YX_8SQNundz+RK1emMEWfgH5|=k;`&-fMHZJqewmNd=JX~Ak~l1b;?}s+Y_~yn z7x3VeneZMrK=@orqm82d*SIaI5}*$bQe~os(Q>ShiCP|Pz zIQ4^5|KFVYd(meHTpCN5xrUnH!@w1TI)IVo&`~j#3Sbh9aBxk66yUD78mo|a^6GCP z-(O=yZl0%6l-#Js*olRbkCAS2G}xZ^;33+|{(~t=I@ZlWEZ8B(;KpnPm3)c))=c(l z5XG(!wPSvLm89YPJoMPDY`T+Pp%-Eh+)7<@D4_>KSkoXX#GeBG?_se&xaMw>gmIpH z3;ISX#uvhwLi%+8rp%D-*W;GV_FI$h22q%$$&X1DMf$Hz6|naXX5t%Wi0M@BJt4%= zm4xs^l2YJDW%7`eesEIS6A{)*iiPv}9(cp}lJAc%x8-&yz(iSGr1?XDc?d8M0p`C} z^|}}r2;7qw3@bgdVw)o}SI`8lDDvLM07Dm3(+n=I-~%6_Z?YOUDbfBzwohpOwaD5CKC+O!&!f@UqLx$axKu@OK|ZNnbBiM2%tzqD*W zG9n>{J_U7Pwxt!!UM9rae-JAHrJQYD`mh)GCSbqfq3aiE5ysalPD#raw3_(Zwgj4+ zJr{r{;cBC{DFV*UUTeBJUkngCo)SJbH0;cTTwCZ?Z|vFL7ym=)DUU+9j9jbsw0mGs zcw2KO0JN?ZUUjCE!2@xmXg6doA>wIJ1>OpP003(ZLGSYQB*0GY9kbo9Wb9^Xp2XR; zN{;Msw`(Ri_z|@1@v7Q_=S?mN&eOJ<%pr)|DKJsI(C!@cDK^>V8thLGa}DdY;m~!* z%rI(=eXjeKbLi%l`dR8nH!$%Ec32@ki)cEPhT&_0MYCSYmf51|>CPr;WjLJ51b>7> zE36(y#bayScg^|GLj;_7kwrIqh_H3v0wQFOzA{QbB0VN)GT(eY8M_2uPU`Ig$=Csy zZlY+!6wU&I76dPNaT)dAwh``8%>F(@;s$vU#JAam6=ML7*Jy26>LNsJxLR-;1Crrj zyoPo?%=Hw+F^iFlsvT-jgh8`p19KXCwO0T1ivD*kVZZ9|FbU5(QF;s2w{KroSVjBM z9K~P_R5oC$V0|_Eq2l;vhL;D$D&BKEiES1SvMbu&0n@z-#(4l5CPA3oLc`q-QZc@? z+FZFAGYck;u{}KP_H^ypmK%r^-Ikkiz3tw8Ry)6<_I*h@l)BR>PW=O05xC$6upwhH zXg~G9@wL;3&z@=+jNuEfNCZDBL<3KrwOycByzi%PBWr0tF3BelW!y9jf+U}vo}8V( UIX!tv?&|6IF8~qDKC>SH0NHU=@&Et; literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M06-open.diff b/agents/goldie/work/queue-265/logs/M06-open.diff new file mode 100644 index 000000000..27bc2b924 --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M06-open.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M06-open +@@ -6438,7 +6438,6 @@ + const t = this.#store.get('SELECT * FROM threads WHERE project=? AND name=?', project, instance); + if (t && (t.instance !== instance || t.owner !== owner)) + fail(opening ? 'room-thread-name-taken' : 'room-not-open'); +- if (!t && !opening) fail('room-not-open'); + return t ?? { instance, name: instance }; + }); + if (opening) { diff --git a/agents/goldie/work/queue-265/logs/M06-open.log.gz b/agents/goldie/work/queue-265/logs/M06-open.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..48d43143cc7feb0b3bb4124b356ec2eaa6c7248c GIT binary patch literal 1864 zcmV-O2eXv%?*8}v4khQ(l{d*W?$ZK;Kqh&3zH{X{XRf$m9}B~Rh}S~T30QvZ}f%-aq=$pmti18#8*5Ff^-pbUS@s} z`cdQykuG^zgd*mvRT8gOo|hF#QFyC#m4wSQNHc$Seg27!VlqFReZ{W&r4icXj2JtX zsg}xU#_O7yjS{>RC97HuxP^e83oLcUj4YTjy5^qS*H~8r|&a~tmtWa0$4bU9`u|n2$ zW!-{tBb$m4>`A8Jkxb7gokZ(LP8=j@{AFNC9qKsJ@EFqnMK=vIbh0=K{Kd0ylBX>- zO!rG)DFJf{w&@$*4i;@?D_8}dj3|JEP7~Z{g!?7r)2J6txbXeJe;H~7q+m^@b=9t+ zHThW--vrym;D~wP;J1!s5W2-*GQE zbVk-aaNSkNZM|V)wIWnAq#Xts63Fmpu9>z$>@4Cii6%U}mW4fsr9Y%)6WUB`ln~l& zq~=vIM{E__F%Qp`+)@7Ru!KCTUFgxJYqd*8&<=e&&1ao2k~}0{D_+&T64&<#-pf+_ zFs#x6p_EiP`xgno*u}3ML_(^$<#mtrVC-hrs!|C0FFuU-LNg@_3ZqhMa>JU+(ndQ)!Up!KkD$S)E)> zQJDL|!1CJWkk*J_jq^83jr&IS`tPU5K>CaCF*vGkKeXq1-xgN|0{BizSh(3pxz%|P zB)M-jg?;2^8_|PG|2vTXugd4C@}6WoRzU!Tn%%Ox!8&Rz`wapw$b*NBP!OQz)t?aC zcv{CtTt9iyB8_rCdw7r3=JGiRP`u^-;>Ea=^v+0D3x68DP2NwJE-R@-wQlEQq54$i zf#M~dE?!=E(R2xuI-!rQ%m0!hY^P+qp5M0y&k!Y>7UiWkP0Ny?KMt}idtSp~A0NXN z5;axaTd_Z5cp1@dag>CnP53TwM372JiZJ+AJJaI3ZhDJ3Bi zdU5Dg{vwvs+R2g^!6Z!f7UE#H z<^^^i5>h+Ux7!v@YMW*cx;PnwW1UhG2C4USpTSuz*1Q<+wJjti0c#h)ljzpe!6RWi z+o?6nYTYBFzh%|XeA=B6xwg=)+%zpX)&0jJJIfZyGaAHEdvGXfK<6U>UY3fwx6v|W zkhyHpAS@-`Aq`P5mjVF*YmKMqVU+tcM|kCHrw1aQlSWbO2Tuw)Tu0h2MOz_`(6CVV zT_f_wkVNp*wPs5^t#%78Nij@-fjbidR%uT6!5ncnL`YMM!$n$NM!=Oxi| zY|U8#4J*QD5sg+^37S(`G`o$gh0W1#?|c$HQw6Jx@CP`&C`31!JF?FG+BZ*I+;{ve z_M-54N!~s)Yh=idVrAfd#yTpU*m8ew8GD3gcI9C-Hw-n#H~lyf{u@poA^@dd%@k@-})|2_g;0EI3UG$y9J&!b`^^ z0`s3e_B74ato+F%`CpsEG10Rq%z_t4ei*u1UIp(4Z)|((pK=9Hh4YmZhN_}rEsczn zD5|a^LmVD)KYb+ZD_lA$UzGYz=6j3qB@TY4K;8~Refw1IhlhpUjbW-hDtj!l4%G%B zrKqjUaNf=%@5Rm@iG31J8@5RpC2G1yIOPq1#X0S2Sk#@Y$i2hSBgv^D*Y* zqaZYxwU_pQ-d0^Vej8az`|*H3TX+e=EQ!Nxc6o7i{qgeRd-huYXYn6YuJZ048UO%N CKC1oz literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M07-body.diff b/agents/goldie/work/queue-265/logs/M07-body.diff new file mode 100644 index 000000000..812bfed30 --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M07-body.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M07-body +@@ -6450,7 +6450,6 @@ + if (sending) { + string(a.body, 32768); + const addressed = parseAddress(a.body); +- if (!addressed.body.trim()) fail('invalid-request'); + const selected = new Set(); + for (const tag of addressed.tags) { + const candidates = new Set([this.#named(s.business, tag), tag].filter((instance) => members.includes(instance))); diff --git a/agents/goldie/work/queue-265/logs/M07-body.log.gz b/agents/goldie/work/queue-265/logs/M07-body.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..58bfacbe02eaced3ccff29dd374588842cf3f078 GIT binary patch literal 1683 zcmV;E25k8siwFP!000021HD*FZ`?KzzWY}Y=phN<)q{Gj(iBKj7sw$^U^|EQVsIty zE@MelNy*L@{qg;V()y9^HtWPLU@YVzXXcyXa2`ApJ$qmFjK?g9iwJ)?`*{9_@qnjC zj7Jk`=vWxAN^I;g3*#b*j~U}^u+o6QYAq@zuA~twS+K}Ul4Jaa_~l-n9R2+9>~|KW zd736^!Thyur2pw!*Zn8yd)-F1S3Y>H(yjHu1|EN*TEE-$Yu!c+LfhW@D_vJg`q$cA z`hN~`kTaepelzp}s}RGE&fk6bAr!>kn))l!ejJ5A1AM^w3l=qjlry zPPWWy(_1F$n)PcVMI|eyS_{CXgr`f8z`-iH6hqyEBH9WD;2d<{1cZXA`)oKlFTR5!L zb*)@jFwyHqk^T)?#P3;jIO|TVVdf<~i1X;%(2_UIeyGttsQ<;c8)xFBJW8_cAeke@UZRBbx=(E(WYii`XRW$(Pt4EM%tz5%=OG59a)<7FgLMfg+T{~i(hq9%*ySvvm~^h<4|TD7w&Ru8Zt+ik-G1?{#Z z^>`emY5XmgTpQi4X1D3#08{earaV;AzMR9eG@r+Z+dSOP#@(fDz6>|2rh~cJw?%kR;6$l1(4?NOWZ3kAPubt8JZMyoORPOf99NvlI z1H4lX#-KT1m9kweHmntmv{T9IsFGC!6tk$B$>Rm?4XhVD1B1m1? z4B(3=Q?M^t@;nXs*DtGJwOomElIyBSMM;9r1@JTyw%JA`&dw$4W}#Mt9_&k|#`@z{ zCgj#ZcXm_1@Ko}5pLg!%=njMMt7cE$LqJgtnoR&iRT)a))5*|*%ye6C7}`4pVlB~| zf&qZ7MN@clH(>`Oi>aS@WYPNqJIm+!j<~LM>9&FNMSt8!uI23wF!+tOLX|V*p7L^P zh-bJ*)ChMV0f6;U&wLVVeY(ijqi?VIWQ#Bfijb5og{lW5&u<~T(Utslq|ydyj5b($ zHwLSY%&@iyQ1^hlJ`~FAmCYe;K1kFzZE){j%wJb{g`!hW!YkLdoped zP1DtOXddT{srRMAB5)RHCeT!13Lov>4lPfpX7^MRdOXRJ>;XQwloHrfMZrc5FCnC{ z)nT*LC-e%j+l!{dS|^}QI*6(*>!E@j5|h~mYnCQnXMTFm{KwX?Z=Rd;@Q{h<7TESV z#3?I9H%4PSxcJmdL@I)>qHAarJ)=-#VPvT~MF+8MuEXq}wT~clr-2Dx(0CZ6aryuY zZ#*d4@xjftu$!^rqke9D@0q+k4L{o{fRNIyRsFc%Jr&%Vo!>M2sWk1r>yeiSob!CQ zD?-l;b2wxy4DQnoiXOlMe0IWunBj{$CKlqOBs6#htK0^Ask(0Z?scWz#~uA_p2l7t d(`(_;>B-so`_q$O*kipW{sSEjwLQ8O002PcQIY@v literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M08-unknown.diff b/agents/goldie/work/queue-265/logs/M08-unknown.diff new file mode 100644 index 000000000..d4994939a --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M08-unknown.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M08-unknown +@@ -6454,7 +6454,6 @@ + const selected = new Set(); + for (const tag of addressed.tags) { + const candidates = new Set([this.#named(s.business, tag), tag].filter((instance) => members.includes(instance))); +- if (!candidates.size) fail('unknown-addressee'); + if (candidates.size > 1) fail('addressee-ambiguous'); + selected.add([...candidates][0]); + } diff --git a/agents/goldie/work/queue-265/logs/M08-unknown.log.gz b/agents/goldie/work/queue-265/logs/M08-unknown.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..fd42ba9f9166ae6079a9cc0800e9dd00dfac6157 GIT binary patch literal 1708 zcmV;d22=STiwFP!000021MOH#ZyPrdzUx;I=phMU?fW6En*wR-0y(4!Z0FFELG4l! z<6Uw??%Gk&AK!1dD?3i)Mt1B51#%HqBxmNE;mmMmPI$-OlpTu_79>TS6iLY5oxWsI z5M>h<#p6=nvM^v3-`E2dCPkVYFcz`i3WEh!YhE#aAq-!Mg2i5%9^f~`Z{*F=$*=ED z{$z1B%d#{pn7`JI@ZVqRx_d8tuiXfB;e*ynt*j3+(D)0f{C3l=wTc;-s?Pc=T~|{0 zm)e~BA9~S?X_TdY({~)ZV8bS-uiyUm>iD_esLr>YCN#b+4e!de-!-lOF`tDOi^)Lp z{B_LkSr$Ny7aRYq7V1k*;Yq~i6NUGpf-p6B5rj)X|~lE+b$&tuN3 zSs2A(l7vF!3tpA6NcnP^rORay%*w1RgJr(V;zb@o{^az()l_N>ofL3)H26xl1g8f>mP4`?|vlR~1yiZCF-0MS5g zC;FU)Z2E`-7@JO~_^o2rIlb3G8s_-2c0Ik$q4s8O%R_dihj_W%nmPrUSTGx~?mOX2)q>RMOQ-XEo2~vMk-Lo( zddPFp9syVO#-K!Cm9%ZmH%#$H*zwJ3=_#umLj1G3zQCJ~8#{zL*sXbq-A@TAp^at0 zMCp#v+Zn(fk0xYyyw1F29^_f_rSi2d-8n3MR!ViTtByJ&g!LP3xh$vf&+>e%ou)80 z)l4mxP#akvInO7y)~DOH9({Ywds~EYP=q9G$z|Oeae58mrLM&9!zvvR#%P1B*JFAT zA6xi4)D<5~(GpINj+LOosiWiLvlk~PN5`kH-uyx9WDKmoK;AWU_=wm!z9XLk-&f>c zlxK7jFDeY@K%g9fJJF(3yI_A$9r+lwPnWV5h3`L_*^;;jqi0U!sWX)#=l6c5+K2xD;CuQHnFNfFLI<)dwPybppjiHdN3XWUtSbxF<& z-;6$g_GL=qtQIR?j?wPQJL2myCX$9mC1tix1+uEEqMC(V^>C6yCWpe%?Tq=vx`g5? zc`D@}i~sIqH21Q36z%a&ZTl&0s5qRC0ItGy$d{BRr&`q;w$N~G3sulNf&hT6g?C>) zn%n$Kh5iGxzOA-S(Wi#tcgniykF5KD&AMq^WV0V>_dBQEA<8KtDxoBbPYhY8X{}MN zj&&?5&bqd2fh%=esOhM+y{c*tX)K~I5lgmTSe&<=#GHiuWEiASEC1MXZtLNqB#DBr zcRrkzNPLFyIYeW!Tnd`+I5d}QT?^OO99}&ayzC^BrDtrAe!yA^S+>|*-;6s#v#x48(i&y~V_!;d3&&lc%15=28QGxs zcA)TxVs=j)5)ap%1o0h=a4rPE$%?#15iGbIPkQmxQQIB&l#Rn~n4 zMFhqs8|+ycM>+ko8~Q)AgxiKK^Dvm-LGkUZ(upd0J2<22oqOsf92LG-Q4|_UGfpZk zj3{L*=^nO?Zqpioe#I{2x zq!hHW8_v5a-nH7Z8)`q6q}xJ0%`uw_cbg*gyl@7C4DW*bw7sP1bb!y6TP$YyqLPV4 z_$UbtM%0x%V9#aSj^CZGwEOr(KAUH`7td*YKRG@+Iel|{^c#DqQU5>f#j9;x82|tp Cz+*1} literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/M09-ambiguous.diff b/agents/goldie/work/queue-265/logs/M09-ambiguous.diff new file mode 100644 index 000000000..06620fcd5 --- /dev/null +++ b/agents/goldie/work/queue-265/logs/M09-ambiguous.diff @@ -0,0 +1,10 @@ +--- broker.original ++++ M09-ambiguous +@@ -6455,7 +6455,6 @@ + for (const tag of addressed.tags) { + const candidates = new Set([this.#named(s.business, tag), tag].filter((instance) => members.includes(instance))); + if (!candidates.size) fail('unknown-addressee'); +- if (candidates.size > 1) fail('addressee-ambiguous'); + selected.add([...candidates][0]); + } + const targets = threads.filter((t) => !addressed.tags.length || selected.has(t.instance)); diff --git a/agents/goldie/work/queue-265/logs/M09-ambiguous.log.gz b/agents/goldie/work/queue-265/logs/M09-ambiguous.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..854c93da13e2f7a9f0ecfa5e13af9529fdaf72db GIT binary patch literal 1679 zcmV;A25|WwiwFP!000021HD*FbK5o$zUx`W4Fq6!zkOgIykaf+RJ6noi5KQUn1> z4~DI-A=D!!+nN(X!#oO42=Pg0xP}cbY2Usxw6MMQ2!b#>!H2V>o|srnFcJ$*OC!Vty2#C3GJ6oQG_|0^d)vfUz>Aen7*J za-PgtSp+;{i$xqQ7M_nVo+ogT{mglb^^{H*dLVbE1{19o2A2 zjMA+ktg1-6(wvpNBtjZMUT`pZ0b4*pO1@xS)xr*wB`5(NF{A)0uBU1vfvBf86SXFk zOphplkm+;^zhws&2hFZ)lM_F7(jZK;1PADJLv@j zo1u4iQa1wfT-Or5SRg9I9|Qg$VewRSN0}G;=}XWrl;&b7r$emnp+hpR!-0&R(j?2$ z@MV73XeF1^`}DAfD(Sc?hjMx{=LD2S`@LlcVUU*TCCB(BYrZ`pa}D*kU1>y-{wI;+*2$cZdSUo{&L}#q zp-&*CFipj_M6#Njp=dQ&%Sww7{ux!>a-zUxr=Sj;R;+;2hlH5XI=Pk*q_%K+V2h&( z7*Cd-llWc|J|E(YRD8*bfv>G1B_;{<3&2y5u=Oq?!FM)U?^>HvBKrDcPX^@1LZ1L7 zLEW)yIF^iYpQnzOq)9O1^GX%=9&CNrMz(?N3|q~)acgCmD5mf(i}lbqP9esyUu<9t z`a>k2+`Fti_6)EPk-P(+7kB9q26e`e1YsN-+@mK>pSw1#uV>D zF9D{rFrX2GcZ8c(@tpiUwG4)Q^>!gDp1bbR3>OAD_1{^MGixk~uip6?)8e)UyuTbD z0}Z1*xX0k=PJWQ*W-E)U0!&5TO0*`!jq8` z!0+L(0<&hXcxa2xYjb{TEJ;CC-`}qRvn}8fx|arPSTFsAG?XVh}U%1vC`USimga>%ALXjwoh)vWXne&ypZIzzA#30h}l?+OX?Ih&a1ia0VNN zRzUE!tZv|}VIYoMj6xPwSArrO#VcDbLFy+5sJ{CuVucl~ z>BCWWHbB(^LKUK~#CNC#eoet%O7lWA0zI+ouxav0+gD&Zs$dkrxa21hr3YwuXF(?W z4{)}R-S! { + const session = this.#defaultSession(t.id); + this.#sessionFence(session); +- this.#checkMessaging(s.business, 'human', t.instance); + return session; + }); + const at = this.#now(); diff --git a/agents/goldie/work/queue-265/logs/M10-messaging.log.gz b/agents/goldie/work/queue-265/logs/M10-messaging.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..e129b074138f6a2aad3d2ac409ce277916a55198 GIT binary patch literal 1693 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 !addressed.tags.length || selected.has(t.instance)); + const sessions = targets.map((t) => { + const session = this.#defaultSession(t.id); +- this.#sessionFence(session); + this.#checkMessaging(s.business, 'human', t.instance); + return session; + }); diff --git a/agents/goldie/work/queue-265/logs/M12-fence.log.gz b/agents/goldie/work/queue-265/logs/M12-fence.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..d73d7a94e30e260af09375bfb5dc60845028e74b GIT binary patch literal 1678 zcmV;9266cxiwFP!000021HD*VZ`(E$e$THUu!prkESb96>N=onGoZk_7D@K7r+}tt zo3$jWq}0^Ie*C^e$+>j)lC;TQ44LFP=Q|gk3(rKy-ph_f37aNGoD?Z%f1JN&(KO1A zSQL*-earZim166T8OKU;%vi*Frz{p&WkkuuXJy4o6)X;7evDs^-zb^Um0qoZZU=}- zQ&rlB1{0mBH6hrNPSGu$?oYZGEl&}%a~@~khL-GM4?~R)LH#ef{W#+wOVT(`?uC;= zZQ9NE#&)A&w?n9;_3WhsBtM3t2OQ< zu3~G=MLI#Dd*|b>FE_H!Vo5x%5iUcggC15_!nc^DO4k z-PV!4wP+7msa;!%Eo(%r+*q<&s$``{h=0yhpA|E3*$b$H-AYL8-Xx@a);F65G3v|a z6t;LW0f$m$o@RM+cd8VuQY#@xzP^T(lq1M5fM<}d?JgqWJD;lSgrMT_Q}I9K?|h!lXLqNl(Rv6dsz8$wfGA5#>3j4HIb>p*YReV|J)?sv=uSZZ zz|Ns9ym`wxbrO%vc7G9>22qqm`Q1&%z>ch4sz&1;pF zQ7Y0`7xV=+c;*uE=lX@idDm%leAGP;T2oW<)N&5?T1hgW-6zDaI&qI^^onoVokw%I zHkI-@`o&dD3fXCRWrRP#5mKrae!&q&$|pX+ADjDrb>~5vq$peeR<|_jjm?Jo(ju1OSoMX}1I~bsNl@X`$?56EtFyC{)AP6Qf2Vay z6Ig$R>tgBf39<8hM?M9!tlwg zmc#{*o_mq!-ck)!vfw8w_1hX5?&qh+z;j;2*BAoZH*cF)ZrjK+2~)9W4VhBV!o}K{ zjVq!kD|m97WIU#!fJH_2qAswGCd_|>U>X%sdV>mGGH!tTfVhWe#@p!bWHiqaX|tPr zjO$MCgCI?!g3lj}JIk+}H&c<8-;3 znul>??0u=a2qZ~#6X+^1h7Xx|H?usUn7x@Po(3siFQ)e#dOf<0QUIq*Dg)H=5=0tX zJvc|5LZ?wxI#IXSYX!t9k5MPsl1Fqv)Hc>lfr*)9DaTf(7vZWiZL{t(r74<^E96(5^Z0K${@1F{;)t=o_`>7=DcXkx;B+3pwMe!iu zGZ_-uv4Vva8=pp4@~5*oaNmHvR+=(ZidJ5w6}aYH_vprzdaNV?8JS123?+_q`PW0AF565&!@I literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/rerun-00-sandbox.log.gz b/agents/goldie/work/queue-265/logs/rerun-00-sandbox.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..cd28ae52d644b7ef525af7335f60cdedb61734e4 GIT binary patch literal 935 zcmV;Y16ceYiwFP!000021I1R`ZreBzefL)k(1*NOvM!cvxfe7@z1sl2q>c+L_NAaC zDq<~>0!i8N-*<*~oD^{2Vt3tr5vZXwGv}O{A#a(5&xM6(48eF7hqE|=ugfclf+!t8 z6z@%a2Vnpu+nOPS<5?080V3!P*Jyx7u@cytYj($H5c$)1h|esf=Oi9neVAV^2Fs5( z@2(fGN3FCYV-DI z@4xp8;CUWC%O24oj&H4TtW2iKI6}MKc1Y6&p}N3V-}j%wG#DpW_cvPQ4R1lR7Gp4I zg)u_jLB7$fbGfkn+EShs6OAE65hD6GE{-N227VMzvq^X|dyd*|As6V}V6`BL+n0{D zyq9IeT~veYk-U{a15&pI%~|OwiKHw1|ABNUh2{m8%9en|2<%MWk7M?eC`=}&1=DH+ zX@Xon6h^DczTp?N=p~kg%l9z}R@r?PtYjUohrn4;!$#QJnGgTtKSoIcKSuCpkMj%- zQIMqR_#_RB`4?~belfp%=S7&Lttk_rPUkK&Y7}!&=Rm&G?5bgX$-!zSaU_V&;#48K zRJNvyZP5wQkWjmxJI+xW0&L%LlAdk=Hz5>m8Mvd#po$f@G*)sHsRXCYrsfiN*IW*t z>V?}muLuV@*=S)I_U{f9p-&P0x!gYkIt`;=1x@LQl1nS>mJ%YHkl28-z#2oIExdYo zfAjWL-s3Dnk>2>NGE5Y{kZab6awo`sf?evnHA1NHpfRp)RgXd3#F^H`xvh}~kKTcbgjr}Z2Q@UrIWX_E?cS`a5P8oNck*1|5u*fOu;dFb?_c(ULh@&f)wh<~R%|{&YIY;^-e#%PvI}0|VkGTzf?${Pw${vfouJ zp6Cyo!^3^W;PH<-ix#kqjVSrv>Pr1_y5RlJ`^{00UzD=Y57Hz^lH(kOz8?n26xj^8 zrRfE}0WCXb_C}J%nF?zCrolAbw=2R3kx^71r`DcGfuNGf-k!(V1&gUFn$Vk8YqE6 zyqE>hFpKB{fI(+uivg$_QGoa%Td|iJupkN-*rr39Q19yVW_{=Fu5UkX?=F|MvP)x| ze(ciZt+4rFX=}aQrp4p+#@nrL0W+DhQ9!x(0q(m8D~-)Si`K|>QMA&S3>qc9<_ReH z69Rzm``8v8=EqFmY7}TdNgT2SiPy6hTzFir7q4 zE4381hw%~Yq&aXTS;gT@nyy5tdRRDu9VI6#OcFj5h9|CjRy1M_iVKw{X+&qDHaDNZ zihWOuN3^r(1QNpE1FVFxXKFG@eI4OK$16_f-k3^?qEvf$K9neHkq?g|9ThM!&UtYo zKKF2ORR-T(HN2D62>x4k?s}X=@l2?!wH<(HO#Y9Njg7?0<2O3aRqrMeWV+J#!t!GW06uI9?jyJ;$2+n1P{dy8ea&!LAnO6nqqAHH31Za#>Ya pRsUt4O07?Q+Z4^v`2!D87{okGY2t0ZZg-c&`vrm_u4+jL008_U7%l(+ literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/rerun-02-rooms.log.gz b/agents/goldie/work/queue-265/logs/rerun-02-rooms.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..dc4e39613ab20f1231f2e00f3cee261831a7c74d GIT binary patch literal 1213 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%0AIMMAWTeDihyU>E$t3H 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 literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/rerun-04-mutants-driver.log.gz b/agents/goldie/work/queue-265/logs/rerun-04-mutants-driver.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..c9689a2f89f309dfc6c9865379cb92209299005d GIT binary patch literal 270 zcmV+p0rCDHiwFP!000021I5%`Zo?o92k`fuA{TH;(zW}La)i9?eImr8G=Mt{%69u@ z4UKXG9uV`A4-Q3j3ib28TA*nNbAl_lMY3po_mnQXkGIK-ov zDNHdSvT(%GDBvj7BsAI4AOxD*^GQgJK5{PJN5pr+gz(>7_Oj?7g2VEB>gyIFa>P&& z^dMx>5pIF5sA56VX2_;zaOegMT+p-`vgrhhtTk+?WSVx0>^cM8uq0^(WX%f8eGjLNGATgl0q)CYgeBNCFK_m@;&{JqofDzQ} zMXvzIWfHFdY*h2!2B4L!2KJrzY|l%e5k@QfMA-^Rl+)nq<92fw>^|MTzrMR%cfzc- zk#6o>QJeCF{;W1P^}&&V7&baD`e+dtolIU4BUz#JBu zPRZUtZTq&Uxu}kn>e}C1zV)~z6d^?B-Qp<1iS_Ja8pfd>T!{j*L&fwd_>DE~7^;}4 sc-vZ6?oB^6N}a|=)^Z&DfrliHk~}M78f?E@?=DgB6CPe}3`__B0DT22-~a#s literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/logs/rerun-05-restored-rooms.log.gz b/agents/goldie/work/queue-265/logs/rerun-05-restored-rooms.log.gz new file mode 100644 index 0000000000000000000000000000000000000000..ae12d5cc0f67ffe5f16453035e1fe477c6f1f47a GIT binary patch literal 1217 zcmV;y1U~y8iwFP!000021HD&GkJ~m7z57=T&_gb^Eb3cc;FDRSPMd7K%3;SPSS97G9($tq4)jKOcW?;#4KYz9$0 z4)qp56ZP z>Bo$s`}!l`fwS3oT`yl)(ia8-j5h}J@dtAttTgTh6_YCF?= zV6b>a0|1M~0)Ois`69F5Tf0J+2P`YXGRFyb?9g*>i0B)94T4~rd1u6?k=q@jI{|`9 zH;p8JA!4UnNeGU_DSE`|@}-k#SsLVVoaN6%Oa3tDp~mN+{@c29IJ2ZE)5~y@)YcYb z_h&DSz<3GR^(|LJNR?IsB-#X8fjH=Ef}4zRpR;^g3tCQJw*L}FLo3=fnqBueFD$B)u&4jTe)T5P49cJ^lOl?qWMGA=mvk;pw)vg)ilfgc zx+kj#>2|tzAT}F9Mffws|6jJ4R!ttHERLe$Ip{aq2)R{@QL7hl$fr46xzRL}B4A~i z73Fi79E?`m#eI6XfJ!k<<=UO5xs*W~v4XM7at^@&$IVudeqk?;b66X!O%=B|ax&@o zc1+orXRv~O!>p~1+)9P;ocQkioHjKMm?Li8JF%3i!=*+aJn8b3uKp*J(;Kb>Gl=b@gc1T9AUysi!9?=dhGkA+sv5!SkvIM@j6;BW!r zwHBMRhliX|EAhhHp3`&^m6(d3BspwH&aQ=$c#N=Lr25<7!5dE`o}H$#u;$g?PoYAo zO5dH&8|v`%0p(}=wZ-qPli2bdwAl}=sVjMHJJX@gf-+CjGP^+G6?)hZK96XO%0^JD z>d_o_x)DA_-`q)(S59J7M)(69UR9zS!<~3-zx2-25obY~6>)iCj`vk&iwUx$qcT{Z zLx;k`037cl<3FLcy*_p4Lt8VJSQ0VESYXb=+=cD_!28r2y`q^(C&X!xZt(VXxYrK*~~Mj`?`z$4CC>a0Eg>=FN$wlGZ{ zuZTsO;x+Md>ZgmBH&*d(kfZ9oK=lTtit4NB92!X%Hq<6YrjnhcNSul|%OA0QflVg~ zrg+bb%OuIND;VB+kSjpZkpV1~$Dy!L-573`qqoN<>(p%!QaZNM4d44K$vy4j5$)Hq zG=139AkMNlJaf%qLBI-h2#s0rkG7X|)eiBo<8~a}aM}2wiqPPFyY_E(FS~AhcDmO7 f;emZ9OBNJ)j(@WcUq9Zy4QGD?Q?$Lr{}2EGqgiP% literal 0 HcmV?d00001 diff --git a/agents/goldie/work/queue-265/mutants.py b/agents/goldie/work/queue-265/mutants.py new file mode 100644 index 000000000..6cc7f956e --- /dev/null +++ b/agents/goldie/work/queue-265/mutants.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +"""Slot-only runner. Every mutation restores and verifies the complete broker bytes.""" +from pathlib import Path +import hashlib, os, re, subprocess, sys + +ROOT = Path(__file__).resolve().parents[4] +SOURCE = ROOT / 'packages/bus/src/broker.mjs' +OUT = Path(__file__).resolve().parent / 'logs' +MUTANTS = [ + ('M01-human', 'human-required', 'room verbs require the human', ' this.#human(s);\n', ''), + ('M02-tester', 'tester-refused', 'room verbs require the human', None, None), + ('M03-project', 'project-not-found', 'room verbs refuse missing projects', " if (!this.#store.get('SELECT 1 FROM projects WHERE id=? AND business=?', project, s.business)) fail('project-not-found');\n", ''), + ('M04-members', 'thread-instance-missing', 'room verbs refuse missing projects', " if (!members.length) fail('thread-instance-missing');\n", ''), + ('M05-collision', 'room-thread-name-taken', 'room.open preflights instance collisions', " if (t && (t.instance !== instance || t.owner !== owner))\n fail(opening ? 'room-thread-name-taken' : 'room-not-open');\n", ''), + ('M06-open', 'room-not-open', 'send/read refuse a missing canonical member', " if (!t && !opening) fail('room-not-open');\n", ''), + ('M07-body', 'invalid-request', 'unknown or non-member addressees and tags-only bodies', " if (!addressed.body.trim()) fail('invalid-request');\n", ''), + ('M08-unknown', 'unknown-addressee', 'unknown or non-member addressees and tags-only bodies', " if (!candidates.size) fail('unknown-addressee');\n", ''), + ('M09-ambiguous', 'addressee-ambiguous', 'a legacy name colliding with another member key', " if (candidates.size > 1) fail('addressee-ambiguous');\n", ''), + ('M10-messaging', 'message-sender-refused', 'messaging denial on the last target', " this.#checkMessaging(s.business, 'human', t.instance);\n", ''), + ('M11-cursor', 'message-not-found', 'room.read groups one send, pages', " if (after === undefined) fail('message-not-found');\n", ' if (after === undefined) after = 0;\n'), + ('M12-fence', 'session-clearing', 'a clearing last member fences the whole send', ' this.#sessionFence(session);\n', ''), +] + +def sha(data): return hashlib.sha256(data).hexdigest() + +def main(): + OUT.mkdir(exist_ok=True) + original = SOURCE.read_bytes() + text = original.decode() + start = text.index(" case 'room.open':") + end = text.index(" // A thread belongs", start) + block = text[start:end] + for name, refusal, expected, old, new in MUTANTS: + if old is None: + needle = 'export const TESTER_VERBS = Object.freeze([' + assert text.count(needle) == 1 + changed = text.replace(needle, needle + "\n 'room.open', 'room.send', 'room.read',", 1) + else: + assert block.count(old) == 1, (name, block.count(old)) + changed = text[:start] + block.replace(old, new, 1) + text[end:] + # Save conventional original→mutant diff without relying on shell interpolation. + import difflib + (OUT / f'{name}.diff').write_text(''.join(difflib.unified_diff(text.splitlines(True), changed.splitlines(True), fromfile='broker.original', tofile=name))) + tmp = subprocess.check_output(['mktemp', '-d', '/mnt/storage/scratch/tmp/XXXXXX'], text=True).strip() + env = {**os.environ, 'TMPDIR': tmp} + log = OUT / f'{name}.log' + try: + SOURCE.write_text(changed) + with log.open('w') as stream: + for command in [['date', '-u'], ['uptime'], ['bash', '-c', 'bash /mnt/storage/scratch/sage-busy-now.sh 2>/dev/null | tail -1']]: + subprocess.run(command, cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT, check=True) + stream.write(f'TMPDIR={tmp}\nmutant={name} refusal={refusal} original_sha256={sha(original)}\n') + stream.flush() + result = subprocess.run(['timeout', '-k', '10', '120', 'node', '--test', '--test-reporter=tap', 'packages/bus/tests/rooms.test.mjs'], + cwd=ROOT, env=env, stdout=stream, stderr=subprocess.STDOUT) + output = log.read_text() + killed = result.returncode == 1 and re.search(r'(?m)^not ok \d+ - ' + re.escape(expected), output) + print(f'{name}: exit={result.returncode} target_killed={bool(killed)} log={log}', flush=True) + if not killed: return 1 + finally: + SOURCE.write_bytes(original) + assert SOURCE.read_bytes() == original + assert sha(SOURCE.read_bytes()) == sha(original) + with log.open('a') as stream: stream.write(f'RESTORED sha256={sha(original)}\n') + return 0 + +if __name__ == '__main__': sys.exit(main()) diff --git a/agents/goldie/work/queue-265/pin-context-grep.txt b/agents/goldie/work/queue-265/pin-context-grep.txt new file mode 100644 index 000000000..2b5e06287 --- /dev/null +++ b/agents/goldie/work/queue-265/pin-context-grep.txt @@ -0,0 +1 @@ +No changed-file mention has a literal 64-hex digest within eight lines. diff --git a/agents/goldie/work/queue-265/pin-context-with-sandbox.txt b/agents/goldie/work/queue-265/pin-context-with-sandbox.txt new file mode 100644 index 000000000..163dbc9ee --- /dev/null +++ b/agents/goldie/work/queue-265/pin-context-with-sandbox.txt @@ -0,0 +1 @@ +No changed-product-file mention has a literal 64-hex digest within eight lines. diff --git a/agents/goldie/work/queue-265/pin-positive-control.txt b/agents/goldie/work/queue-265/pin-positive-control.txt new file mode 100644 index 000000000..ca74f0d18 --- /dev/null +++ b/agents/goldie/work/queue-265/pin-positive-control.txt @@ -0,0 +1,6 @@ +packages/bus/src/store.mjs:15:const ddl = readFileSync(new URL('../schema.sql', import.meta.url), 'utf8'); +packages/bus/src/store.mjs:16:export const SCHEMA_SHA256 = 'a2ba3a46f12e56139ecae9e55227d00847842aedec50c1d92aaae28844ca48e7'; +packages/bus/src/store.mjs:106:const hex = (value) => createHash('sha256').update(value).digest('hex'); +packages/bus/src/store.mjs:107:if (hex(ddl) !== SCHEMA_SHA256) throw Error('schema-source-mismatch'); +packages/bus/tests/schema.test.mjs:17: db.exec(readFileSync(new URL('../schema.sql', import.meta.url), 'utf8')); +packages/bus/tests/schema.test.mjs:90: const hex = (s) => createHash('sha256').update(s).digest('hex'); diff --git a/agents/goldie/work/queue-265/reader-grep.txt b/agents/goldie/work/queue-265/reader-grep.txt new file mode 100644 index 000000000..31f481627 --- /dev/null +++ b/agents/goldie/work/queue-265/reader-grep.txt @@ -0,0 +1,133 @@ +packages/bus/tests/session-compactions.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/console-decide.test.mjs:14:import { Broker, CONSOLE_VERBS } from '../src/broker.mjs'; +packages/harness/tests/runner.test.mjs:14:import { Broker, BusError } from "../../bus/src/broker.mjs"; +packages/bus/tests/project-files.test.mjs:8:import { PROJECT_FILE_VERBS } from '../src/broker.mjs'; +packages/cli/tests/lifecycle.test.mjs:19:import { BusError } from "../../bus/src/broker.mjs"; +packages/bus/tests/lifecycle-verbs.test.mjs:11:import { Broker, LIFECYCLE_REQUEST_MS, TESTER_VERBS } from '../src/broker.mjs'; +packages/bus/tests/lifecycle-verbs.test.mjs:74: for (const verb of ['instance.launch', 'instance.end', 'instance.request']) assert.ok(TESTER_VERBS.includes(verb), verb); +packages/bus/tests/lifecycle-verbs.test.mjs:75: assert.equal(TESTER_VERBS.includes('instance.regenerate'), false); +packages/bus/tests/tasks.test.mjs:9:import { Broker, BusError, TASK_VERBS } from '../src/broker.mjs'; +packages/harness/tests/tools.test.mjs:4:import { ORGANIZATION_KEYS as BROKER_ORGANIZATION_KEYS, TASK_PAGE, TASK_PAGE_MAX } from "../../bus/src/broker.mjs"; +packages/seat/tests/session.test.mjs:11:import { Broker } from "../../bus/src/broker.mjs"; +packages/bus/tests/decision-route.test.mjs:12:import { Broker } from '../src/broker.mjs'; +packages/cli/tests/thread-launch.test.mjs:19:import { BusError } from "../../bus/src/broker.mjs"; +packages/seat/tests/sandbox.test.mjs:15:import { Broker } from "../../bus/src/broker.mjs"; +packages/bus/tests/host-run.test.mjs:16:import { Broker, ORGANIZATION_KEYS } from '../src/broker.mjs'; +packages/bus/tests/host-run.test.mjs:181: // organization.set reaches the writer as limits.set (broker.mjs:1379). +packages/cli/tests/helpers.mjs:10:import { BusError, Broker } from "../../bus/src/broker.mjs"; +packages/tasks/tests/fields.test.mjs:10:import { TASK_VERBS } from '../../bus/src/broker.mjs'; +packages/tasks/tests/fields.test.mjs:226: // decision back to that role (broker.mjs, decision.raise). +packages/webui/tests/instances.test.mjs:15:import { BusError } from '../../bus/src/broker.mjs'; +packages/cli/tests/tester-threads.test.mjs:14:import { BusError, Broker } from "../../bus/src/broker.mjs"; +packages/bus/tests/staff-request.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/tasks/tests/world.mjs:5:import { Broker } from '../../bus/src/broker.mjs'; +packages/cli/tests/processing-cli.test.mjs:7:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/grant-host.test.mjs:10:import { Broker, registrySha256 } from '../src/broker.mjs'; +packages/business/tests/workflow-roles.test.mjs:115: // Q169 (broker.mjs END_PROTECTED, #hardWait): revoking the assistant is a hard wait as well. +packages/business/tests/workflow-roles.test.mjs:136: // sage-0709: only recordLand spends a decision (broker.mjs #spent). checkLand refuses decision-consumed after +packages/cli/tests/thread-revoke.test.mjs:18:import { BusError } from "../../bus/src/broker.mjs"; +packages/bus/tests/tester-writes.test.mjs:10:import { Broker, TESTER_VERBS, TESTER_ORGANIZATION_VERBS } from '../src/broker.mjs'; +packages/bus/tests/tester-writes.test.mjs:18:test('row 175: TESTER_VERBS and the organization branch tester set are pinned', () => { +packages/bus/tests/tester-writes.test.mjs:19: assert.deepEqual([...TESTER_VERBS], [ +packages/bus/tests/tester-writes.test.mjs:32: assert.ok(Object.isFrozen(TESTER_VERBS) && Object.isFrozen(TESTER_ORGANIZATION_VERBS)); +packages/cli/tests/stack-release.test.mjs:1993: for(const [f,text] of [['packages/cli/src/cli.mjs',id===A?'// fixture host from before row 163\nprocess.exit(1);\n':script(rHost)],['packages/webui/src/cli.mjs',script(rConsole)],['packages/bus/src/store.mjs',rStore(v,froms)],['packages/bus/src/migrate-schema.mjs',script(rMigrate)],['packages/bus/src/broker.mjs','export class BusError extends Error { constructor(code) { super(code); this.code = code; } }\n']]){mkdirSync(dirname(join(d,f)),{recursive:true});writeFileSync(join(d,f),text)} +packages/cli/tests/session-cli.test.mjs:94: const { Broker } = await import('../../bus/src/broker.mjs'); +packages/cli/tests/session-launch.test.mjs:21:import { BusError } from "../../bus/src/broker.mjs"; +packages/cli/tests/revoke-window.test.mjs:19:import { BusError } from "../../bus/src/broker.mjs"; +packages/bus/tests/chief-of-staff.test.mjs:10:import { Broker, ACTIONS } from '../src/broker.mjs'; +packages/cli/tests/instances.test.mjs:13:import { BusError } from "../../bus/src/broker.mjs"; +packages/cli/tests/thread-cli.test.mjs:14:import { BusError, Broker } from "../../bus/src/broker.mjs"; +packages/bus/tests/processing.test.mjs:6:import { Broker } from '../src/broker.mjs'; +packages/cli/tests/idle-stop-race.test.mjs:17:import { BusError } from "../../bus/src/broker.mjs"; +packages/cli/tests/tester-reads.test.mjs:12:import { BusError } from "../../bus/src/broker.mjs"; +packages/cli/tests/session-clear.test.mjs:18:import { BusError } from "../../bus/src/broker.mjs"; +packages/bus/tests/names.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/cli/tests/compactions-launch.test.mjs:24:import { BusError } from "../../bus/src/broker.mjs"; +packages/cli/tests/tester.test.mjs:7:import { BusError, Broker } from "../../bus/src/broker.mjs"; +packages/bus/tests/reload.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/agents.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/end-launch.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/webui/tests/decide-browser.test.mjs:14:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/credential-verbs.test.mjs:11:import { Broker, CREDENTIAL_VERBS } from '../src/broker.mjs'; +packages/webui/tests/send-browser.test.mjs:13:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/launch-notice.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/messages.test.mjs:3:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/workflow-roles.test.mjs:11:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/library-sync.test.mjs:11:import { Broker, LIBRARY_VERBS } from '../src/broker.mjs'; +packages/bus/tests/credential-status.test.mjs:12:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/gitea-grant-docker.test.mjs:15:import { Broker, GRANT_EVIDENCE } from '../src/broker.mjs'; +packages/bus/tests/thread-migration.test.mjs:11:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/comment-cursors.test.mjs:7:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/thread-claims.test.mjs:11:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/state.test.mjs:7:import { Broker, TASK_PAGE } from '../src/broker.mjs'; +packages/bus/tests/access-revoke.test.mjs:14:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/plugins-verb.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/transport.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/publish.test.mjs:14:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/publish.test.mjs:221: const { ACTIONS, HARD_WAITS } = await import('../src/broker.mjs'); +packages/bus/tests/tester-threads.test.mjs:11:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/tester-threads.test.mjs:284: // The row #specNotice (broker.mjs) writes for a human save of the spec in project stack. The save +packages/bus/tests/approval-binding.test.mjs:7:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/fire-revokes-grants.test.mjs:15:import { Broker, GRANT_EVIDENCE, registrySha256 } from '../src/broker.mjs'; +packages/bus/tests/daily-quota-runtime.test.mjs:10:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/limit-checks.test.mjs:323: for (const file of ['../src/runtime.mjs', '../src/broker.mjs', '../src/process.mjs']) { +packages/bus/tests/spec-fixtures.mjs:6:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/decisions.test.mjs:9:import { Broker, RECENT } from '../src/broker.mjs'; +packages/bus/tests/peer-transport.test.mjs:9:import { BusError } from '../src/broker.mjs'; +packages/bus/tests/peer-transport.test.mjs:47: const {TASK_VERBS,BusError}=await import('../src/broker.mjs'); +packages/bus/tests/messaging.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/rooms.test.mjs:8:import { Broker, THREAD_PAGE, THREAD_PAGE_MAX, TESTER_VERBS } from '../src/broker.mjs'; +packages/bus/tests/rooms.test.mjs:80: assert.ok(!TESTER_VERBS.includes(verb)); +packages/bus/tests/web.test.mjs:8:import { Broker, BusError, WEB_UNTRUSTED } from '../src/broker.mjs'; +packages/bus/tests/replies.test.mjs:11:import { Broker, REPLIES } from '../src/broker.mjs'; +packages/bus/tests/thread-shares.test.mjs:14:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/message-citation.test.mjs:6:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/limits.test.mjs:7:import {Broker} from '../src/broker.mjs'; +packages/bus/tests/host-fixtures.mjs:6:import { registrySha256, writeGrantEvent } from '../src/broker.mjs'; +packages/bus/tests/gitea-grant.test.mjs:12:import { Broker, GRANT_EVIDENCE, writeGrantEvent } from '../src/broker.mjs'; +packages/bus/tests/csuite-messaging.test.mjs:12:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/decision-close.test.mjs:9:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/grant-scope.test.mjs:14:import { Broker, GRANT_EVIDENCE, writeGrantEvent } from '../src/broker.mjs'; +packages/bus/tests/project-await.test.mjs:7:import { Broker, BusError } from '../src/broker.mjs'; +packages/bus/tests/launcher-released.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/limit-stop.test.mjs:12:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/message-filter.test.mjs:12:import { Broker, REPLIES } from '../src/broker.mjs'; +packages/bus/tests/land.test.mjs:18:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/single-use.test.mjs:7:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/session-clear.test.mjs:10:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/grant-migration.test.mjs:10:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/usage-broker.test.mjs:7:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/project-runtime.test.mjs:13: const source = readFileSync(new URL('../src/broker.mjs', import.meta.url), 'utf8'); +packages/bus/tests/task-read.test.mjs:7:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/library.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/instances-verb.test.mjs:11:import { Broker, LIFECYCLE_HUMAN_VERBS, ORGANIZATION_KEYS, TESTER_ORGANIZATION_VERBS } from '../src/broker.mjs'; +packages/bus/tests/routes-verb.test.mjs:13:import { Broker, ORGANIZATION_KEYS } from '../src/broker.mjs'; +packages/bus/tests/broker.test.mjs:10:const { Broker } = await import('../src/broker.mjs').catch((e) => { +packages/bus/tests/grant-enroll.test.mjs:10:import { Broker, BusError, writeGrantEvent, registrySha256 } from '../src/broker.mjs'; +packages/bus/tests/hard-waits.test.mjs:7:import { Broker, ACTIONS, HARD_WAITS } from '../src/broker.mjs'; +packages/bus/tests/requirements.test.mjs:10:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/grant-executor.test.mjs:15:import { Broker, registrySha256, writeGrantEvent } from '../src/broker.mjs'; +packages/bus/tests/sessions.test.mjs:10:import { Broker } from '../src/broker.mjs'; +packages/bus/tests/user-principal.test.mjs:14: Broker, ACTIONS, USER_VERBS, TESTER_VERBS, TASK_VERBS, WEB_VERBS, HOST_VERBS, HOSTS_VERBS, CREDENTIAL_VERBS, +packages/bus/tests/user-principal.test.mjs:16:} from '../src/broker.mjs'; +packages/bus/tests/user-principal.test.mjs:137: ...ACTIONS, ...TESTER_VERBS, ...TESTER_ORGANIZATION_VERBS, ...PROJECT_FILE_VERBS, ...LIBRARY_VERBS, ...CREDENTIAL_VERBS, ...HOSTS_VERBS, +packages/bus/tests/tester.test.mjs:10:import { Broker, TASK_VERBS } from '../src/broker.mjs'; +packages/bus/tests/threads.test.mjs:9:import { Broker, THREAD_PAGE } from '../src/broker.mjs'; +packages/webui/tests/routes-browser.test.mjs:15:import {BusError} from '../../bus/src/broker.mjs'; +packages/bus/tests/creative.test.mjs:8:import { Broker } from '../src/broker.mjs'; +packages/webui/tests/granted-user.test.mjs:16:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/task-page.test.mjs:7:import { Broker, TASK_PAGE, TASK_PAGE_MAX } from '../src/broker.mjs'; +packages/webui/tests/user-option-swap.test.mjs:14:import { Broker } from '../../bus/src/broker.mjs'; +packages/webui/tests/board-held.test.mjs:20:import { Broker } from '../../bus/src/broker.mjs'; +packages/webui/tests/chat-sessions-access.test.mjs:10:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/review.test.mjs:14:import { Broker } from '../src/broker.mjs'; +packages/webui/tests/sso-browser.test.mjs:14:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/revoke-window.test.mjs:13:import { Broker } from '../src/broker.mjs'; +packages/webui/tests/bus.test.mjs:13:import { Broker } from '../../bus/src/broker.mjs'; +packages/bus/tests/viewer.test.mjs:13: Broker, ACTIONS, USER_VERBS, VIEWER_VERBS, BOARD_VERBS, TESTER_VERBS, TESTER_ORGANIZATION_VERBS, PROJECT_FILE_VERBS, +packages/bus/tests/viewer.test.mjs:14:} from '../src/broker.mjs'; +packages/bus/tests/viewer.test.mjs:116: const others = new Set([...ACTIONS, ...TESTER_VERBS, ...TESTER_ORGANIZATION_VERBS, ...PROJECT_FILE_VERBS, ...BOARD_VERBS, 'no.such.verb']); +packages/webui/tests/tester-fixture.mjs:12:import { Broker, BusError } from '../../bus/src/broker.mjs'; +packages/webui/tests/routes.test.mjs:12:import { BusError } from '../../bus/src/broker.mjs'; +packages/webui/tests/chat.test.mjs:191: const { Broker } = await import('../../bus/src/broker.mjs'); +packages/webui/tests/bus-browser.test.mjs:11:import { Broker } from '../../bus/src/broker.mjs'; diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index 18280f3dc..ddb328720 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -1623,3 +1623,5 @@ are never rewritten or removed; corrections are new entries. 2026-10-24 | Poe | Q246 / mos-1566, row 208 / 193d (#1706), poe/row208 | Started; approved design hash verified; implementation and isolated acceptance pending. 2026-10-24 | Poe | Row 208 / 193d (#1706), poe/row208 | Builder acceptance green: webui 418/418, plugins 119/119, four UI mutants killed with bus bypass proofs; candidate prepared for Gladstone then Duckworth guard review. 2026-10-24T04:29Z | Duckworth (Opus 5.5) | row 208 (193d) second review, guards only, on 4a4bef6c1 (sage-3934) | APPROVE (static), no bus change, every hidden control has a broker refusal, grant hint per-grant and self-only, N1 5 s poll (duckworth-0302) | +2026-10-24T04:27Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row265 / #1770 C2-09b rooms | Goldie owns build, Boyd reviews under sage-3915. New goldie/row265 worktree at ec86f2c84, claim rev3814; room verbs/parser/new tests prepared, no old tests changed. Sage-3932 slot: new parser14/14 and rooms18/18 passed; whole bus in progress before refusal mutants, stop rule active. +2026-10-24T04:35Z | Goldie (a13dd6d5-5e73-4b7d-8318-02abeff24940) | Row265 / #1770 verified | First slot stopped at project-runtime import pin. mos-1567 narrowly authorizes pin and pure-source mount correction. sage-3942 rerun: sandbox10/10, parser15/15, rooms18/18, bus957/957, twelve refusal mutants killed/restored SHA71b32ee4, parser15/15 + rooms18/18 again. Slot returned goldie-0034; no further test runs. Boyd reviews RUNNER_FILES alongside rooms; own-branch push/claimant in-review next. diff --git a/packages/bus/README.md b/packages/bus/README.md index 2b3142bae..7d5ae43e7 100644 --- a/packages/bus/README.md +++ b/packages/bus/README.md @@ -242,6 +242,9 @@ a receipt with empty `changes`. A refusal is `action.refused` with its code alon | `replies` | `{id}`: a message UUID; human and reader sessions only. The messages whose `in_reply_to` is that id, oldest first, at most 50. Writes nothing. | | `project.create` | `{name,repo?}`; human sessions only (row 121, #1615). `repo` must name one of the business's `projects` (`unknown-repo`); a second project with the same name refuses `project-exists`. Returns `{id}`. | | `project.list` | No args; human sessions only. The business's projects, oldest first. | +| `room.open` | `{project}`; human only. Creates/reuses the caller's canonical member threads, named by sorted `THREAD_DEFINITIONS` instance keys. A taken name/owner/instance refuses `room-thread-name-taken` atomically. Returns `{project,threads:[{id,instance,name}]}`. | +| `room.send` | `{project,body}`; human only, room must be fully open (`room-not-open`). Leading whitespace and `@name` tokens (including a final EOF tag) address current display names or member keys; no tags broadcasts, repeats send once. Unknown/ambiguous members refuse `unknown-addressee`/`addressee-ambiguous`; tags-only refuses `invalid-request`. Stores the original body, one normal message/route/human.input per target in one transaction, with one shared message timestamp. Returns `{ids,to}` in member-key order. | +| `room.read` | `{project,after?,limit?}`; human only, complete owned room. Oldest first across all sessions of member threads. Returns entries with first-message fields plus `thread`, `session`, `instance`, `ids` and `to`. Only consecutive human rows with equal at/body/class and distinct instances merge; repeated instances split identical sends. `limit` counts merged entries (default 50, 1–200). Continue after the last entry's last `ids` element; an `after` outside the room refuses `message-not-found`. No tester access or schema change. | | `thread.create` | `{project,name}`; human sessions only. The thread belongs to the caller and to the business's one thread instance (Projects and threads, below). Returns `{id,instance}`. Refuses `project-not-found`, `thread-exists`, `thread-instance-missing` or `thread-instance-ambiguous`. | | `thread.list` | `{project?,shared?}`; human sessions only. The caller's own threads, oldest first. With `shared: true` (row 206), the threads others own that the caller may read (Thread shares, below), each row adding `owner`. | | `thread.open` | `{thread,session?}`; human sessions only. Records a `thread_opens` row, which asks the launcher to start the thread's session. Returns `{opened}`. | diff --git a/packages/bus/src/address.mjs b/packages/bus/src/address.mjs new file mode 100644 index 000000000..d667b75ee --- /dev/null +++ b/packages/bus/src/address.mjs @@ -0,0 +1,14 @@ +// C2-09b: a pure leading-address parser, shared with the room UI's parity test. +// The remainder is for empty-body checks; the broker always stores the original input. +export function parseAddress(input) { + if (typeof input !== 'string') throw new TypeError('body must be a string'); + const tags = []; + let body = input.trimStart(); + while (true) { + const token = /^@(\S+)(?:\s+|$)/u.exec(body); + if (!token) break; + tags.push(token[1]); + body = body.slice(token[0].length); + } + return { tags, body }; +} diff --git a/packages/bus/src/broker.mjs b/packages/bus/src/broker.mjs index 58dff6b09..163a7ec65 100644 --- a/packages/bus/src/broker.mjs +++ b/packages/bus/src/broker.mjs @@ -1,4 +1,5 @@ import { randomUUID, randomBytes, createHash } from 'node:crypto'; +import { parseAddress } from './address.mjs'; import { isAbsolute, dirname } from 'node:path'; import { initializeControl, processingStatus } from '../../processing-control/src/state.mjs'; import { NAME as HARNESS_NAME } from '../../plugins/src/kinds.mjs'; @@ -6418,6 +6419,99 @@ export class Broker { .all('SELECT id,at,name,repo FROM projects WHERE business=? ORDER BY seq', s.business) .filter((p) => !s.user || this.#granted(s, 'project.list', p.id, null)); } + // C2-09b: canonical per-instance threads form one human-owned project room. + case 'room.open': + case 'room.send': + case 'room.read': { + this.#human(s); + const opening = verb === 'room.open'; + const sending = verb === 'room.send'; + keys(a, opening ? ['project'] : sending ? ['project', 'body'] : ['project', 'after', 'limit'], + sending ? ['project', 'body'] : ['project']); + const project = identifier(a.project); + if (!this.#store.get('SELECT 1 FROM projects WHERE id=? AND business=?', project, s.business)) fail('project-not-found'); + const members = Object.keys(b.roles).filter((instance) => this.#threaded(s.business, instance)).sort(); + if (!members.length) fail('thread-instance-missing'); + const owner = this.#owner(s); + // Preflight all collisions/missing threads before open creates or send writes anything. + const threads = members.map((instance) => { + const t = this.#store.get('SELECT * FROM threads WHERE project=? AND name=?', project, instance); + if (t && (t.instance !== instance || t.owner !== owner)) + fail(opening ? 'room-thread-name-taken' : 'room-not-open'); + if (!t && !opening) fail('room-not-open'); + return t ?? { instance, name: instance }; + }); + if (opening) { + return { project, threads: threads.map((t) => ({ + id: t.id ?? this.#dispatch(s, 'thread.create', { project, name: t.name, instance: t.instance }).id, + instance: t.instance, name: t.name, + })) }; + } + if (sending) { + string(a.body, 32768); + const addressed = parseAddress(a.body); + if (!addressed.body.trim()) fail('invalid-request'); + const selected = new Set(); + for (const tag of addressed.tags) { + const candidates = new Set([this.#named(s.business, tag), tag].filter((instance) => members.includes(instance))); + if (!candidates.size) fail('unknown-addressee'); + if (candidates.size > 1) fail('addressee-ambiguous'); + selected.add([...candidates][0]); + } + const targets = threads.filter((t) => !addressed.tags.length || selected.has(t.instance)); + const sessions = targets.map((t) => { + const session = this.#defaultSession(t.id); + this.#sessionFence(session); + this.#checkMessaging(s.business, 'human', t.instance); + return session; + }); + const at = this.#now(); + const ids = targets.map((t, i) => { + const mid = randomUUID(); + this.#store.run( + 'INSERT INTO messages(id,at,business,from_role,from_run,to_role,class,in_reply_to,decision,corrects,body) VALUES(?,?,?,?,?,?,?,?,?,?,?)', + mid, at, s.business, 'human', 'human-cli', t.instance, 'INFO', null, null, null, a.body, + ); + this.#route(s.business, mid, t.instance, sessions[i]); + this.#event(s, 'human.input', { kind: 'instruction', message: mid }, mid); + return mid; + }); + return { ids, to: targets.map((t) => t.instance) }; + } + const limit = a.limit ?? THREAD_PAGE; + if (!Number.isInteger(limit) || limit < 1 || limit > THREAD_PAGE_MAX) fail('invalid-request'); + const tids = threads.map((t) => t.id); + const placeholders = tids.map(() => '?').join(','); + let after = 0; + if (a.after !== undefined) { + after = this.#store.get( + `SELECT m.seq FROM messages m JOIN message_threads mt ON mt.message=m.id WHERE m.id=? AND m.business=? AND mt.thread IN (${placeholders})`, + identifier(a.after), s.business, ...tids, + )?.seq; + if (after === undefined) fail('message-not-found'); + } + // At most one row per instance joins a group; one lookahead row completes the last page. + const rows = this.#store.all( + `SELECT m.*,mt.thread,mt.session,t.instance FROM messages m JOIN message_threads mt ON mt.message=m.id JOIN threads t ON t.id=mt.thread + WHERE m.business=? AND mt.thread IN (${placeholders}) AND m.seq>? ORDER BY m.seq LIMIT ${limit * members.length + 1}`, + s.business, ...tids, after, + ); + const entries = []; + let previous; + for (const m of rows) { + const entry = entries.at(-1); + if (entry && m.from_role === 'human' && previous.from_role === 'human' && m.seq === previous.seq + 1 + && m.at === previous.at && m.body === previous.body && m.class === previous.class && !entry.to.includes(m.instance)) { + entry.ids.push(m.id); + entry.to.push(m.instance); + } else { + if (entries.length === limit) break; + entries.push({ ...m, ids: [m.id], to: [m.instance] }); + } + previous = m; + } + return entries; + } // A thread belongs to the user who made it and to one declared thread instance. // Row 177 (#1675): a tester's thread is owned by `tester`, so neither reaches the other's. case 'thread.create': { diff --git a/packages/bus/src/index.mjs b/packages/bus/src/index.mjs index 3e6bea77c..c8d9951f1 100644 --- a/packages/bus/src/index.mjs +++ b/packages/bus/src/index.mjs @@ -3,3 +3,4 @@ export { startBroker } from './runtime.mjs'; export { Client } from './client.mjs'; export { views } from './views.mjs'; export { busBusiness } from './business.mjs'; +export { parseAddress } from './address.mjs'; diff --git a/packages/bus/tests/address-cases.mjs b/packages/bus/tests/address-cases.mjs new file mode 100644 index 000000000..274e66369 --- /dev/null +++ b/packages/bus/tests/address-cases.mjs @@ -0,0 +1,16 @@ +// C2-09b / C2-10c: reusable parser vectors. Keep the expected result independent of the parser. +export const addressCases = [ + ['one', '@continuity x', { tags: ['continuity'], body: 'x' }], + ['many', '@bean @chet hello', { tags: ['bean', 'chet'], body: 'hello' }], + ['repeat', '@bean @bean hi', { tags: ['bean', 'bean'], body: 'hi' }], + ['plain', 'hello @bean', { tags: [], body: 'hello @bean' }], + ['stop', '@bean hello @chet', { tags: ['bean'], body: 'hello @chet' }], + ['EOF tag', '@continuity', { tags: ['continuity'], body: '' }], + ['EOF last tag', '@bean @chet', { tags: ['bean', 'chet'], body: '' }], + ['leading whitespace', ' \t\n@bean\t@chet\nhello ', { tags: ['bean', 'chet'], body: 'hello ' }], + ['tags only', '@bean \t\n', { tags: ['bean'], body: '' }], + ['empty', '', { tags: [], body: '' }], + ['whitespace', ' \t', { tags: [], body: '' }], + ['bare at', '@ hello', { tags: [], body: '@ hello' }], + ['punctuation is a name', '@unknown, hi', { tags: ['unknown,'], body: 'hi' }], +]; diff --git a/packages/bus/tests/address.test.mjs b/packages/bus/tests/address.test.mjs new file mode 100644 index 000000000..b3c2dc337 --- /dev/null +++ b/packages/bus/tests/address.test.mjs @@ -0,0 +1,17 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import { parseAddress } from '../src/address.mjs'; +import { addressCases } from './address-cases.mjs'; + +for (const [label, input, expected] of addressCases) { + test(`parseAddress: ${label}`, () => assert.deepEqual(parseAddress(input), expected)); +} +test('parseAddress rejects non-text without coercion', () => { + for (const input of [null, undefined, {}, 1]) assert.throws(() => parseAddress(input), TypeError); +}); + +// mos-1567: new coverage, separate from the pre-existing broker import pin. +test('the mounted address parser has no import dependency', () => { + assert.doesNotMatch(readFileSync(new URL('../src/address.mjs', import.meta.url), 'utf8'), /\bimport\b/); +}); diff --git a/packages/bus/tests/project-runtime.test.mjs b/packages/bus/tests/project-runtime.test.mjs index 2de4464ef..2aed8876a 100644 --- a/packages/bus/tests/project-runtime.test.mjs +++ b/packages/bus/tests/project-runtime.test.mjs @@ -14,6 +14,8 @@ test('Broker keeps the sandbox client import closure: only the listed imports, n assert.deepEqual([...source.matchAll(/^import .*;$/gm)].map(m => m[0]), [ // Row 210 (#1707): createHash gives host.run events the argv, stdin and output sha256 values. "import { randomUUID, randomBytes, createHash } from 'node:crypto';", + // Row 265 (#1770): pure room address parsing, mounted in RUNNER_FILES beside the broker. + "import { parseAddress } from './address.mjs';", // Row 65 (#1558): bindLaunch checks a run's transcript path is absolute. "import { isAbsolute, dirname } from 'node:path';", // Row 191 / sage-1367: the one additional read-only CODE source, with no project/git imports. diff --git a/packages/bus/tests/rooms.test.mjs b/packages/bus/tests/rooms.test.mjs new file mode 100644 index 000000000..4b155180a --- /dev/null +++ b/packages/bus/tests/rooms.test.mjs @@ -0,0 +1,247 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { randomUUID } from 'node:crypto'; +import { mkdtempSync, readFileSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { Store } from '../src/store.mjs'; +import { Broker, THREAD_PAGE, THREAD_PAGE_MAX, TESTER_VERBS } from '../src/broker.mjs'; + +const MEMBERS = ['bean', 'chet', 'continuity']; +const shipped = (name) => JSON.parse(readFileSync(new URL(`../../../roles/${name}.json`, import.meta.url), 'utf8')); +function setup(t, { deny = false, empty = false } = {}) { + const root = mkdtempSync(join(tmpdir(), 'bus-rooms-')); + const store = new Store(root); + t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); }); + const role = (definition) => ({ definition, authority: { withinRole: ['message.send'], crossRole: [] } }); + // Deliberately unsorted, with two instances of one definition and a non-member chief. + const roles = { continuity: role('continuity'), chet: role('companion'), bean: role('companion'), chief: role('chief-of-staff') }; + const definitions = { + 'chief-of-staff': {}, companion: { messaging: shipped('companion').messaging }, + continuity: { messaging: deny ? { sendTo: ['human'], receiveFrom: [] } : shipped('continuity').messaging }, + }; + const b = new Broker({ store, businesses: { demo: { + id: 'demo', human: 'jason', arbiters: { technical: 'chief', delivery: 'chief' }, + roles: empty ? { chief: roles.chief } : roles, definitions, + projects: { stack: { root: '/nonexistent' } }, vars: { 'bus.tester': true }, + } } }); + const caps = { + human: b.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true }), + tester: b.bindTester({ business: 'demo' }), + }; + const call = (verb, args = {}, who = 'human') => b.request(caps[who], { verb, args }); + caps.chief = b.bindLaunch({ business: 'demo', role: 'chief', run: 'chief-run', harness: 'pi' }); + call('role.claim', {}, 'chief'); + const project = call('project.create', { name: 'room', repo: 'stack' }).id; + const open = () => call('room.open', { project }); + const send = (body, extra = {}) => call('room.send', { project, body, ...extra }); + const read = (extra = {}) => call('room.read', { project, ...extra }); + const effects = () => ['messages', 'message_threads', 'deliveries'].map((table) => store.get(`SELECT count(*) n FROM ${table}`).n) + .concat(store.get("SELECT count(*) n FROM events WHERE kind='human.input'").n); + const refuse = (code, fn) => { + const before = effects(); + assert.throws(fn, { code }); + assert.deepEqual(effects(), before, `${code}: no message, route, delivery or human.input`); + }; + return { b, caps, store, call, project, open, send, read, effects, refuse }; +} + +test('room.open sorts all threaded instances, creates defaults, and reuses caller-owned threads', (t) => { + const { open, call, project, store } = setup(t); + const existing = call('thread.create', { project, name: 'chet', instance: 'chet' }).id; + const result = open(); + assert.equal(result.project, project); + assert.deepEqual(result.threads.map(({ instance, name }) => [instance, name]), MEMBERS.map((x) => [x, x])); + assert.equal(result.threads[1].id, existing); + for (const thread of result.threads) { + assert.equal(store.get('SELECT owner FROM threads WHERE id=?', thread.id).owner, 'jason'); + assert.equal(call('session.list', { thread: thread.id }).filter((s) => s.default).length, 1); + } + assert.deepEqual(open(), result); + assert.equal(store.get('SELECT count(*) n FROM threads').n, 3); +}); + +for (const collision of ['instance', 'owner']) { + test(`room.open preflights ${collision} collisions atomically`, (t) => { + const { call, project, open, store } = setup(t); + call('thread.create', { project, name: 'continuity', instance: collision === 'instance' ? 'bean' : 'continuity' }, + collision === 'owner' ? 'tester' : 'human'); + assert.throws(open, { code: 'room-thread-name-taken' }); + assert.deepEqual(store.all('SELECT name FROM threads').map((r) => r.name), ['continuity']); + assert.equal(store.get('SELECT count(*) n FROM sessions').n, 1); + }); +} + +test('room verbs require the human, and none is a tester verb', (t) => { + const { call, project, open, refuse } = setup(t); + open(); + for (const verb of ['room.open', 'room.send', 'room.read']) { + const args = { project, ...(verb === 'room.send' ? { body: 'hello' } : {}) }; + assert.ok(!TESTER_VERBS.includes(verb)); + refuse('tester-refused', () => call(verb, args, 'tester')); + refuse('human-required', () => call(verb, args, 'chief')); + } +}); + +test('room verbs refuse missing projects and zero member businesses', (t) => { + const { call, refuse } = setup(t); + for (const verb of ['room.open', 'room.send', 'room.read']) { + refuse('project-not-found', () => call(verb, { project: randomUUID(), ...(verb === 'room.send' ? { body: 'hello' } : {}) })); + } + const empty = setup(t, { empty: true }); + assert.throws(empty.open, { code: 'thread-instance-missing' }); +}); + +for (const state of ['missing', 'foreign-owner', 'wrong-instance']) { + test(`send/read refuse a ${state} canonical member without effects`, (t) => { + const { call, project, send, read, refuse } = setup(t); + for (const instance of MEMBERS) { + if (instance === 'continuity' && state === 'missing') continue; + call('thread.create', { project, name: instance, instance: instance === 'continuity' && state === 'wrong-instance' ? 'bean' : instance }, + instance === 'continuity' && state === 'foreign-owner' ? 'tester' : 'human'); + } + refuse('room-not-open', () => send('hello')); + refuse('room-not-open', read); + }); +} + +test('room.send targets a key, broadcasts without tags, and preserves original text and ordinary route/input rows', (t) => { + const { open, send, store, read } = setup(t); + const threads = open().threads; + const one = send('@continuity x'); + assert.deepEqual(one.to, ['continuity']); + assert.equal(one.ids.length, 1); + assert.equal(store.get('SELECT thread FROM message_threads WHERE message=?', one.ids[0]).thread, threads[2].id); + const body = ' \t@bean @chet hello @continuity'; + const two = send(body); + assert.deepEqual(two.to, ['bean', 'chet']); + const all = send('hello @bean'); + assert.deepEqual(all.to, MEMBERS); + const rows = store.all('SELECT * FROM messages ORDER BY seq'); + assert.deepEqual(rows.map((r) => r.body), ['@continuity x', body, body, ...MEMBERS.map(() => 'hello @bean')]); + assert.equal(new Set(rows.slice(-3).map((r) => r.at)).size, 1); + assert.ok(rows.every((r) => r.from_role === 'human' && r.from_run === 'human-cli' && r.class === 'INFO')); + assert.equal(store.get('SELECT count(*) n FROM message_threads').n, 6); + assert.equal(store.get("SELECT count(*) n FROM deliveries WHERE op='routed'").n, 6); + assert.equal(store.get("SELECT count(*) n FROM events WHERE kind='human.input'").n, 6); + assert.deepEqual(read().map((r) => r.to), [['continuity'], ['bean', 'chet'], MEMBERS]); +}); + +test('current display names and repeated tags resolve once; a replaced display name is unknown', (t) => { + const { open, call, send, refuse } = setup(t); + open(); + call('name.set', { instance: 'bean', name: 'beanie' }); + assert.deepEqual(send('@beanie @bean @beanie hi').to, ['bean']); + call('name.set', { instance: 'bean', name: 'newbeanie' }); + refuse('unknown-addressee', () => send('@beanie hi')); + assert.deepEqual(send('@newbeanie hi').to, ['bean']); +}); + +test('a legacy name colliding with another member key is ambiguous; its own key resolves once', (t) => { + const { open, send, store, refuse } = setup(t); + open(); + // Naming policy now forbids key collisions; legacy data can still contain them. Append real rows. + store.run('INSERT INTO instance_names(at,business,instance,name,by) VALUES(?,?,?,?,?)', new Date().toISOString(), 'demo', 'bean', 'chet', 'fixture'); + refuse('addressee-ambiguous', () => send('@chet hi')); + store.run('INSERT INTO instance_names(at,business,instance,name,by) VALUES(?,?,?,?,?)', new Date().toISOString(), 'demo', 'bean', 'bean', 'fixture'); + assert.deepEqual(send('@bean @bean hi').to, ['bean']); +}); + +test('unknown or non-member addressees and tags-only bodies leave no message effects', (t) => { + const { open, send, refuse } = setup(t); + open(); + for (const body of ['@nobody x', '@chief x', '@bean @nobody x']) refuse('unknown-addressee', () => send(body)); + for (const body of ['@continuity', ' \t@bean\n@chet ', '', ' \t']) refuse('invalid-request', () => send(body)); +}); + +test('messaging denial on the last target rolls back the entire broadcast; allowed subset still works', (t) => { + const { open, send, refuse } = setup(t, { deny: true }); + open(); + refuse('message-sender-refused', () => send('all')); + assert.deepEqual(send('@bean @chet okay').to, ['bean', 'chet']); +}); + +test('a clearing last member fences the whole send; another active target still accepts', (t) => { + const { b, caps, open, call, send, refuse } = setup(t); + const thread = open().threads[2].id; + caps.worker = b.bindLaunch({ business: 'demo', role: 'continuity', run: 'continuity-run', harness: 'pi', thread }); + call('role.claim', {}, 'worker'); + const session = call('session.list', { thread })[0].id; + call('session.clear', { thread, session, revision: 0, op: 'room-clear', confirm: true }); + refuse('session-clearing', () => send('all')); + assert.deepEqual(send('@bean okay').to, ['bean']); +}); + +test('room.read groups one send, pages by the last grouped id, and rejects foreign or absent cursors', (t) => { + const { open, send, read, call, project, refuse } = setup(t); + const threads = open().threads; + const first = send('first'); + const second = send('@continuity second'); + const page = read({ limit: 1 }); + assert.equal(page.length, 1); + assert.deepEqual(page[0].ids, first.ids); + assert.deepEqual(page[0].to, MEMBERS); + assert.equal(page[0].thread, threads[0].id); + assert.equal(page[0].instance, 'bean'); + assert.deepEqual(read({ after: first.ids.at(-1), limit: 1 }).map((r) => r.ids), [second.ids]); + assert.deepEqual(read({ after: second.ids[0] }), []); + const other = call('project.create', { name: 'other', repo: 'stack' }).id; + const thread = call('thread.create', { project: other, name: 'bean', instance: 'bean' }).id; + const foreign = call('thread.send', { thread, body: 'elsewhere' }).id; + const noncanonical = call('thread.create', { project, name: 'side', instance: 'bean' }).id; + const side = call('thread.send', { thread: noncanonical, body: 'side' }).id; + for (const after of [foreign, side, randomUUID()]) refuse('message-not-found', () => read({ after })); + for (const limit of [0, -1, 1.1, THREAD_PAGE_MAX + 1, '1']) refuse('invalid-request', () => read({ limit })); +}); + +test('room.read keeps identical sends at the same timestamp separate and includes every session', (t) => { + const { open, call, project, store, read } = setup(t); + const threads = open().threads; + const at = '2026-10-24T00:00:00.000Z'; + const batches = [[], []]; + // Broker clocks are monotonic. Append two independently valid transaction-shaped batches to + // exercise the historical same-at boundary without altering production clocks or existing rows. + for (const batch of batches) for (const thread of threads) { + const id = randomUUID(); + batch.push(id); + const session = call('session.list', { thread: thread.id })[0].id; + store.run('INSERT INTO messages(id,at,business,from_role,from_run,to_role,class,body) VALUES(?,?,?,?,?,?,?,?)', + id, at, 'demo', 'human', 'human-cli', thread.instance, 'INFO', 'same'); + store.run('INSERT INTO message_threads(message,thread,session) VALUES(?,?,?)', id, thread.id, session); + } + assert.deepEqual(read().map((r) => r.ids), batches); + assert.deepEqual(read({ limit: 1 })[0].ids, batches[0]); + assert.deepEqual(read({ after: batches[0].at(-1) }).map((r) => r.ids), [batches[1]]); + const created = call('session.create', { thread: threads[0].id, name: 'later', op: 'new-later' }); + call('thread.send', { thread: threads[0].id, session: created.id, body: 'later session' }); + assert.equal(read().at(-1).body, 'later session'); + assert.equal(read().at(-1).session, created.id); + assert.equal(read().at(-1).thread, threads[0].id); + assert.equal(store.get('SELECT count(*) n FROM threads WHERE project=?', project).n, 3); +}); + +test('room.read defaults and caps the number of merged entries, not recipient rows', (t) => { + const { open, send, read } = setup(t); + open(); + for (let i = 0; i <= THREAD_PAGE_MAX; i++) send(`message ${i}`); + assert.equal(read().length, THREAD_PAGE); + assert.equal(read({ limit: THREAD_PAGE_MAX }).length, THREAD_PAGE_MAX); + assert.ok(read({ limit: 1 })[0].to.length === 3); +}); + +test('room.read includes an agent reply with its thread and instance without merging it with human rows', (t) => { + const { b, caps, open, call, send, read, refuse, project } = setup(t); + const thread = open().threads[0].id; + send('question'); + caps.worker = b.bindLaunch({ business: 'demo', role: 'bean', run: 'bean-run', harness: 'pi', thread }); + call('role.claim', {}, 'worker'); + const reply = call('message.send', { to: 'human', body: 'answer' }, 'worker'); + const entries = read(); + assert.equal(entries.length, 2); + assert.deepEqual(entries[0].to, MEMBERS); + assert.equal(entries[1].id, reply.id); + assert.equal(entries[1].from_role, 'bean'); + assert.equal(entries[1].thread, thread); + assert.equal(entries[1].instance, 'bean'); + refuse('human-required', () => call('room.read', { project }, 'worker')); +}); diff --git a/packages/seat/src/sandbox.mjs b/packages/seat/src/sandbox.mjs index 8ccd6ed51..c2de792cb 100644 --- a/packages/seat/src/sandbox.mjs +++ b/packages/seat/src/sandbox.mjs @@ -57,6 +57,7 @@ export const RUNNER_FILES = Object.freeze([ "packages/harness/src/pi-extension.mjs", "packages/bus/src/client.mjs", "packages/bus/src/broker.mjs", + "packages/bus/src/address.mjs", "packages/bus/src/landing.mjs", "packages/business/src/vocabulary.mjs", "packages/plugins/src/kinds.mjs",