docs: register Sage row 121 approval and row 49 review; add Rocko row 49 r1 packet
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
# Row 49 / #1535 — bus comment cursor across restarts, round 1
|
||||
|
||||
Base: `7b166a0f1` (origin/refactor). Detached worktree:
|
||||
`/mnt/storage/src/mosaic-stack-rocko-49`. Source code is uncommitted; Sage lands
|
||||
`build.patch`. Reviewers: Darkwing and Filbert. Scope is comments only.
|
||||
|
||||
## Root cause and change
|
||||
|
||||
The adapter's comment count and last ID caches vanished at restart. Startup
|
||||
reconcile seeded a new count without checking the comment list, and the next
|
||||
updated-window poll could miss a comment posted during a long outage.
|
||||
|
||||
The broker now stores the highest observed comment ID per business/task in a
|
||||
separate append-only table. Adapter startup restores IDs before reconciliation;
|
||||
the first reconcile checks comment lists even if no count is cached. Cursor rows,
|
||||
snapshots and comment events commit in one transaction. ID, expanded count and
|
||||
updated caches advance after success. A cursor advances for bot comments too,
|
||||
but only foreign comments contribute to external events. Project moves retain
|
||||
the task ID. Neither task_current, task digests, event kinds nor tracker client
|
||||
changes. recordTask's existing return shape remains unchanged.
|
||||
|
||||
## Exact persisted state and growth bound
|
||||
|
||||
`DDL.sql` contains the exact 3b→3c DDL: task_comment_cursors with `seq INTEGER
|
||||
PRIMARY KEY AUTOINCREMENT`, `business TEXT`, positive `task_id` and positive
|
||||
`last_comment`; an index on business/task_id/seq; three append-only guards and
|
||||
one strictly-increasing-ID guard. No timestamp or count is stored per cursor.
|
||||
An immutable meta entry `comment_cursor_epoch` is inserted once at creation or
|
||||
migration; the existing version/digest metadata advances from 3b to 3c only in
|
||||
the explicit offline migration.
|
||||
|
||||
A row is appended only when the maximum observed ID increases. Empty polls,
|
||||
unchanged counts, restarts, already-seen IDs and comment deletions append none.
|
||||
Growth is bounded by the number of observed new comments, usually one row per
|
||||
batch, never by poll frequency. No pruning is introduced.
|
||||
|
||||
## Live-copy schema evidence and ordered migrations
|
||||
|
||||
Confirmed from CODE, never the live database, at live-copy commit
|
||||
`2f57e3c5995dc1c75fb506b43bea602172908bb1`: Store requires version 3b,
|
||||
and schema.sql SHA-256 is
|
||||
`179ffe356d4ff19a49b5ebad39b6c6bfd7771deb8e1b7c55b5e746f039d69e65`.
|
||||
`live-schema-evidence.txt` records the commands/results. The same immutable DDL
|
||||
is pinned in src/migrations/3b.sql and independently in the test fixture.
|
||||
|
||||
The migration test creates a schema-current 3b fixture, closes it, copies it and
|
||||
migrates only the copy. Source bytes and existing event evidence are preserved.
|
||||
It checks ordinary startup refusal, explicit migration/reopen/idempotence,
|
||||
writer-lock refusal, schema drift and incorrect metadata refusal. A retained
|
||||
future3d fixture appends a named 3c→3d step and proves the actual engine executes
|
||||
3b→3c→3d in order. Researcher's row 123 can append its step and leave prior SQL
|
||||
pinned. Each step validates its input digest/version and commits its DDL, metadata
|
||||
and optional initializer atomically, then the next step runs. A failed later step
|
||||
can resume from the last committed version. Normal startup never migrates.
|
||||
Migration DDL lives under src/migrations so stack-copy's existing bus/src allowlist
|
||||
includes it; no stack-copy.sh edit.
|
||||
|
||||
`MIGRATION.md` describes Mos's separately approved downtime and re-pin window.
|
||||
No seat reads or migrates the live store, or starts/stops a live unit.
|
||||
|
||||
## Initial cutoff and clock skew
|
||||
|
||||
Before any durable ID exists, timestamps are compared to database creation/
|
||||
migration epoch minus a stated 60-second margin, rounded down to tracker seconds.
|
||||
A test pins a comment 30 seconds behind host time. This favors a possible cutover
|
||||
duplicate over losing a comment within the margin. Historical comments older
|
||||
than that cutoff are baselined without an event. More than 60 seconds of tracker
|
||||
lag or downtime before the initial migration cutoff remains outside this initial
|
||||
guarantee; a clock ahead can replay already emitted comments once at migration.
|
||||
After the first ID is durable, timestamps never determine freshness and long
|
||||
outages do not reset the cursor.
|
||||
|
||||
## Approved scope extension — sage-0304, 2026-10-15 16:05:10Z
|
||||
|
||||
`packages/bus/src/store.mjs` exports SCHEMA_VERSION. `scripts/land-work/read.mjs`
|
||||
imports it instead of its local 3b literal, and updates the explanatory comment.
|
||||
Without this, its digest check would follow 3c but every version check would
|
||||
refuse a valid database. No other land-work behavior changes. test-land-work.sh
|
||||
is included in the builder gate; Darkwing (row 116 owner) reviews this row.
|
||||
|
||||
## Verification and honest corrections
|
||||
|
||||
Sage sage-0307 granted the slot. busy.py is chained with && and returns a failing
|
||||
exit if busy. DOCKER_HOST=unix:///nonexistent.sock for all checks; no Docker run
|
||||
is required by the targeted gate. Gate list: bus, tasks, cli, webui, harness and
|
||||
seat node suites, plus scripts/test-land-work.sh. Relative import searches find
|
||||
these Store/Broker/adapter consumers; test-land-work.sh is the shell reader of
|
||||
Store/schema and land-work/read.mjs. Other shell scripts do not read the changed
|
||||
paths; the brief's full shell gate remains Sage's landing gate.
|
||||
|
||||
Focused red logs show the missing restart behavior and migration before code.
|
||||
An initial gate lacked the worktree's node_modules link; the CLI launcher refused
|
||||
that setup. The link now points to canonical pinned dependencies, as prior seat
|
||||
worktrees do. A second gate caught a candidate packaging defect: SQL first lived
|
||||
outside bus/src and pinned copies omitted it. SQL now lives under src/migrations;
|
||||
the real pinned-install test verifies it. Both failed runs are retained. Neither
|
||||
was a known #258/#261/#262/#263 flake. Final counts/results follow below.
|
||||
|
||||
|
||||
Final gate: seven steps green, zero failures/skips. Node counts: bus **178**,
|
||||
tasks **97**, cli **195**, webui **112** (real browser tests), harness **84**,
|
||||
seat **132**. land-work selftests: **84** passed, zero failed. Bus was rerun
|
||||
after adding final migration metadata/command coverage. DOCKER_HOST remained
|
||||
`unix:///nonexistent.sock`; no Docker run, network or daemon action occurred.
|
||||
No known flake recurred. `gate/results.json` and per-suite logs are the evidence.
|
||||
|
||||
22/22 mutants killed; no survivor, timeout, syntax/import failure or invalid
|
||||
mutation. `MUTANTS.md` maps every fault to its behavioral test. All 17 candidate
|
||||
hashes were restored. A fresh detached reconstruction applied build.patch at
|
||||
the base and verified all 17 manifest paths; the temporary verification worktree
|
||||
was removed. The restored restart/skew file also passed 5/5 after the mutants.
|
||||
The cwd/argv-scoped node/Chromium sweep found zero owned runners. No live
|
||||
systemd, dataRoot, token, binding, Settings or bus endpoint was touched.
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE task_comment_cursors (
|
||||
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business TEXT NOT NULL,
|
||||
task_id INTEGER NOT NULL CHECK (task_id > 0),
|
||||
last_comment INTEGER NOT NULL CHECK (last_comment > 0)
|
||||
) STRICT;
|
||||
CREATE INDEX task_comment_cursors_latest ON task_comment_cursors (business, task_id, seq);
|
||||
CREATE TRIGGER task_comment_cursors_no_update BEFORE UPDATE ON task_comment_cursors
|
||||
BEGIN SELECT RAISE(ABORT, 'task_comment_cursors is append-only'); END;
|
||||
CREATE TRIGGER task_comment_cursors_no_delete BEFORE DELETE ON task_comment_cursors
|
||||
BEGIN SELECT RAISE(ABORT, 'task_comment_cursors is append-only'); END;
|
||||
CREATE TRIGGER task_comment_cursors_no_replace BEFORE INSERT ON task_comment_cursors
|
||||
WHEN EXISTS (SELECT 1 FROM task_comment_cursors WHERE seq = NEW.seq)
|
||||
BEGIN SELECT RAISE(ABORT, 'task_comment_cursors is append-only'); END;
|
||||
CREATE TRIGGER task_comment_cursors_forward BEFORE INSERT ON task_comment_cursors
|
||||
WHEN NEW.last_comment <= COALESCE((SELECT last_comment FROM task_comment_cursors
|
||||
WHERE business = NEW.business AND task_id = NEW.task_id ORDER BY seq DESC LIMIT 1), 0)
|
||||
BEGIN SELECT RAISE(ABORT, 'comment cursor must advance'); END;
|
||||
@@ -0,0 +1,15 @@
|
||||
# Review handoff
|
||||
|
||||
- Issue #1535, row49, round1; Darkwing and Filbert.
|
||||
- Claim rev1272. in-review rev1276; missing-token request outcome rev1277,
|
||||
exit1. Sage posts queue review request as jarvis.
|
||||
- Base7b166a0f1; 17 source paths. Candidate manifest SHA-256:
|
||||
87ef1321a1a08be64a20499889fc24b5549b47d6d33abfd86db95f62fb3cb6d0.
|
||||
- Source uncommitted in /mnt/storage/src/mosaic-stack-rocko-49.
|
||||
- Own append-only stage logs committed by explicit pathspec as8a4c8fca6;
|
||||
no push. Packet remains for Sage's scan/commit.
|
||||
- Slot returned16:18:57UTC after all runners, restored hashes and empty sweep.
|
||||
- BUILD.md and MIGRATION.md describe scope and human-only live boundaries;
|
||||
DDL.sql names Researcher's 3c starting point. Keep the future3d chain test.
|
||||
- packet-manifest.sha256 paths are relative to this packet directory;
|
||||
candidate-manifest.sha256 paths are relative to repository root.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Row 49: explicit 3b→3c migration and cutover
|
||||
|
||||
Development seats use fixture databases only. These instructions are a plan,
|
||||
not live authorization. Mos runs the live operation only after their go, during
|
||||
a re-pin window that includes bus downtime. Nobody reads the live store for
|
||||
build/review evidence. There has been no live unit, file, bus or Console action.
|
||||
|
||||
1. Sage lands the reviewed candidate and identifies its pinned copy. Mos schedules
|
||||
the downtime/re-pin window and stops the bus using the established window
|
||||
procedure. No writer may remain; the migrator refuses an existing writer lock
|
||||
and never removes a stale lock. Resolve any lock under the established human
|
||||
recovery procedure, not by bypassing it.
|
||||
2. Mos takes a consistent restorable backup of the stopped bus directory, including
|
||||
SQLite WAL state if present. Do not copy only bus.sqlite while WAL data exists.
|
||||
Record the backup identity and current copy, without printing database contents.
|
||||
3. From the NEW pinned copy, Mos invokes the explicit migration, passing the
|
||||
actual absolute dataRoot (not a database filename):
|
||||
|
||||
```sh
|
||||
node /absolute/new-copy/packages/bus/src/migrate-schema.mjs /absolute/dataRoot
|
||||
```
|
||||
|
||||
Run this promptly after stopping the old bus: the initial epoch is migration
|
||||
host time minus a 60-second skew margin. Comments older than that initial cutoff
|
||||
cannot reliably be distinguished from historical comments without prior IDs.
|
||||
More than a minute of pre-migration downtime or tracker lag is outside this
|
||||
initial guarantee; arrange the window accordingly. Once 3c has run, later
|
||||
outages use persisted IDs and have no timestamp-window limit.
|
||||
4. Migration validates source version, full trusted schema digest, metadata, WAL,
|
||||
timestamps and integrity before applying each named step. 3b→3c adds only the
|
||||
DDL in DDL.sql, creates the epoch and updates version/digest atomically. It
|
||||
preserves all existing evidence. Already-current is a validated no-op. An
|
||||
unknown version, damage, wrong metadata, missing store or active writer refuses.
|
||||
Stop the window on refusal; do not bypass validation or silently start old code
|
||||
against upgraded data. Future steps chain in order, with each committed version
|
||||
an explicit resume boundary.
|
||||
5. Mos completes the re-pin and starts the new bus in the same approved window.
|
||||
Its startup reconcile restores cursor IDs and reads comments; the new copy is
|
||||
required because an old 3b Store refuses 3c. Perform the agreed human acceptance
|
||||
check. Any Console or other unit action remains a separately approved Mos step.
|
||||
|
||||
Rollback: code alone cannot downgrade 3c to 3b. With the bus stopped and Mos's go,
|
||||
restore the complete consistent pre-migration bus-directory backup AND the prior
|
||||
pinned copy. Restoring backup discards evidence recorded after the backup; Sage
|
||||
and Mos must decide the recovery rather than silently doing so. No automatic
|
||||
schema downgrade, pruning or live repair ships in this row.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Acceptance mutants
|
||||
|
||||
22/22 killed; no timeout, syntax/import failure, invalid mutation or survivor.
|
||||
Each runner owns a process group; a timeout kills the entire group and never counts as a kill.
|
||||
SQL mutants update both new-schema and migration DDL, with the source checksum recomputed,
|
||||
so they reach behavioral assertions rather than fail at schema import.
|
||||
|
||||
| Check / deliberate fault | Test | Result |
|
||||
| --- | --- | --- |
|
||||
| 01-restore-durable-ids | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 02-persist-observed-ids | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 03-startup-comment-read | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 04-exclude-bots | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 05-strict-new-id | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 06-cache-after-commit | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 07-event-cursor-atomicity | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 08-no-empty-poll-row | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 09-initial-clock-margin | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 10-durable-initial-epoch | packages/tasks/tests/comment-restart.test.mjs | KILLED |
|
||||
| 11-validate-cursor-input | packages/bus/tests/comment-cursors.test.mjs | KILLED |
|
||||
| 12-sync-only-cursor-write | packages/bus/tests/comment-cursors.test.mjs | KILLED |
|
||||
| 13-business-isolation | packages/bus/tests/comment-cursors.test.mjs | KILLED |
|
||||
| 14-explicit-offline-only | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
| 15-pinned-source-metadata | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
| 16-chain-all-steps | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
| 17-preserve-source-copy | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
| 18-land-work-version | scripts/test-land-work.sh | KILLED |
|
||||
| 19-append-only-cursor-evidence | packages/bus/tests/comment-cursors.test.mjs | KILLED |
|
||||
| 20-monotonic-cursor | packages/bus/tests/comment-cursors.test.mjs | KILLED |
|
||||
| 21-exclusive-writer-lock | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
| 22-migration-command | packages/bus/tests/comment-migration.test.mjs | KILLED |
|
||||
@@ -0,0 +1 @@
|
||||
7b166a0f196026b5896473e0e09181e996d962a9
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
CLEAR
|
||||
@@ -0,0 +1 @@
|
||||
CLEAR
|
||||
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python3
|
||||
import pathlib,os,sys,json
|
||||
busy=[]
|
||||
for p in pathlib.Path('/proc').glob('[0-9]*'):
|
||||
try:
|
||||
cwd=os.readlink(p/'cwd')
|
||||
if not cwd.startswith('/mnt/storage/src/mosaic-stack'):continue
|
||||
args=[a.decode(errors='replace') for a in (p/'cmdline').read_bytes().split(b'\0') if a]
|
||||
if not args:continue
|
||||
exe=pathlib.Path(args[0]).name
|
||||
node=exe=='node' and any(a=='--test' or a.startswith('--test-') or a.endswith('.test.mjs') for a in args[1:])
|
||||
browser='chrom' in exe and any(a.startswith('--headless') for a in args[1:])
|
||||
shell=exe in ['bash','sh'] and len(args)>1 and pathlib.Path(args[1]).name.startswith('test-')
|
||||
if node or browser or shell:busy.append({'pid':int(p.name),'exe':exe,'cwd':cwd})
|
||||
except OSError:pass
|
||||
print('BUSY '+json.dumps(busy) if busy else 'CLEAR')
|
||||
sys.exit(bool(busy))
|
||||
@@ -0,0 +1,17 @@
|
||||
90e27a81463069afcf628d39e320db803a49ee281448f138c5703a5df191eb7e packages/bus/README.md
|
||||
7587ac1df813e5148fdb73dc4733ec8064e6a142e4647f0da71be009a73eebdb packages/bus/schema.sql
|
||||
578d0c265c758655e506a0e2a66ca4aeb8337ff89e897fc79a7832b9fb81de40 packages/bus/src/broker.mjs
|
||||
af5031e21c4fee8c2252a7d0b92cd8492cca2efdbcb6c7c47f1ffe069a933455 packages/bus/src/migrate-schema.mjs
|
||||
b753f630301bf125e9e286b4156d0736930dd8fb9cd8eb2ebf316688f9191a07 packages/bus/src/migrations/3b-3c.sql
|
||||
179ffe356d4ff19a49b5ebad39b6c6bfd7771deb8e1b7c55b5e746f039d69e65 packages/bus/src/migrations/3b.sql
|
||||
208c8d6208e63b4b0110eca83b8a61d97735d13a539a33cae0afed2d0dab63be packages/bus/src/store.mjs
|
||||
aa6544d51c7741b99f9115ba69390dc14b6b70e7978e144191f9eac55bb212de packages/bus/tests/comment-cursors.test.mjs
|
||||
1f12df682689705223493c4153d327baf4499f8a457262bf897a759c4b434622 packages/bus/tests/comment-migration.test.mjs
|
||||
179ffe356d4ff19a49b5ebad39b6c6bfd7771deb8e1b7c55b5e746f039d69e65 packages/bus/tests/fixtures/schema-3b.sql
|
||||
0e079cf703233e70fd057d01d852140693e023a6e9a2cd35409b168c4d08c3ed packages/bus/tests/schema.test.mjs
|
||||
7f16447f47bc10874df1b400dd85416ba9115b984222436666880f806610ea0e packages/tasks/README.md
|
||||
4e263e5b73c95ece04397f70524067e63cf3ab9778341c1e18ebcb995851ee50 packages/tasks/src/adapter.mjs
|
||||
39887268258c3b651246b3596a866005fc193cd8ee5f151a02492967069f2d06 packages/tasks/src/sync.mjs
|
||||
c65abc7df9b6e1ad18e164fb4a4fe6127c3375a74079389859086088ee6223e7 packages/tasks/tests/comment-restart.test.mjs
|
||||
477aef1cfafa35490b50568601b9ad0de35ff3789b2069526f6548b329e6f965 packages/tasks/tests/world.mjs
|
||||
0e23a3dceac3a80dd5e2fa144ad96b12f8691d63a179920f9063d4c6a083984a scripts/land-work/read.mjs
|
||||
@@ -0,0 +1,184 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (14.204951ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (13.910211ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (22.68387ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (9.575619ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (14.874145ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (11.10281ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (12.317223ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (11.392683ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (57.016538ms)
|
||||
✔ agents: stranded is per role and per business (18.978326ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (7.093856ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (16.444672ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (15.187757ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (16.098609ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (9.447922ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (9.620951ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (16.611918ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (10.50657ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (16.347543ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (7.00047ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (11.607591ms)
|
||||
✔ authority never transfers between action, run, target, unresolved or replaced role holder (15.740974ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (8.114717ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (11.945808ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (7.901772ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (13.89849ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (13.87552ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (1.158918ms)
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (9.942736ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.34407ms)
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (36.103883ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (57.522291ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (37.774338ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (10.220983ms)
|
||||
✔ credentials refuses a role session and any argument (9.787797ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (10.757991ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (61.073581ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (2.146996ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (1.320734ms)
|
||||
✔ expiry refuses use and env references never become client data (0.417679ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (0.865039ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.248738ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (24.06906ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (13.187684ms)
|
||||
✔ a human withdraw sends one message with the note (13.098121ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (16.151824ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (15.978528ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (15.783336ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (13.830742ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (13.097903ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (17.926583ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (16.997133ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (17.180096ms)
|
||||
✔ recent stops at RECENT rows (57.216438ms)
|
||||
✔ every row is what trail already gives the same session for that id (24.542349ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (23.981308ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (23.80236ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (13.213218ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (7.639076ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (8.481423ms)
|
||||
✔ endLaunch leaves a claim another run took alone (9.191965ms)
|
||||
✔ refuse records action.refused against the caller with the code only (6.92126ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (10.686819ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (73.14704ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (1.25466ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.377922ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.529354ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.207429ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (15.486616ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (28.78493ms)
|
||||
✔ uncertain organization receipts leave bus startup and reads alone but refuse writes until reconciled (22.278652ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (16.047835ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (10.008354ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (14.69295ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (211.873021ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (15.754103ms)
|
||||
✔ views messages passes only its paging arguments through (0.201639ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (9.600953ms)
|
||||
✔ the assistant sends to the user and to the chief of staff only (20.833556ms)
|
||||
✔ an assistant send to any other role, or to the tester, is refused and logged (19.431127ms)
|
||||
✔ only the user and the chief of staff may send to the assistant; the tester is refused by default (17.256432ms)
|
||||
✔ a sender-side list alone refuses a send to a role that has no list (16.030851ms)
|
||||
✔ a target-side list alone refuses a send from a role that has no list (17.243162ms)
|
||||
✔ the sender list is checked before the target list (13.786601ms)
|
||||
✔ roles without the field behave exactly as before (21.3031ms)
|
||||
✔ a business with no role definitions at all is unlimited (15.688328ms)
|
||||
✔ a malformed messaging field refuses at boot (7.233199ms)
|
||||
✔ the assistant's review.request to a reviewer is refused and logged, even with an approved decision (17.616886ms)
|
||||
✔ a review.verdict to the assistant from a role outside its receiveFrom is refused and logged (18.831077ms)
|
||||
✔ review requests and verdicts between roles without the field are unchanged (15.129264ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (61.121681ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (47.265694ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (57.812384ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (87.916068ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (56.87281ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (41.974148ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (54.539409ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (23.543933ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (10.97289ms)
|
||||
✔ a message with no reply gives an empty list (8.735418ms)
|
||||
✔ replies come oldest first and stop at REPLIES (47.470179ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (17.133656ms)
|
||||
✔ strict arguments; a role session gets human-required (21.546357ms)
|
||||
✔ views passes replies through as one call with the id (0.173835ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (17.027096ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (8.590232ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (9.170806ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (19.08643ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (15.904564ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (15.839849ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (21.141944ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (14.097222ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (16.691564ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (22.312721ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (12.578619ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (52.286002ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (20.630602ms)
|
||||
✔ another run cannot consume an approval; a failed check leaves it usable (12.995201ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (9.225849ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (19.348092ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (11.933064ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (12.751145ms)
|
||||
✔ class drift gated to within-role refuses before consumption (11.81697ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (13.68665ms)
|
||||
✔ class drift within-role to gated refuses before consumption (11.674539ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (11.377197ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (14.081567ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (16.423868ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (14.945803ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (9.937997ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (10.732084ms)
|
||||
✔ a tombstone is not open (8.656972ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (11.668022ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (8.281989ms)
|
||||
✔ a human session reads the same state, with the same cap (10.13632ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (8.670922ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (9.195052ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (8.740087ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (8.778653ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (42.898119ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (6.601363ms)
|
||||
✔ async transactions refuse before invoking their function (4.779191ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (107.02939ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (67.516828ms)
|
||||
✔ each filter, alone and together, and total counts every match (139.59457ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (87.956498ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (66.800696ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (289.116786ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (28.122158ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (28.535065ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (6.838919ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (16.327699ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (6.455356ms)
|
||||
✔ a bad entry refuses the whole record (6.445869ms)
|
||||
✔ taskView reads the projection for one business (7.840617ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (15.493208ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (280.319713ms)
|
||||
✔ without an adapter the server refuses every task verb (14.688994ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (15.362832ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (113.35814ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (46.161488ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (13.433944ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (30.732781ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (12.856891ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (15.24297ms)
|
||||
✔ the tester reads the human views a reader reads (16.461478ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.03496ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.348649ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.183542ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (14.573729ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (603.639701ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (18.46578ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (12.957214ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (7.379298ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (11.19722ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (9.09595ms)
|
||||
ℹ tests 176
|
||||
ℹ suites 0
|
||||
ℹ pass 176
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 6127.343577
|
||||
@@ -0,0 +1,241 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1427.904586ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (63.82284ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (142.286234ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (214.481669ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (46.867159ms)
|
||||
✔ the app shows the same decide text as mosaic decide (19.187482ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (171.065509ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (59.625819ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (234.691615ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (30.979978ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (20.816461ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (390.722587ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (31.955017ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (27.664863ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (43.413134ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (283.262311ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8382.982447ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (63.34997ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (29.051797ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (14.392159ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (73.013587ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (15.554713ms)
|
||||
✔ no business: the app says so and :business picks one (8.548785ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.847886ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (168.951774ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.412841ms)
|
||||
✔ decide with --note still asks; a No sends nothing (9.381733ms)
|
||||
✔ the app's business comes from a live bus host only (1.007561ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (6.808205ms)
|
||||
✔ draw is pure: same state, same frame (0.776433ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (15.368975ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (10.980225ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (9.361021ms)
|
||||
✔ decide prints a declining choice as declining (8.640638ms)
|
||||
✔ an unknown outcome is reported once and never resent (7.300699ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (7.638996ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (7.257074ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (6.771454ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (6.749563ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (7.415423ms)
|
||||
✔ agents and tasks print through the broker (6.852527ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.037559ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (31.46294ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (51.232562ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (26.88494ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (25.74653ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (26.061158ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (46.510296ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (25.25532ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (22.654466ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (196.346379ms)
|
||||
✔ follow refuses agent context and bad arguments (7.661422ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (8.078722ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (9.336137ms)
|
||||
✔ empty views say so (0.56444ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (0.69533ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.119003ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (276.206822ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (269.370279ms)
|
||||
✔ the size cap refuses a push before any byte (134.996702ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (281.913854ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (136.70351ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (226.057686ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (170.244445ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (167.151988ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (120.910174ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (116.570243ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (525.624754ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (387.380247ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (431.237815ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (42.302371ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (431.049466ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (43.884849ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.357819ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (293.851268ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (812.147408ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (133.342112ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (76.35783ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (444.988694ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.696083ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.709436ms)
|
||||
✔ a live host's lock stays, however old the file is (0.494196ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (650.772352ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (181.374213ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (25.820447ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (27.634714ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (30.893575ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (28.848413ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (83.598678ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (79.819097ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (86.169548ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (84.299012ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (210.384058ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (29.597773ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (78.402838ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (182.162401ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (183.628133ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (169.177027ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1081.943402ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (155.429645ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (78.930311ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (120.660528ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (123.0613ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (77.500211ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (129.922183ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (78.443165ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (137.774455ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (21.594065ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (203.261549ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (237.175197ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (96.473866ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (626.931946ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (55.148632ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (66.564241ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (12.495032ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (8.033054ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (18.545047ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1176.358192ms)
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (406.068339ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3505.1885ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (113.919203ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (190.743436ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (92.04268ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (171.850663ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (235.351822ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (97.289639ms)
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (986.319428ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (597.06317ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3605.916527ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (85.345697ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (86.867186ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (90.149191ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1210.51669ms)
|
||||
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.208477ms)
|
||||
✔ migration needs no bus/config, prints whole converted document, is idempotent and never writes (8.759466ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (1.031242ms)
|
||||
✔ post-119 example and Jason fixture migrate with checked inherited models; wrong or absent config refuses (158.44061ms)
|
||||
✔ zoned uses the IANA zone across DST (11.561521ms)
|
||||
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (15.27872ms)
|
||||
✔ two blocking decisions get two DMs with different nonces (9.969303ms)
|
||||
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.178198ms)
|
||||
✔ a failed DM is journaled, backs off, and is retried until it lands (10.415377ms)
|
||||
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (11.499671ms)
|
||||
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (12.396482ms)
|
||||
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (9.210611ms)
|
||||
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (66.587499ms)
|
||||
✔ a restart after the second refusal does not send before that refusal's 30 min are up (34.443171ms)
|
||||
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (11.4283ms)
|
||||
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (7.53495ms)
|
||||
✔ an inbox read failure is logged and the next poll retries (0.612829ms)
|
||||
✔ no Discord id reaches the journal or the log (7.948974ms)
|
||||
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (1.716435ms)
|
||||
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (1.881929ms)
|
||||
✔ the journal: a whole file that is one torn line truncates to empty (1.155235ms)
|
||||
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (0.414853ms)
|
||||
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (1.822258ms)
|
||||
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (1.859145ms)
|
||||
✔ the journal: a symlinked directory refuses and says it is a link (0.296921ms)
|
||||
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.434939ms)
|
||||
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.371102ms)
|
||||
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.424287ms)
|
||||
✔ digest content stays within Discord's 2000 characters (0.254051ms)
|
||||
✔ runLoop never overlaps ticks and stops after the one in flight (110.781103ms)
|
||||
✔ a human command refused with human-required prints the other-tree line and exits 3 (1.806267ms)
|
||||
✔ a --tester command refused with tester-required prints the other-tree line and exits 3 (0.648711ms)
|
||||
✔ other exit-3 refusals print no other-tree line (0.961234ms)
|
||||
✔ the line names no path (0.082183ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (353.477728ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (374.738022ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (371.839233ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (243.708858ms)
|
||||
✖ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (2335.309909ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (422.506345ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (145.066595ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (153.320303ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (146.979151ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (157.568628ms)
|
||||
✔ inherited service.d override refuses without changing the unit (159.31668ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (137.271235ms)
|
||||
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (26.785834ms)
|
||||
✔ talk --tester refuses text without the [mos test] prefix before any call (7.494529ms)
|
||||
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (11.249612ms)
|
||||
✔ decide, stop and launches take no --tester (8.282781ms)
|
||||
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.308455ms)
|
||||
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.439194ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (242.884135ms)
|
||||
✔ the transport writes {business, verb, args} to the child and reads its JSON (29.833127ms)
|
||||
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2123.384644ms)
|
||||
✔ busExit and refuseInsideAgent (0.477555ms)
|
||||
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (40.875699ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1027.385396ms)
|
||||
✔ a late reply the Console has listed still reaches the next talk (2027.788358ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (10.456277ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (8.428599ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (8.087903ms)
|
||||
ℹ tests 195
|
||||
ℹ suites 0
|
||||
ℹ pass 194
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 48729.492384
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/stack-copy.test.mjs:101:1
|
||||
✖ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (2335.309909ms)
|
||||
AssertionError [ERR_ASSERTION]: mosaic-bus: warning: business acme sets tracker.baseUrl, but no project file sets tracker.project; the broker gets no task verbs
|
||||
node:fs:621
|
||||
return binding.readFileUtf8(path, stringToFlags(options.flag));
|
||||
^
|
||||
|
||||
Error: ENOENT: no such file or directory, open '/mnt/storage/scratch/tmp/stack-copy-aJ334I/copies/6575f99b4a4a09b0fc8dc01398a88333bcae6ca6/packages/bus/migrations/3b.sql'
|
||||
at readFileSync (node:fs:621:20)
|
||||
at file:///mnt/storage/scratch/tmp/stack-copy-aJ334I/copies/6575f99b4a4a09b0fc8dc01398a88333bcae6ca6/packages/bus/src/store.mjs:19:19
|
||||
at ModuleJob.run (node:internal/modules/esm/module_job:569:25)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async node:internal/modules/esm/loader:650:26
|
||||
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5) {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'open',
|
||||
path: '/mnt/storage/scratch/tmp/stack-copy-aJ334I/copies/6575f99b4a4a09b0fc8dc01398a88333bcae6ca6/packages/bus/migrations/3b.sql'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
mosaic: broker exited (1) before it replied
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/tests/stack-copy.test.mjs:111:84)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: '',
|
||||
expected: /bus host up/,
|
||||
operator: 'match',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
✔ the boot config is checked before anything starts (12.221505ms)
|
||||
✔ a business with no tracker entry refuses task verbs (8.967263ms)
|
||||
✔ credential.expiring and .expired are recorded once per instance (20.433012ms)
|
||||
✔ a token file that changes on disk records credential.changed (8.940243ms)
|
||||
✔ autostart polls, reconciles and retries a startup the tracker was down for (31.924571ms)
|
||||
✔ a refusal a restart must clear is not retried by the poll (6.835335ms)
|
||||
✔ a poll that fires while two are queued is dropped (9.018359ms)
|
||||
✔ close waits for a running verb and refuses one that has not started (36.647349ms)
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (29.810424ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (22.960972ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.029927ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.089284ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.13875ms)
|
||||
✔ the bundled Vikunja is the pinned upstream image the runbook names (0.677045ms)
|
||||
✔ every published port is on 127.0.0.1, and no secret is in the file (0.261543ms)
|
||||
✔ the committed table loads frozen; its verbs are the broker task verbs (1.155586ms)
|
||||
✔ a write names a verb the table has as its own key, not one it inherits (0.861613ms)
|
||||
✔ the schema refuses any other shape (1.899372ms)
|
||||
✔ the Field table in the slice 1 plan names the verbs each field is written by (0.512601ms)
|
||||
✔ each verb refuses, asks for a decision and writes as the table and the role files say (144.429003ms)
|
||||
✔ the list holds the PRD's requirement ids, in its order, at its version (1.142054ms)
|
||||
✔ the committed list loads frozen (0.518629ms)
|
||||
✔ the schema refuses any other shape (2.042976ms)
|
||||
✔ the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent (85.481066ms)
|
||||
✔ the project list holds recorded project objects in the recorded list envelope (6.767417ms)
|
||||
✔ the recorded task bodies pass the checks S3 applies to every read (0.424812ms)
|
||||
✔ the client works against the fake over real HTTP with the platform fetch (87.974094ms)
|
||||
✔ a correct install starts, and the first reconcile records tasks that already exist (21.653994ms)
|
||||
✔ verbs refuse while a business is starting and after startup refused it (11.597711ms)
|
||||
✔ startup refuses a token that can do more than its role needs (26.289898ms)
|
||||
✔ startup refuses an unsupported version and flags an untested one (20.072499ms)
|
||||
✔ startup refuses a board that the runbook did not install (24.261388ms)
|
||||
✔ startup refuses a project the sync bot cannot read (5.849053ms)
|
||||
✔ startup refuses a configured label the pm bot cannot see (6.655776ms)
|
||||
✔ startup refuses an expired credential and a missing sync credential (12.40412ms)
|
||||
✔ an unreachable tracker refuses with tracker-unavailable (5.563292ms)
|
||||
✔ an edit in the UI is recorded once, with the fields that changed (69.94148ms)
|
||||
✔ a move between open buckets is seen on the board, though updated does not change (35.909321ms)
|
||||
✔ a person's comment is counted and a bot's is not (62.853184ms)
|
||||
✔ the hourly reconcile catches a comment through comment_count (76.102533ms)
|
||||
✔ a task closed in the UI leaves the open view with its done bucket (113.073443ms)
|
||||
✔ a task that leaves the board is recorded as deleted, moved or out of reach (64.987547ms)
|
||||
✔ a poll that read before a verb wrote does not overwrite the verb (34.105733ms)
|
||||
✔ a tracker fault during a tick is reported and the next tick catches up (35.02089ms)
|
||||
✔ a malformed answer refuses the tick with tracker-shape (12.486665ms)
|
||||
✔ no token value reaches the database, the log or a refusal (44.974769ms)
|
||||
✔ the first look at a task counts only comments inside the window (34.059209ms)
|
||||
✔ with descendants off the adapter reads no project list and no child, as in v0 (40.370536ms)
|
||||
✔ a three-level tree is read per project, and a project outside it is not (17.94978ms)
|
||||
✔ a watch-only child keeps the business ready, and a failed child read refuses as transient (18.32525ms)
|
||||
✔ a root without the installed buckets refuses with descendants on (6.587103ms)
|
||||
✔ the project list refuses without read_all, and skips archived projects and saved filters (14.844219ms)
|
||||
✔ descendants must be true or false (5.93382ms)
|
||||
✔ a move inside the tree is a moved tombstone plus a snapshot under the new ref (57.252789ms)
|
||||
✔ a child made after startup joins the tree at the next reconcile (53.140971ms)
|
||||
✔ a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history (57.885662ms)
|
||||
✔ a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses (80.947918ms)
|
||||
✔ a reconcile that fails keeps the previous tree (32.927837ms)
|
||||
✔ a closed task the cursor missed takes its own project's done bucket (33.615038ms)
|
||||
✔ closed tasks read at startup take their own project's done bucket (9.341405ms)
|
||||
✔ a closed task the cursor returns takes its own project's done bucket (34.752774ms)
|
||||
✔ a task moved out of a child that leaves the tree at the same time is moved, not no-access (30.834171ms)
|
||||
✔ a task in a bucket outside the five keeps its raw bucket id (29.656102ms)
|
||||
✔ bucket 0 on a watch-only task never becomes a bucket or a state (76.741968ms)
|
||||
✔ a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only (55.748787ms)
|
||||
✔ a child dropped at a tick comes back at the next reconcile once the bot reads it again (34.979983ms)
|
||||
✔ task.create needs a recorded human request and a requirement id (34.297269ms)
|
||||
✔ task.create takes only an approved requirement id (19.564207ms)
|
||||
✔ task.create cites the request a received message carries, not the message's id (16.250892ms)
|
||||
✔ only labels named in the business file can be written (21.137117ms)
|
||||
✔ task.schedule sets and clears a due date and relations (28.005657ms)
|
||||
✔ assign and reassign move the role bots and record task.assigned (51.994457ms)
|
||||
✔ task.update.assigned is for the assignee and records task.state (46.675677ms)
|
||||
✔ a wrong expected digest records task.conflict and writes nothing (17.064885ms)
|
||||
✔ a cross-role verb needs a resolved decision, used once (22.344587ms)
|
||||
✔ task.close needs a verdict; after it every verb refuses with task-done (24.522689ms)
|
||||
✔ a task with pushed work closes only citing an approve verdict for its latest push, and a refusal writes nothing (31.878869ms)
|
||||
✔ a lost answer is settled by a re-read and never retried (27.721746ms)
|
||||
✔ a create whose answer is lost is reported uncertain, and the poll finds the task (37.893596ms)
|
||||
✔ a task the sync bot cannot read refuses and records nothing (15.021889ms)
|
||||
✔ verbs and polls for one business run one at a time (86.732867ms)
|
||||
✔ a due date with milliseconds is written to the second (63.735305ms)
|
||||
✔ every write landed and the final read failed: the verb succeeds and records what it wrote (39.704995ms)
|
||||
✔ some writes landed and the final read failed: write-uncertain, and nothing is recorded (17.067921ms)
|
||||
✔ a create whose final read fails succeeds and records task.created (33.621215ms)
|
||||
✔ an edit between the last write and the final read shows as external on the next poll (37.290514ms)
|
||||
✔ task.created is recorded when a later label write fails (14.19622ms)
|
||||
✔ every verb acts in an installed child, on the child's own board (57.975653ms)
|
||||
✔ task.create refuses a project outside the tree, a watch-only one and one that is not an id (27.413353ms)
|
||||
✔ with descendants off, task.create takes only the root project (14.932514ms)
|
||||
✔ a verb on a watch-only task, or a relation to one, refuses with project-not-installed (19.264887ms)
|
||||
✔ a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found (26.325048ms)
|
||||
✔ a task moved to another project of the tree refuses its old ref with task-moved and takes its new one (18.833608ms)
|
||||
✔ a verb and a create in the child record the final read of the child's board (17.350349ms)
|
||||
✔ a create in the child whose final read fails records the child's todo bucket (36.569519ms)
|
||||
✔ a lost answer in the child is settled by a re-read of the child's board (22.820036ms)
|
||||
✔ every related task is read before authority, not only the first (15.502746ms)
|
||||
ℹ tests 97
|
||||
ℹ suites 0
|
||||
ℹ pass 97
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3508.520884
|
||||
@@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"suite": "pkg-bus",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/bus/tests/agents.test.mjs",
|
||||
"packages/bus/tests/broker.test.mjs",
|
||||
"packages/bus/tests/business.test.mjs",
|
||||
"packages/bus/tests/comment-cursors.test.mjs",
|
||||
"packages/bus/tests/comment-migration.test.mjs",
|
||||
"packages/bus/tests/credential-status.test.mjs",
|
||||
"packages/bus/tests/credentials.test.mjs",
|
||||
"packages/bus/tests/decision-close.test.mjs",
|
||||
"packages/bus/tests/decisions.test.mjs",
|
||||
"packages/bus/tests/end-launch.test.mjs",
|
||||
"packages/bus/tests/human.test.mjs",
|
||||
"packages/bus/tests/limits.test.mjs",
|
||||
"packages/bus/tests/message-citation.test.mjs",
|
||||
"packages/bus/tests/messages.test.mjs",
|
||||
"packages/bus/tests/messaging.test.mjs",
|
||||
"packages/bus/tests/process.test.mjs",
|
||||
"packages/bus/tests/replies.test.mjs",
|
||||
"packages/bus/tests/requirements.test.mjs",
|
||||
"packages/bus/tests/review.test.mjs",
|
||||
"packages/bus/tests/schema.test.mjs",
|
||||
"packages/bus/tests/single-use.test.mjs",
|
||||
"packages/bus/tests/state.test.mjs",
|
||||
"packages/bus/tests/store.test.mjs",
|
||||
"packages/bus/tests/task-page.test.mjs",
|
||||
"packages/bus/tests/task-read.test.mjs",
|
||||
"packages/bus/tests/tasks.test.mjs",
|
||||
"packages/bus/tests/tester.test.mjs",
|
||||
"packages/bus/tests/transport.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-tasks",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/tasks/tests/adapter.test.mjs",
|
||||
"packages/tasks/tests/comment-restart.test.mjs",
|
||||
"packages/tasks/tests/deploy.test.mjs",
|
||||
"packages/tasks/tests/fields.test.mjs",
|
||||
"packages/tasks/tests/requirements.test.mjs",
|
||||
"packages/tasks/tests/shapes.test.mjs",
|
||||
"packages/tasks/tests/startup.test.mjs",
|
||||
"packages/tasks/tests/sync.test.mjs",
|
||||
"packages/tasks/tests/tree.test.mjs",
|
||||
"packages/tasks/tests/verbs.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-cli",
|
||||
"exit": 1,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/cli/tests/app.test.mjs",
|
||||
"packages/cli/tests/cli.test.mjs",
|
||||
"packages/cli/tests/config.test.mjs",
|
||||
"packages/cli/tests/follow.test.mjs",
|
||||
"packages/cli/tests/format.test.mjs",
|
||||
"packages/cli/tests/git-socket.test.mjs",
|
||||
"packages/cli/tests/host.test.mjs",
|
||||
"packages/cli/tests/launch-limits.test.mjs",
|
||||
"packages/cli/tests/launcher.test.mjs",
|
||||
"packages/cli/tests/limits.test.mjs",
|
||||
"packages/cli/tests/notifier.test.mjs",
|
||||
"packages/cli/tests/other-tree.test.mjs",
|
||||
"packages/cli/tests/stack-copy.test.mjs",
|
||||
"packages/cli/tests/tester.test.mjs",
|
||||
"packages/cli/tests/trackers-boot.test.mjs",
|
||||
"packages/cli/tests/transport.test.mjs",
|
||||
"packages/cli/tests/verbs.test.mjs"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,184 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (14.694119ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (12.89286ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (20.424092ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (9.132402ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (11.873927ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (9.992559ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (11.295312ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (10.693113ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (56.043313ms)
|
||||
✔ agents: stranded is per role and per business (20.345092ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (7.070457ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (14.224673ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (16.489082ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (14.270655ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (8.710815ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (8.863982ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (13.794059ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (9.316961ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (16.222624ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (7.916002ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (11.696746ms)
|
||||
✔ authority never transfers between action, run, target, unresolved or replaced role holder (15.886532ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (8.649519ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (12.971752ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (8.549761ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (15.07381ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (14.44278ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (1.75302ms)
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (10.960712ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (6.952661ms)
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (39.574068ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (62.383266ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (38.700556ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (10.638403ms)
|
||||
✔ credentials refuses a role session and any argument (10.653125ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (12.093482ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (62.511757ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (2.124537ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (1.285414ms)
|
||||
✔ expiry refuses use and env references never become client data (0.409731ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (0.85467ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.270753ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (24.376591ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (13.51917ms)
|
||||
✔ a human withdraw sends one message with the note (12.688532ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (16.269106ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (17.222917ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (16.841133ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (14.147646ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (12.849278ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (16.630987ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (17.262893ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (17.263886ms)
|
||||
✔ recent stops at RECENT rows (56.30294ms)
|
||||
✔ every row is what trail already gives the same session for that id (24.95038ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (25.964446ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (24.080277ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (11.704294ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (7.712519ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (8.94932ms)
|
||||
✔ endLaunch leaves a claim another run took alone (9.078793ms)
|
||||
✔ refuse records action.refused against the caller with the code only (7.810934ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (14.114655ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (74.818856ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (1.976245ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.400604ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.54122ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.217168ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (14.086882ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (28.517428ms)
|
||||
✔ uncertain organization receipts leave bus startup and reads alone but refuse writes until reconciled (21.114715ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (16.366936ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (10.602507ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (14.280762ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (212.824651ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (17.488634ms)
|
||||
✔ views messages passes only its paging arguments through (0.218161ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (10.881854ms)
|
||||
✔ the assistant sends to the user and to the chief of staff only (23.293826ms)
|
||||
✔ an assistant send to any other role, or to the tester, is refused and logged (19.166302ms)
|
||||
✔ only the user and the chief of staff may send to the assistant; the tester is refused by default (20.14079ms)
|
||||
✔ a sender-side list alone refuses a send to a role that has no list (17.488013ms)
|
||||
✔ a target-side list alone refuses a send from a role that has no list (19.472114ms)
|
||||
✔ the sender list is checked before the target list (15.345074ms)
|
||||
✔ roles without the field behave exactly as before (23.02958ms)
|
||||
✔ a business with no role definitions at all is unlimited (16.800626ms)
|
||||
✔ a malformed messaging field refuses at boot (7.129303ms)
|
||||
✔ the assistant's review.request to a reviewer is refused and logged, even with an approved decision (19.048188ms)
|
||||
✔ a review.verdict to the assistant from a role outside its receiveFrom is refused and logged (21.728873ms)
|
||||
✔ review requests and verdicts between roles without the field are unchanged (17.133732ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (60.584579ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (39.068361ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (53.156504ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (95.132305ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (53.029448ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (38.518948ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (55.638703ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (24.05427ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (11.790717ms)
|
||||
✔ a message with no reply gives an empty list (9.749848ms)
|
||||
✔ replies come oldest first and stop at REPLIES (49.020081ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (17.242349ms)
|
||||
✔ strict arguments; a role session gets human-required (20.040422ms)
|
||||
✔ views passes replies through as one call with the id (0.17781ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (17.088859ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (9.274192ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (9.346127ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (18.541174ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (13.683565ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (15.481336ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (21.449758ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (14.20091ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (17.164639ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (21.917811ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (12.828466ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (52.124371ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (20.392001ms)
|
||||
✔ another run cannot consume an approval; a failed check leaves it usable (12.394165ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (8.925564ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (18.027903ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (12.497191ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (13.265983ms)
|
||||
✔ class drift gated to within-role refuses before consumption (11.931205ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (13.438046ms)
|
||||
✔ class drift within-role to gated refuses before consumption (11.567283ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (11.476235ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (13.519676ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (14.981673ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (11.338474ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (9.122669ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (9.13099ms)
|
||||
✔ a tombstone is not open (7.372573ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (10.999341ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (7.858681ms)
|
||||
✔ a human session reads the same state, with the same cap (9.651601ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (8.325051ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (9.458006ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (8.43887ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (8.189648ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (41.654297ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (5.904631ms)
|
||||
✔ async transactions refuse before invoking their function (4.591316ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (105.127339ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (68.356902ms)
|
||||
✔ each filter, alone and together, and total counts every match (139.12956ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (87.937707ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (66.361452ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (290.162112ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (23.636732ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (26.800046ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (6.38123ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (15.963ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (5.704743ms)
|
||||
✔ a bad entry refuses the whole record (5.600562ms)
|
||||
✔ taskView reads the projection for one business (6.983907ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (13.943232ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (283.245328ms)
|
||||
✔ without an adapter the server refuses every task verb (16.295978ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (15.168253ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (106.696101ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (46.368131ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (12.715382ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (30.073718ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (13.748584ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (16.067521ms)
|
||||
✔ the tester reads the human views a reader reads (16.817791ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.075242ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.334655ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.19747ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (14.562903ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (598.045324ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (19.184394ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (13.08992ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (7.240817ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (11.221426ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (8.82784ms)
|
||||
ℹ tests 176
|
||||
ℹ suites 0
|
||||
ℹ pass 176
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 6095.062239
|
||||
@@ -0,0 +1,336 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1121.652366ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (59.477458ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (146.117245ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (204.950193ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (48.153ms)
|
||||
✔ the app shows the same decide text as mosaic decide (19.759474ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (178.43424ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (62.923265ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (229.986793ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (29.999435ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (18.774058ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (404.340608ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (39.204203ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (29.685824ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (42.891944ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (278.963934ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8145.538976ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (61.287549ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (29.828155ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (14.49415ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (72.306521ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (14.620775ms)
|
||||
✔ no business: the app says so and :business picks one (8.119722ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.805534ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (163.499123ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.452085ms)
|
||||
✔ decide with --note still asks; a No sends nothing (10.275383ms)
|
||||
✔ the app's business comes from a live bus host only (1.131127ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (7.020195ms)
|
||||
✔ draw is pure: same state, same frame (0.769013ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (15.852731ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (12.336739ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (10.039739ms)
|
||||
✔ decide prints a declining choice as declining (9.108848ms)
|
||||
✔ an unknown outcome is reported once and never resent (7.699179ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (7.519771ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (7.122371ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (6.732556ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (6.746574ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (7.562074ms)
|
||||
✔ agents and tasks print through the broker (6.943048ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.054446ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (31.970092ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (55.210151ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (25.950418ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (29.214393ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (26.346839ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (47.981901ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (95.980388ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (24.715319ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (203.091443ms)
|
||||
✔ follow refuses agent context and bad arguments (8.652411ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (8.040659ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (8.780067ms)
|
||||
✔ empty views say so (0.616341ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (0.738756ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.123286ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (283.906056ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (276.134348ms)
|
||||
✔ the size cap refuses a push before any byte (132.427401ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (280.697069ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (138.263086ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (228.07992ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (179.584626ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (175.152991ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (120.845109ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (120.005731ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (541.181635ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (394.674097ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (422.066513ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (40.914244ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (434.231135ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (23.188029ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.328511ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (310.766495ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (816.234292ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (145.779759ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (77.476775ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (443.610958ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.618588ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.750404ms)
|
||||
✔ a live host's lock stays, however old the file is (0.491738ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (651.372967ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (207.314684ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (26.750088ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (29.520666ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (25.660704ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (27.89985ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (75.983713ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (74.439395ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (72.107171ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (78.124904ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (176.101702ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (28.725944ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (75.778323ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (171.803051ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (176.323753ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (169.214461ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1087.406112ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (154.93192ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (76.071655ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (125.563878ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (129.453832ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (81.776118ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (123.790329ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (83.402842ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (138.837902ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (20.956526ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (202.571636ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (235.341987ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (99.530252ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (648.710281ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (55.948587ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (66.913172ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (12.508043ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (7.833353ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (21.935809ms)
|
||||
✖ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (122.745684ms)
|
||||
✖ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (112.830992ms)
|
||||
✖ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (110.494699ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (118.483266ms)
|
||||
✖ a runner that stops at once ends its launch with the runner's reason (114.667119ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (94.581245ms)
|
||||
✖ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (111.305512ms)
|
||||
✖ a runner killed from the host ends its launch as killed, not failed (111.348741ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (92.719059ms)
|
||||
✖ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (117.008533ms)
|
||||
node:fs:3413
|
||||
const stats = binding.lstat(base, true, undefined, true /* throwIfNoEntry */);
|
||||
^
|
||||
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
✖ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (30005.587899ms)
|
||||
node:fs:3413
|
||||
const stats = binding.lstat(base, true, undefined, true /* throwIfNoEntry */);
|
||||
^
|
||||
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
✖ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (30004.900336ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (89.124771ms)
|
||||
|
||||
Interrupted while running:
|
||||
|
||||
⚠ packages/cli/tests/launcher.test.mjs (packages/cli/tests/launcher.test.mjs:1:1)
|
||||
✖ packages/cli/tests/launcher.test.mjs (61320.850548ms)
|
||||
✖ packages/cli/tests/limits.test.mjs
|
||||
✖ packages/cli/tests/notifier.test.mjs
|
||||
✖ packages/cli/tests/other-tree.test.mjs
|
||||
✖ packages/cli/tests/stack-copy.test.mjs
|
||||
✖ packages/cli/tests/tester.test.mjs
|
||||
✖ packages/cli/tests/trackers-boot.test.mjs
|
||||
✖ packages/cli/tests/transport.test.mjs
|
||||
✖ packages/cli/tests/verbs.test.mjs
|
||||
ℹ tests 139
|
||||
ℹ suites 0
|
||||
ℹ pass 121
|
||||
ℹ fail 7
|
||||
ℹ cancelled 11
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 85300.300681
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:134:1
|
||||
✖ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (122.745684ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:214:1
|
||||
✖ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (112.830992ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:296:1
|
||||
✖ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (110.494699ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:370:1
|
||||
✖ a runner that stops at once ends its launch with the runner's reason (114.667119ms)
|
||||
AssertionError [ERR_ASSERTION]: {"ok":false,"error":"launch-failed"}
|
||||
|
||||
false !== true
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/tests/launcher.test.mjs:381:10)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: false,
|
||||
expected: true,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:405:1
|
||||
✖ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (111.305512ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:418:1
|
||||
✖ a runner killed from the host ends its launch as killed, not failed (111.348741ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:452:1
|
||||
✖ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (117.008533ms)
|
||||
Error: ENOENT: no such file or directory, lstat '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
at realpathSync (node:fs:3413:29)
|
||||
at binds (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/sandbox.mjs:103:53)
|
||||
at spawnSession (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/seat/src/session.mjs:117:28)
|
||||
at start (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:257:19)
|
||||
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
|
||||
at async file:///mnt/storage/src/mosaic-stack-rocko-49/packages/cli/src/launcher.mjs:355:16 {
|
||||
errno: -2,
|
||||
code: 'ENOENT',
|
||||
syscall: 'lstat',
|
||||
path: '/mnt/storage/src/mosaic-stack-rocko-49/node_modules'
|
||||
}
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:511:3
|
||||
✖ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (30005.587899ms)
|
||||
'test timed out after 30000ms'
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:511:3
|
||||
✖ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (30004.900336ms)
|
||||
'test timed out after 30000ms'
|
||||
|
||||
test at packages/cli/tests/launcher.test.mjs:1:1
|
||||
✖ packages/cli/tests/launcher.test.mjs (61320.850548ms)
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/limits.test.mjs:1:1
|
||||
✖ packages/cli/tests/limits.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/notifier.test.mjs:1:1
|
||||
✖ packages/cli/tests/notifier.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/other-tree.test.mjs:1:1
|
||||
✖ packages/cli/tests/other-tree.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/stack-copy.test.mjs:1:1
|
||||
✖ packages/cli/tests/stack-copy.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/tester.test.mjs:1:1
|
||||
✖ packages/cli/tests/tester.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/trackers-boot.test.mjs:1:1
|
||||
✖ packages/cli/tests/trackers-boot.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/transport.test.mjs:1:1
|
||||
✖ packages/cli/tests/transport.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
|
||||
test at packages/cli/tests/verbs.test.mjs:1:1
|
||||
✖ packages/cli/tests/verbs.test.mjs
|
||||
'Promise resolution is still pending but the event loop has already resolved'
|
||||
@@ -0,0 +1,105 @@
|
||||
✔ the boot config is checked before anything starts (17.314653ms)
|
||||
✔ a business with no tracker entry refuses task verbs (9.867916ms)
|
||||
✔ credential.expiring and .expired are recorded once per instance (24.030637ms)
|
||||
✔ a token file that changes on disk records credential.changed (9.455372ms)
|
||||
✔ autostart polls, reconciles and retries a startup the tracker was down for (32.01509ms)
|
||||
✔ a refusal a restart must clear is not retried by the poll (7.036527ms)
|
||||
✔ a poll that fires while two are queued is dropped (8.646611ms)
|
||||
✔ close waits for a running verb and refuses one that has not started (37.225278ms)
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (29.746394ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (22.759438ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.261345ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.632204ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.419375ms)
|
||||
✔ the bundled Vikunja is the pinned upstream image the runbook names (0.656992ms)
|
||||
✔ every published port is on 127.0.0.1, and no secret is in the file (0.241034ms)
|
||||
✔ the committed table loads frozen; its verbs are the broker task verbs (1.150872ms)
|
||||
✔ a write names a verb the table has as its own key, not one it inherits (0.861983ms)
|
||||
✔ the schema refuses any other shape (1.861007ms)
|
||||
✔ the Field table in the slice 1 plan names the verbs each field is written by (0.510398ms)
|
||||
✔ each verb refuses, asks for a decision and writes as the table and the role files say (143.018095ms)
|
||||
✔ the list holds the PRD's requirement ids, in its order, at its version (1.113812ms)
|
||||
✔ the committed list loads frozen (0.500614ms)
|
||||
✔ the schema refuses any other shape (2.155739ms)
|
||||
✔ the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent (90.592343ms)
|
||||
✔ the project list holds recorded project objects in the recorded list envelope (7.293815ms)
|
||||
✔ the recorded task bodies pass the checks S3 applies to every read (0.412698ms)
|
||||
✔ the client works against the fake over real HTTP with the platform fetch (85.845387ms)
|
||||
✔ a correct install starts, and the first reconcile records tasks that already exist (21.689257ms)
|
||||
✔ verbs refuse while a business is starting and after startup refused it (11.299043ms)
|
||||
✔ startup refuses a token that can do more than its role needs (29.850515ms)
|
||||
✔ startup refuses an unsupported version and flags an untested one (21.198916ms)
|
||||
✔ startup refuses a board that the runbook did not install (24.825318ms)
|
||||
✔ startup refuses a project the sync bot cannot read (5.746162ms)
|
||||
✔ startup refuses a configured label the pm bot cannot see (6.837196ms)
|
||||
✔ startup refuses an expired credential and a missing sync credential (13.084053ms)
|
||||
✔ an unreachable tracker refuses with tracker-unavailable (5.67549ms)
|
||||
✔ an edit in the UI is recorded once, with the fields that changed (72.569399ms)
|
||||
✔ a move between open buckets is seen on the board, though updated does not change (35.79823ms)
|
||||
✔ a person's comment is counted and a bot's is not (63.964905ms)
|
||||
✔ the hourly reconcile catches a comment through comment_count (76.335641ms)
|
||||
✔ a task closed in the UI leaves the open view with its done bucket (110.958185ms)
|
||||
✔ a task that leaves the board is recorded as deleted, moved or out of reach (63.554461ms)
|
||||
✔ a poll that read before a verb wrote does not overwrite the verb (33.754481ms)
|
||||
✔ a tracker fault during a tick is reported and the next tick catches up (34.762895ms)
|
||||
✔ a malformed answer refuses the tick with tracker-shape (11.816672ms)
|
||||
✔ no token value reaches the database, the log or a refusal (43.91509ms)
|
||||
✔ the first look at a task counts only comments inside the window (33.646394ms)
|
||||
✔ with descendants off the adapter reads no project list and no child, as in v0 (40.168944ms)
|
||||
✔ a three-level tree is read per project, and a project outside it is not (17.843699ms)
|
||||
✔ a watch-only child keeps the business ready, and a failed child read refuses as transient (16.743518ms)
|
||||
✔ a root without the installed buckets refuses with descendants on (6.281475ms)
|
||||
✔ the project list refuses without read_all, and skips archived projects and saved filters (14.185193ms)
|
||||
✔ descendants must be true or false (5.62954ms)
|
||||
✔ a move inside the tree is a moved tombstone plus a snapshot under the new ref (56.395762ms)
|
||||
✔ a child made after startup joins the tree at the next reconcile (53.335585ms)
|
||||
✔ a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history (56.5104ms)
|
||||
✔ a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses (81.451576ms)
|
||||
✔ a reconcile that fails keeps the previous tree (32.643014ms)
|
||||
✔ a closed task the cursor missed takes its own project's done bucket (31.653772ms)
|
||||
✔ closed tasks read at startup take their own project's done bucket (9.184182ms)
|
||||
✔ a closed task the cursor returns takes its own project's done bucket (33.400693ms)
|
||||
✔ a task moved out of a child that leaves the tree at the same time is moved, not no-access (29.907575ms)
|
||||
✔ a task in a bucket outside the five keeps its raw bucket id (28.577174ms)
|
||||
✔ bucket 0 on a watch-only task never becomes a bucket or a state (76.341918ms)
|
||||
✔ a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only (54.965019ms)
|
||||
✔ a child dropped at a tick comes back at the next reconcile once the bot reads it again (33.686472ms)
|
||||
✔ task.create needs a recorded human request and a requirement id (29.360773ms)
|
||||
✔ task.create takes only an approved requirement id (18.272543ms)
|
||||
✔ task.create cites the request a received message carries, not the message's id (13.451082ms)
|
||||
✔ only labels named in the business file can be written (19.43598ms)
|
||||
✔ task.schedule sets and clears a due date and relations (23.332302ms)
|
||||
✔ assign and reassign move the role bots and record task.assigned (46.778211ms)
|
||||
✔ task.update.assigned is for the assignee and records task.state (44.090524ms)
|
||||
✔ a wrong expected digest records task.conflict and writes nothing (15.197261ms)
|
||||
✔ a cross-role verb needs a resolved decision, used once (21.459156ms)
|
||||
✔ task.close needs a verdict; after it every verb refuses with task-done (21.028012ms)
|
||||
✔ a task with pushed work closes only citing an approve verdict for its latest push, and a refusal writes nothing (26.448783ms)
|
||||
✔ a lost answer is settled by a re-read and never retried (22.128748ms)
|
||||
✔ a create whose answer is lost is reported uncertain, and the poll finds the task (33.937822ms)
|
||||
✔ a task the sync bot cannot read refuses and records nothing (13.426948ms)
|
||||
✔ verbs and polls for one business run one at a time (86.31078ms)
|
||||
✔ a due date with milliseconds is written to the second (63.596374ms)
|
||||
✔ every write landed and the final read failed: the verb succeeds and records what it wrote (36.948559ms)
|
||||
✔ some writes landed and the final read failed: write-uncertain, and nothing is recorded (13.622195ms)
|
||||
✔ a create whose final read fails succeeds and records task.created (33.518094ms)
|
||||
✔ an edit between the last write and the final read shows as external on the next poll (38.267517ms)
|
||||
✔ task.created is recorded when a later label write fails (13.10961ms)
|
||||
✔ every verb acts in an installed child, on the child's own board (47.289399ms)
|
||||
✔ task.create refuses a project outside the tree, a watch-only one and one that is not an id (23.243708ms)
|
||||
✔ with descendants off, task.create takes only the root project (11.790128ms)
|
||||
✔ a verb on a watch-only task, or a relation to one, refuses with project-not-installed (15.761532ms)
|
||||
✔ a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found (21.308136ms)
|
||||
✔ a task moved to another project of the tree refuses its old ref with task-moved and takes its new one (14.192795ms)
|
||||
✔ a verb and a create in the child record the final read of the child's board (13.558827ms)
|
||||
✔ a create in the child whose final read fails records the child's todo bucket (31.934289ms)
|
||||
✔ a lost answer in the child is settled by a re-read of the child's board (20.832798ms)
|
||||
✔ every related task is read before authority, not only the first (14.551685ms)
|
||||
ℹ tests 97
|
||||
ℹ suites 0
|
||||
ℹ pass 97
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3405.838395
|
||||
@@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"suite": "pkg-bus",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/bus/tests/agents.test.mjs",
|
||||
"packages/bus/tests/broker.test.mjs",
|
||||
"packages/bus/tests/business.test.mjs",
|
||||
"packages/bus/tests/comment-cursors.test.mjs",
|
||||
"packages/bus/tests/comment-migration.test.mjs",
|
||||
"packages/bus/tests/credential-status.test.mjs",
|
||||
"packages/bus/tests/credentials.test.mjs",
|
||||
"packages/bus/tests/decision-close.test.mjs",
|
||||
"packages/bus/tests/decisions.test.mjs",
|
||||
"packages/bus/tests/end-launch.test.mjs",
|
||||
"packages/bus/tests/human.test.mjs",
|
||||
"packages/bus/tests/limits.test.mjs",
|
||||
"packages/bus/tests/message-citation.test.mjs",
|
||||
"packages/bus/tests/messages.test.mjs",
|
||||
"packages/bus/tests/messaging.test.mjs",
|
||||
"packages/bus/tests/process.test.mjs",
|
||||
"packages/bus/tests/replies.test.mjs",
|
||||
"packages/bus/tests/requirements.test.mjs",
|
||||
"packages/bus/tests/review.test.mjs",
|
||||
"packages/bus/tests/schema.test.mjs",
|
||||
"packages/bus/tests/single-use.test.mjs",
|
||||
"packages/bus/tests/state.test.mjs",
|
||||
"packages/bus/tests/store.test.mjs",
|
||||
"packages/bus/tests/task-page.test.mjs",
|
||||
"packages/bus/tests/task-read.test.mjs",
|
||||
"packages/bus/tests/tasks.test.mjs",
|
||||
"packages/bus/tests/tester.test.mjs",
|
||||
"packages/bus/tests/transport.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-tasks",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/tasks/tests/adapter.test.mjs",
|
||||
"packages/tasks/tests/comment-restart.test.mjs",
|
||||
"packages/tasks/tests/deploy.test.mjs",
|
||||
"packages/tasks/tests/fields.test.mjs",
|
||||
"packages/tasks/tests/requirements.test.mjs",
|
||||
"packages/tasks/tests/shapes.test.mjs",
|
||||
"packages/tasks/tests/startup.test.mjs",
|
||||
"packages/tasks/tests/sync.test.mjs",
|
||||
"packages/tasks/tests/tree.test.mjs",
|
||||
"packages/tasks/tests/verbs.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-cli",
|
||||
"exit": 1,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/cli/tests/app.test.mjs",
|
||||
"packages/cli/tests/cli.test.mjs",
|
||||
"packages/cli/tests/config.test.mjs",
|
||||
"packages/cli/tests/follow.test.mjs",
|
||||
"packages/cli/tests/format.test.mjs",
|
||||
"packages/cli/tests/git-socket.test.mjs",
|
||||
"packages/cli/tests/host.test.mjs",
|
||||
"packages/cli/tests/launch-limits.test.mjs",
|
||||
"packages/cli/tests/launcher.test.mjs",
|
||||
"packages/cli/tests/limits.test.mjs",
|
||||
"packages/cli/tests/notifier.test.mjs",
|
||||
"packages/cli/tests/other-tree.test.mjs",
|
||||
"packages/cli/tests/stack-copy.test.mjs",
|
||||
"packages/cli/tests/tester.test.mjs",
|
||||
"packages/cli/tests/trackers-boot.test.mjs",
|
||||
"packages/cli/tests/transport.test.mjs",
|
||||
"packages/cli/tests/verbs.test.mjs"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
import json, os, pathlib, signal, subprocess, sys
|
||||
root=pathlib.Path('/mnt/storage/src/mosaic-stack-rocko-49')
|
||||
out=pathlib.Path(__file__).resolve().parent/'gate';out.mkdir(exist_ok=True)
|
||||
steps=[]
|
||||
for package in ['bus','tasks','cli','webui','harness','seat']:
|
||||
files=[str(f.relative_to(root)) for f in sorted((root/'packages'/package/'tests').glob('*.test.mjs'))]
|
||||
steps.append(('pkg-'+package,['node','--test','--test-concurrency=1','--test-reporter=spec',*files]))
|
||||
steps.append(('script-land-work',['bash','scripts/test-land-work.sh']))
|
||||
results=[]
|
||||
for name,command in steps:
|
||||
with (out/(name+'.log')).open('w') as log:
|
||||
p=subprocess.Popen(command,cwd=root,env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'},
|
||||
stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try: rc=p.wait(timeout=1200)
|
||||
except subprocess.TimeoutExpired: os.killpg(p.pid,signal.SIGKILL);p.wait();rc='timeout'
|
||||
results.append(dict(suite=name,exit=rc,command=command))
|
||||
(out/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
print(name,rc,flush=True)
|
||||
if rc!=0:sys.exit(1)
|
||||
@@ -0,0 +1,186 @@
|
||||
✔ agents: a held role with nothing on the bus is idle; a role session gets the claim rows unchanged (18.0726ms)
|
||||
✔ agents: working counts what the holder received and has not read; routed alone is not working (16.776875ms)
|
||||
✔ agents: input needed is the role's open decisions routed to the human, gated first, then oldest (24.937642ms)
|
||||
✔ agents: working wins over waiting, and Input needed still shows (9.117675ms)
|
||||
✔ agents: a new holder doesn't inherit what the last one left unread; decisions stay with the role (12.753115ms)
|
||||
✔ agents: state reads only its own business, even for a run name both use (10.434423ms)
|
||||
✔ agents: a message the holder released unread is stranded; the next holder gets nothing and cannot read it (12.176738ms)
|
||||
✔ agents: a message the holder read is not stranded; one the current holder has not read is not listed (11.508931ms)
|
||||
✔ agents: stranded is oldest first and capped at 50 for a role (57.594964ms)
|
||||
✔ agents: stranded is per role and per business (19.58298ms)
|
||||
✔ agents: a message routed to a held role and not yet received is not stranded (7.386457ms)
|
||||
✔ launch identity is stamped, payload identity is refused and stale holder cannot send (13.82679ms)
|
||||
✔ decision classes route from policy; gated resolution is human-only, choice and target must match (14.656152ms)
|
||||
✔ claim exclusion, holder release, gated revoke and rerouting to a new holder are atomic (15.460275ms)
|
||||
✔ launch events require a human CLI capability; generic emit cannot forge authority events (9.493622ms)
|
||||
✔ within-role decisions close atomically and invalid options or blocking omissions refuse (9.439881ms)
|
||||
✔ a recommendation that is not exactly one option key refuses invalid-recommendation after the options (14.313793ms)
|
||||
✔ observer capabilities read human inbox but cannot mutate or forge launch identity (8.894824ms)
|
||||
✔ task action subjects and linked decision trail are complete and ordered (15.796502ms)
|
||||
✔ launch binding is durable and reconnecting requires the identical trusted record (6.699842ms)
|
||||
✔ business isolation includes inherited object names and cross-business message references (10.833233ms)
|
||||
✔ authority never transfers between action, run, target, unresolved or replaced role holder (14.850575ms)
|
||||
✔ task projection uses schema current view, skipping earlier and equal-start polls (7.737827ms)
|
||||
✔ revocation permanently bars the old run from reclaiming first, including after broker restart (11.98167ms)
|
||||
✔ empty message references refuse before storage; refusal-evidence failure stays a typed error (7.834072ms)
|
||||
✔ both arbiters require human resolution when their cross-role route is themselves (14.377512ms)
|
||||
✔ the shipped coder role raises task.reassign as gated to the human; task.scope.change stays cross-role (12.965967ms)
|
||||
✔ S1 adapter takes resolved limits and refs, rejects mismatched instance, never mutates input (1.188116ms)
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (11.96074ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.297847ms)
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (34.747403ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (58.865301ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (36.594311ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (28.983697ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (104.329457ms)
|
||||
✔ credentials gives human and reader sessions service, account, role, date and state, and nothing else (10.460845ms)
|
||||
✔ credentials refuses a role session and any argument (10.127004ms)
|
||||
✔ credentials reads the status on each request, and a broker without one lists none (10.839449ms)
|
||||
✔ the broker process answers credentials without a token, path or variable in its output, log or store (57.610412ms)
|
||||
✔ only validated broker references load; returned data and exceptions cannot expose a known token (2.262147ms)
|
||||
✔ bad file modes, symlinks, repository/data paths, malformed tokens and missing dates refuse (1.249245ms)
|
||||
✔ expiry refuses use and env references never become client data (0.427206ms)
|
||||
✔ S1 parsed service refs work, service mismatch refuses, Gitea rotation due is a warning state (0.953329ms)
|
||||
✔ opaque tokens shorter than 16 characters refuse before use (0.214693ms)
|
||||
✔ a human resolve sends the raising role one message from the human, and its request is the answer (23.929128ms)
|
||||
✔ a cross-role decision resolved by its arbiter comes from that role and run, with no request (13.563597ms)
|
||||
✔ a human withdraw sends one message with the note (12.756137ms)
|
||||
✔ a human seen before the close leaves the request on the close's answer, not the seen (17.74069ms)
|
||||
✔ the raising run's withdraw, a supersede, a within-role raise and seen send nothing (17.912782ms)
|
||||
✔ refused closes send nothing: invalid-choice, decision-closed, not-resolver (16.668141ms)
|
||||
✔ a raising role nobody holds at the close gets the message on the next claim (15.234374ms)
|
||||
✔ a human DECISION send keeps its own instruction as the request, not a close's answer (13.830529ms)
|
||||
✔ roles lists open decisions routed to a role, and never the human inbox (18.105779ms)
|
||||
✔ recent lists closed decisions of every route, newest close first, with how each closed (17.245748ms)
|
||||
✔ recent gives the closing event as closed when the decision was seen first (18.513671ms)
|
||||
✔ recent stops at RECENT rows (57.367473ms)
|
||||
✔ every row is what trail already gives the same session for that id (23.302507ms)
|
||||
✔ a role session can't list decisions, so it can't read another role's open decisions (22.351858ms)
|
||||
✔ decisions is a read: one business, strict arguments, nothing written (22.233524ms)
|
||||
✔ endLaunch writes session.ended, releases the run claim and kills its capabilities (11.680833ms)
|
||||
✔ endLaunch refuses an unknown run, a second end and a rebind of the ended run (7.152513ms)
|
||||
✔ a restarted broker refuses to rebind an ended run; a refused rebind leaves the run unbound (8.397838ms)
|
||||
✔ endLaunch leaves a claim another run took alone (8.773063ms)
|
||||
✔ refuse records action.refused against the caller with the code only (6.435292ms)
|
||||
✔ launches off refuses role.launch with launch-revoked until launches on (10.257184ms)
|
||||
✔ broker process: launch ops authorize role.launch, record refusals and end runs (71.203905ms)
|
||||
✔ human proof binds CLI entry, process start and nonce; agents and incomplete ancestry refuse (1.275133ms)
|
||||
✔ process reader gets own kernel identity without exposing environment values (0.36235ms)
|
||||
✔ EACCES ancestor environments skip only markers; commands and registered launches still refuse (0.520996ms)
|
||||
✔ real pid 1 remains inspectable when its environment is protected (0.220532ms)
|
||||
✔ limits binds actor from human proof and rejects role, reader, tester and forged actor (14.739915ms)
|
||||
✔ runtime wires verified human settings to the actual shared file writer and actor receipt (29.022343ms)
|
||||
✔ uncertain organization receipts leave bus startup and reads alone but refuse writes until reconciled (21.969682ms)
|
||||
✔ within-role sends cite an open gated launch decision without spending it or naming it in grants (17.326368ms)
|
||||
✔ missing and foreign-business citations refuse and roll back message and grant (10.62723ms)
|
||||
✔ cross-role sends still need a matching resolved decision and consume it once (13.429227ms)
|
||||
✔ messages pages all human messages newest first without writes; read state is history (212.444232ms)
|
||||
✔ messages refuses role callers, invalid paging and cursors outside this human feed (15.746617ms)
|
||||
✔ views messages passes only its paging arguments through (0.215112ms)
|
||||
✔ messages isolates businesses even with a valid foreign cursor (9.893388ms)
|
||||
✔ the assistant sends to the user and to the chief of staff only (24.17533ms)
|
||||
✔ an assistant send to any other role, or to the tester, is refused and logged (19.08546ms)
|
||||
✔ only the user and the chief of staff may send to the assistant; the tester is refused by default (17.153132ms)
|
||||
✔ a sender-side list alone refuses a send to a role that has no list (15.733558ms)
|
||||
✔ a target-side list alone refuses a send from a role that has no list (17.260187ms)
|
||||
✔ the sender list is checked before the target list (13.642779ms)
|
||||
✔ roles without the field behave exactly as before (22.778491ms)
|
||||
✔ a business with no role definitions at all is unlimited (16.397702ms)
|
||||
✔ a malformed messaging field refuses at boot (7.386471ms)
|
||||
✔ the assistant's review.request to a reviewer is refused and logged, even with an approved decision (18.115621ms)
|
||||
✔ a review.verdict to the assistant from a role outside its receiveFrom is refused and logged (19.232548ms)
|
||||
✔ review requests and verdicts between roles without the field are unchanged (15.344471ms)
|
||||
✔ broker process binds trusted launches, offers reader capabilities, refuses human mutation, closes cleanly (60.188823ms)
|
||||
✔ startup token refusal returns safe code without value or partial listening broker (45.226238ms)
|
||||
✔ loaded fixture token is absent from socket replies and SQLite, including refusal evidence (58.129808ms)
|
||||
✔ killed broker leaves an explicit stale lock; another process cannot silently reclaim it (91.555498ms)
|
||||
✔ trusted host registers later launches; socket clients never have a registration verb (56.357222ms)
|
||||
✔ runtime excludes declared project roots even when host supplies no repoRoots (44.970952ms)
|
||||
✔ a refused launch binding leaves the broker and existing capabilities alive; bad protocol stops it (56.559453ms)
|
||||
✔ a reply is listed for human and reader sessions, and its delivery rows are unchanged (22.08921ms)
|
||||
✔ the reply still reaches the human message.receive (mosaic talk) after the Console showed it (10.970058ms)
|
||||
✔ a message with no reply gives an empty list (8.543807ms)
|
||||
✔ replies come oldest first and stop at REPLIES (48.281659ms)
|
||||
✔ an id that names no message in the business refuses message-not-found, and the refusal is recorded (17.776643ms)
|
||||
✔ strict arguments; a role session gets human-required (19.600949ms)
|
||||
✔ views passes replies through as one call with the id (0.178546ms)
|
||||
✔ requirements returns the committed list to a holding role session, and no one else (15.733467ms)
|
||||
✔ the PM's prd.approve with no task, when no id fits, reaches the human's Inbox (8.661343ms)
|
||||
✔ the PM's non-blocking role.revoke with no task reaches the human's Inbox (9.270735ms)
|
||||
✔ a push is recorded as the action.allowed for git.push.working on the task, and only the host records one (18.153079ms)
|
||||
✔ review.request names the latest pushed commit and sends the reviewer a REVIEW-REQUEST (13.658961ms)
|
||||
✔ review.request says which run holds the reviewer role, or null, and a null request waits for a claim (15.20457ms)
|
||||
✔ review.request refuses a commit that isn't the latest push, a non-reviewer and a role without the action (21.463462ms)
|
||||
✔ reviewFetch answers only the addressed reviewer, for the request it cites (14.14993ms)
|
||||
✔ review.verdict answers one request once, to the role that asked (16.165243ms)
|
||||
✔ task.close on a pushed task needs an approve verdict for the latest push (22.189753ms)
|
||||
✔ a refusal the host decided is filed on the task it names, and only a task ref counts (12.421543ms)
|
||||
✔ v3b prototype refusals, views and append-only mutations (50.185231ms)
|
||||
✔ gated approval authorizes once, survives store reopen, and fresh approval works (18.659864ms)
|
||||
✔ another run cannot consume an approval; a failed check leaves it usable (12.007889ms)
|
||||
✔ two scheduled callers have exactly one grant and one consumed refusal (8.555251ms)
|
||||
✔ failed commit rolls consumption back; cross-role consumes and within-role stays reusable (18.745599ms)
|
||||
✔ class drift gated to cross-role refuses before consumption (12.004218ms)
|
||||
✔ class drift cross-role to gated refuses before consumption (12.864003ms)
|
||||
✔ class drift gated to within-role refuses before consumption (11.826685ms)
|
||||
✔ class drift cross-role to within-role refuses before consumption (13.016785ms)
|
||||
✔ class drift within-role to gated refuses before consumption (10.665639ms)
|
||||
✔ class drift within-role to cross-role refuses before consumption (10.700153ms)
|
||||
✔ message.send consumes approval and prevents a later send or authorize (12.96513ms)
|
||||
✔ role.revoke consumes approval and prevents a later revoke or authorize (17.747564ms)
|
||||
✔ a business that never switched launches reads allowed with no time and no event (11.412878ms)
|
||||
✔ launches revoked and then restored read allowed, with the restore time and event id (8.703518ms)
|
||||
✔ a task closed on the tracker leaves the open list, and total counts the open ones (9.033301ms)
|
||||
✔ a tombstone is not open (7.110312ms)
|
||||
✔ the open list stops at the cap and says so; total still counts every open task (10.125157ms)
|
||||
✔ a role and a reader session read state; arguments, and an unbound cap, refuse (7.518531ms)
|
||||
✔ a human session reads the same state, with the same cap (9.592429ms)
|
||||
✔ reading state writes nothing: every table keeps its row count (8.161166ms)
|
||||
✔ creates private WAL store and excludes a second writer until explicit close (9.837253ms)
|
||||
✔ rollback is atomic and schema metadata is checked against trusted DDL, not just itself (9.425037ms)
|
||||
✔ existing empty database and symlink runtime directory refuse, never initialize over damage (8.94876ms)
|
||||
✔ crash during a transaction recovers no partial event after explicit fixture-only lock removal (41.720607ms)
|
||||
✔ writer refuses mixed at/read_at forms atomically, even through trusted SQL helpers (6.583885ms)
|
||||
✔ async transactions refuse before invoking their function (4.979465ms)
|
||||
✔ the session default fits under the reply cap and pages to the end with next (107.357709ms)
|
||||
✔ the short form: no description, assignees by role, every listed key (64.790404ms)
|
||||
✔ each filter, alone and together, and total counts every match (138.579347ms)
|
||||
✔ task_ref reads one task in full, as the whole board has it (80.646442ms)
|
||||
✔ no arguments is the read the Console and mosaic make, unchanged (65.713235ms)
|
||||
✔ an unknown argument or a bad value refuses invalid-request (304.09939ms)
|
||||
✔ tasks rows carry priority and requirement for every session that reads tasks (24.861154ms)
|
||||
✔ the read model rebuilds from the ledger: a reopened bus and each trail give the same values (27.823064ms)
|
||||
✔ an empty business and one with snapshots but no task.created read cleanly (5.980928ms)
|
||||
✔ recordTask keeps sync reads and a role write apart (15.120671ms)
|
||||
✔ read_at must be one canonical UTC format, so the projection compares strings safely (5.83325ms)
|
||||
✔ a bad entry refuses the whole record (6.421079ms)
|
||||
✔ taskView reads the projection for one business (7.42201ms)
|
||||
✔ requestTask hands only a holder and a task verb to the handler, and records refusals (14.07288ms)
|
||||
✔ the server sends task verbs to the adapter with its own timeout; other verbs stay synchronous (281.792883ms)
|
||||
✔ without an adapter the server refuses every task verb (15.442981ms)
|
||||
✔ the runtime refuses an invalid adapter and closes a valid one (15.132483ms)
|
||||
✔ the process loads the S3 adapter from plain-data trackers (110.2661ms)
|
||||
✔ the tester binds only when the business sets bus.tester to exactly true (48.995999ms)
|
||||
✔ a business may not name a role tester, so the tester address is never a role (12.908115ms)
|
||||
✔ every verb outside the tester list refuses tester-refused and is recorded against the tester (30.857581ms)
|
||||
✔ a tester message is from tester, starts [mos test], and writes no human.input or authority (12.951493ms)
|
||||
✔ a role answers a tester only in reply to a tester message, and the answer never reaches the human (15.772385ms)
|
||||
✔ the tester reads the human views a reader reads (17.064712ms)
|
||||
✔ tester proof binds its own CLI, start time and nonce, refuses a managed run and allows an agent (1.082345ms)
|
||||
✔ neither CLI's nonce proves the other: each proof is bound to its own CLI and nonce variable (0.327914ms)
|
||||
✔ testerNonce reads only the tester's variable and gives null on any read error (0.187745ms)
|
||||
✔ an envelope carries exactly one of cap, human and tester; no tester authenticator refuses (14.905855ms)
|
||||
✔ tester-cli.mjs binds through the runtime when the switch is on, and refuses off or under a run marker (591.41324ms)
|
||||
✔ socket capability stamps launch identity; shared views use wire, no SQL client (19.098642ms)
|
||||
✔ two wire claims serialize; a lost reply never automatically retries (14.182425ms)
|
||||
✔ malformed, oversized and identity-forging envelopes refuse without echoing input (8.354323ms)
|
||||
✔ client preserves UTF-8 when a response divides a multibyte character (11.250544ms)
|
||||
✔ committed mutation followed by dropped reply reports unknown and is never retried (8.891815ms)
|
||||
ℹ tests 178
|
||||
ℹ suites 0
|
||||
ℹ pass 178
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 6225.595082
|
||||
@@ -0,0 +1,205 @@
|
||||
✔ every screen and overlay fits 120x36, 80x24 and the narrow layout, row for row (1131.456583ms)
|
||||
✔ width counts terminal cells: wide CJK and emoji 2, U+FE0F after a one-cell base 1, marks 0 (58.120119ms)
|
||||
✔ broker text is shown, never interpreted: no raw control character or bidi override reaches the terminal (139.421181ms)
|
||||
✔ NO_COLOR: no escape codes, except reverse video on the selected row (207.952015ms)
|
||||
✔ 1-9 shows the decide flow's own lines and question; only y resolves (48.636173ms)
|
||||
✔ the app shows the same decide text as mosaic decide (21.134775ms)
|
||||
✔ any key but y or Y at the question answers No; nothing is sent (174.770503ms)
|
||||
✔ below 40x10 the question is hidden, so every key answers it No, y included (Filbert R3) (57.007814ms)
|
||||
✔ under 40 columns a tall terminal shows the too-small screen even where the decide box would fit; y sends nothing (Filbert N10) (222.375161ms)
|
||||
✔ a hidden decide box names the way out, and the status line under it does not promise y (Filbert N12) (30.408824ms)
|
||||
✔ a throw while answering the question goes to crash, sends nothing and leaves no job pending (19.44225ms)
|
||||
✔ type-ahead never answers the question: a paste, keys typed before it is drawn, keys inside askMs (390.416391ms)
|
||||
✔ quitting at the question answers No and sends nothing, armed or not (29.532601ms)
|
||||
✔ a timer tick reads nothing under an overlay, never answers the question, and keeps a resolved status (28.662636ms)
|
||||
✔ a long question is cut inside the question; the action, target, choice and prompt stay (Dewey B1) (44.476171ms)
|
||||
✔ a decide box too big for the terminal says so, and every key answers it No, y included (Dewey B1, round 3) (290.460586ms)
|
||||
✔ at every size the decide box shows each line y depends on, or says it is hidden (8077.378001ms)
|
||||
✔ outcome unknown: the CLI's sentence, no retry, then the trail or a re-read (63.021149ms)
|
||||
✔ refused and failed reads keep the last list, marked stale; a refused decide says refused (30.974953ms)
|
||||
✔ help or a detail box cut to fit keeps its last line, Esc included (Dewey) (14.54113ms)
|
||||
✔ keys: views, moving, trail of a selection, the command line, help and quit (75.983753ms)
|
||||
✔ one option: the status line says Press 1, not 1-1 (16.057421ms)
|
||||
✔ no business: the app says so and :business picks one (8.431433ms)
|
||||
✔ mosaic with no argument: exit 3 in an agent run, exit 4 with the usage off a terminal, the app on one (1.768245ms)
|
||||
✔ scripts/mosaic with no argument reaches the app entry; the seat usage it printed before has not drifted (169.495219ms)
|
||||
✔ strings to keep exactly live once, in the decide flow and the transport; the app does not restate them (0.400948ms)
|
||||
✔ decide with --note still asks; a No sends nothing (9.521648ms)
|
||||
✔ the app's business comes from a live bus host only (0.988477ms)
|
||||
✔ runApp leaves the terminal as it found it on q, end of input, SIGTERM, SIGINT, SIGHUP and an error, the first frame's included (6.857319ms)
|
||||
✔ draw is pure: same state, same frame (0.734297ms)
|
||||
✔ inbox lists only decisions routed to the human, with what approving authorizes and how to decide (14.596726ms)
|
||||
✔ decide resolves by id prefix with --yes, and the trail shows it in broker order with the task to follow (11.216971ms)
|
||||
✔ decide refuses without a terminal or --yes, on an unknown option and on a short reference (9.252602ms)
|
||||
✔ decide prints a declining choice as declining (8.237693ms)
|
||||
✔ an unknown outcome is reported once and never resent (7.375108ms)
|
||||
✔ a decision closed before the answer arrives exits 2 and points at its trail (7.515498ms)
|
||||
✔ a prefix that matches two open decisions exits 2 and resolves neither (7.047251ms)
|
||||
✔ without --business a command uses the live host's business, and a stale host.json is not a host (6.74696ms)
|
||||
✔ every human command refuses inside an agent run before it touches the bus (6.88021ms)
|
||||
✔ usage errors exit 4; no business and no host is a usage error (7.374595ms)
|
||||
✔ agents and tasks print through the broker (6.811365ms)
|
||||
✔ notify.json: missing, loose, malformed and extra keys refuse; a binding or null passes (1.066409ms)
|
||||
✔ bootConfig builds the broker's boot message for one business, with no trackers key when no project names one (29.411399ms)
|
||||
✔ trackers come from the tracker.* variables of the one project that names a tracker project (58.013196ms)
|
||||
✔ with two projects, the one that sets tracker.project supplies the tracker and the other is no conflict (27.217546ms)
|
||||
✔ two projects that each name a tracker project refuse, since the boot shape holds one (26.366462ms)
|
||||
✔ a business without tracker.baseUrl gets no trackers entry (26.701526ms)
|
||||
✔ an unknown business and a broken system config refuse with exit 3 (47.368364ms)
|
||||
✔ follow prints an unsolicited message after plain talk returned (24.383509ms)
|
||||
✔ talk --follow continues after reply and prints a later unsolicited message (21.908989ms)
|
||||
✔ inbox lists all unread human messages under decisions, does not deliver or read them (190.772267ms)
|
||||
✔ follow refuses agent context and bad arguments (8.810271ms)
|
||||
✔ follow Ctrl-C wakes the poll sleep and removes its handler; transport errors also clean up (8.748044ms)
|
||||
✔ plain talk leaves the process SIGINT handlers unchanged (9.081367ms)
|
||||
✔ empty views say so (0.552504ms)
|
||||
✔ the trail keeps the broker's order and names a decision's task without its rows (0.697926ms)
|
||||
✔ tasks print the tracker fields the snapshot carries (0.137188ms)
|
||||
✔ the review loop: the coder pushes and asks, the reviewer fetches and approves, and the task's trail holds each step (295.124997ms)
|
||||
✔ refusals: no action, non-fast-forward, an unknown commit or request, and a push for another task moves only that task's ref (280.549371ms)
|
||||
✔ the size cap refuses a push before any byte (134.175945ms)
|
||||
✔ a fetch over the cap refuses before any byte reaches the reviewer (283.232588ms)
|
||||
✔ the socket refuses a request with no capability, an unknown one, and a bad request line (131.574218ms)
|
||||
✔ a rigged clone runs nothing: hooks, fsmonitor, a filter, a gitlink and a symlinked .git/config leave no marker (226.79686ms)
|
||||
✔ an identity with no role, or of another business, refuses not-a-role and moves no ref (174.108327ms)
|
||||
✔ a review of a project the business no longer has refuses unknown-project (168.123063ms)
|
||||
✔ past maxActive connections the socket refuses git-busy, and a hung-up connection frees its slot (117.21618ms)
|
||||
✔ close() answers host-closing to a connection still sending its request line (113.268063ms)
|
||||
✔ a bundle that trickles in refuses body-timeout at its deadline and frees its slot (534.329974ms)
|
||||
✔ a reviewer gone before its bundle was sent is filed fetch-aborted, not as the host's fault (380.867788ms)
|
||||
✔ a reviewer that hangs up the moment it has the whole bundle was served, not aborted (538.400794ms)
|
||||
✔ send: a close after every byte left is served; one that fails a queued write is fetch-aborted (41.008301ms)
|
||||
✔ a bundle with no bytes for bodyIdle refuses body-timeout long before its deadline (431.598333ms)
|
||||
✔ send: a close once the loop is past its last chunk is served, and a failed write there is fetch-aborted (44.760492ms)
|
||||
✔ letGo waits for an answer to leave for at most its cap, then destroys the socket (302.256337ms)
|
||||
✔ a record that fails and can't be undone refuses rollback-failed, which the host logs (317.012764ms)
|
||||
✔ the host boots the broker, binds a launch in process, and the notifier DMs a blocking decision exactly once (816.51652ms)
|
||||
✔ a notifier that dies takes the host down with exit 1, so the unit restarts the pair (150.523651ms)
|
||||
✔ a second host for the same data root refuses with exit 3 while the first runs (90.264186ms)
|
||||
✔ two bus starts racing for one data root leave one host running; the other refuses that a host already runs (445.292146ms)
|
||||
✔ a host takes over a host.lock its dead host left, and puts back a live claim that replaced it meanwhile (1.668611ms)
|
||||
✔ a host.lock that goes between the check and the read is tried again; one that can't be parsed still refuses as unreadable (0.737147ms)
|
||||
✔ a live host's lock stays, however old the file is (0.49289ms)
|
||||
✔ a host.lock left by a host killed with SIGKILL doesn't stop the next bus start (651.148049ms)
|
||||
✔ while a host boots, a reader sees no host: the human commands still ask for --business, stop and status find none (192.632425ms)
|
||||
✔ a host started before host.lock existed, holding only host.json, still refuses a second start, which leaves no lock (25.880752ms)
|
||||
✔ a broker fork that throws leaves no host.lock and no host.json (28.441835ms)
|
||||
✔ a broker send that throws leaves no host.lock and no host.json (29.170023ms)
|
||||
✔ a broker that misses its boot wait leaves no host.lock and no host.json (27.830115ms)
|
||||
✔ a notifier fork that throws stops the broker and leaves no host.lock and no host.json (77.48177ms)
|
||||
✔ a notifier send that throws stops the broker and leaves no host.lock and no host.json (74.025809ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, before the notifier starts, and leaves no host.lock and no live broker (77.278937ms)
|
||||
✔ a boot reply with no reader for the business refuses with exit 3 naming it, with no notifier, and leaves no host.lock and no live broker (77.733845ms)
|
||||
✔ a host.json that can't be written stops both children and leaves no host.lock (171.864239ms)
|
||||
✔ an error event on the broker before it replies fails the start at once, and leaves no host.lock and no live child (28.011242ms)
|
||||
✔ an error event on the notifier before it replies fails the start at once, and leaves no host.lock and no live child (77.61208ms)
|
||||
✔ an error event on the broker while the notifier starts fails the start once the notifier replies (178.318612ms)
|
||||
✔ an error event on the broker once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (167.882863ms)
|
||||
✔ an error event on the notifier once the host is up stops the host with exit 1, and leaves no host.lock and no host.json (166.734956ms)
|
||||
✔ a broker reply that misses the wait breaks the channel: the late reply answers nothing, later requests refuse, the host exits 1 (1081.193583ms)
|
||||
✔ a broker reply with another request's id, or none, breaks the channel and the host exits 1 (159.920744ms)
|
||||
✔ a broker reply with no request waiting breaks the channel and the host exits 1 (81.003533ms)
|
||||
✔ a notifier that refuses stops the broker and the host refuses with exit 3 (124.179343ms)
|
||||
✔ a notifier that refuses after the broker died still refuses with exit 3, without a send to the dead broker (126.11229ms)
|
||||
✔ a notifier that dies before it replies, after the broker died, still refuses, without a send to the dead broker (72.711683ms)
|
||||
✔ a close send that fails with EPIPE after the notifier refuses still gives the notifier's refusal, exit 3 (122.416861ms)
|
||||
✔ a close send that fails with EPIPE after the notifier dies unanswered still gives the notifier's error (79.571814ms)
|
||||
✔ close() whose stop and close sends fail with EPIPE still finishes, with exit 1 (155.317416ms)
|
||||
✔ watchChildren reports a child that died before it was called, and one that dies later (26.18894ms)
|
||||
✔ bus stop refuses to signal a live pid that is not a bus host (203.212399ms)
|
||||
✔ bus start refuses with exit 3 and the code when the broker refuses to boot; bus status names the lock (271.241869ms)
|
||||
✔ bus start refuses with exit 3 without a notifier config (110.921359ms)
|
||||
✔ bus start runs until bus stop; status reports it while it runs (736.896734ms)
|
||||
✔ bus-service.sh renders the unit and installs it into a given directory (72.455188ms)
|
||||
✔ bus-service.sh pins the claude binary, refuses one the unit can't carry, and renders without one (93.719175ms)
|
||||
✔ bus-service.sh refuses a directory pin and keeps a symlink default unresolved (17.213694ms)
|
||||
✔ bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space (12.75944ms)
|
||||
✔ each launch rereads limits and model selections; lowered limits keep sessions and log exact hit (21.214148ms)
|
||||
✔ bus start --pm: the launcher instance (the chief of staff) runs under its own PID namespace, registered, with a manifest (1205.2367ms)
|
||||
✔ the chief of staff launches a coder through its launch tool; the coder answers; refusals name their code (402.001985ms)
|
||||
✔ each launch makes sure the workspace has a clone of the project: cloned, fast-forwarded, or fetched and logged (3506.847457ms)
|
||||
✔ a project clone that can't be made refuses checkout-failed, from --chief and from a session, with no run and no clone left (113.940976ms)
|
||||
✔ a runner that stops at once ends its launch with the runner's reason (186.098661ms)
|
||||
✔ a Claude Code launch with no session credential refuses before it starts (90.636589ms)
|
||||
✔ a pi launch needs no session credential: pi logs in through its own ENV_ALLOW variables (164.860555ms)
|
||||
✔ a runner killed from the host ends its launch as killed, not failed (231.953812ms)
|
||||
✔ a missing or failing bwrap refuses sandbox-unavailable before anything starts; there is no unconfined fallback (95.232227ms)
|
||||
✔ a real Claude Code coder's shell can't read a stand-in secret or anything else its sandbox doesn't hold (937.691851ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which kills them and ends their runs so the role can be launched again (603.636217ms)
|
||||
✔ a host that died hard leaves its sessions to the next host, which finds one already exited (23) and ends their runs so the role can be launched again (3549.372427ms)
|
||||
✔ a malformed sessions.json refuses the host start with exit 3 and stays as it was (84.128303ms)
|
||||
✔ an over-long launch request is refused at once, not at the 10 s idle timeout (92.842817ms)
|
||||
✔ a launch client that never closes its side doesn't hold the host's close (88.921593ms)
|
||||
✔ a runner that ignores SIGTERM is killed when the host closes (1202.789156ms)
|
||||
✔ claudeVersion asks MOSAIC_CLAUDE_BIN when set, else claude on PATH (4.383835ms)
|
||||
✔ migration needs no bus/config, prints whole converted document, is idempotent and never writes (8.358277ms)
|
||||
✔ limits view/set use the human bus transport and pass only the explicit patch (0.952992ms)
|
||||
✔ post-119 example and Jason fixture migrate with checked inherited models; wrong or absent config refuses (157.024585ms)
|
||||
✔ zoned uses the IANA zone across DST (11.921454ms)
|
||||
✔ each open blocking decision is DM'd once, across polls and a restart; non-blocking ones are not (14.279928ms)
|
||||
✔ two blocking decisions get two DMs with different nonces (9.204216ms)
|
||||
✔ the digest nonce differs per business and per day and fits Discord's 25 characters (0.158994ms)
|
||||
✔ a failed DM is journaled, backs off, and is retried until it lands (9.416039ms)
|
||||
✔ five definite refusals stop a DM: one gave-up line, one log line, and a restart keeps the count (10.273711ms)
|
||||
✔ 429s, 5xx-style unknowns and refusals without a status never count toward the limit (11.720936ms)
|
||||
✔ a crash between the fifth refusal and its gave-up line: the next poll appends it and sends nothing (8.354491ms)
|
||||
✔ polled every POLL_MS against a permanent 403, a DM is sent at 0, 30, 60, 90 and 120 min and gives up only then (65.108365ms)
|
||||
✔ a restart after the second refusal does not send before that refusal's 30 min are up (31.384463ms)
|
||||
✔ the digest goes at 08:00 Chicago once a day, with blocking ones marked as DM'd (8.984149ms)
|
||||
✔ a late start with no digest for the day sends one at once; an empty inbox gets one line (6.720052ms)
|
||||
✔ an inbox read failure is logged and the next poll retries (0.498648ms)
|
||||
✔ no Discord id reaches the journal or the log (7.253134ms)
|
||||
✔ the journal: a torn tail is copied out and truncated, so an append after it reopens cleanly (1.684233ms)
|
||||
✔ the journal: a crash between the copy and the truncate leaves a tail the next open repairs (1.83131ms)
|
||||
✔ the journal: a whole file that is one torn line truncates to empty (1.14407ms)
|
||||
✔ the journal: a malformed complete line refuses and leaves the file and any torn tail alone (0.40844ms)
|
||||
✔ the journal: a loose file mode, a loose directory or a symlinked journal refuses (1.514678ms)
|
||||
✔ the journal: a line with a wrong type refuses with exit 3 and names the field (1.723801ms)
|
||||
✔ the journal: a symlinked directory refuses and says it is a link (0.273471ms)
|
||||
✔ the journal: a dangling directory link, a parent that is a file and a journal that is a directory each refuse with exit 3 (0.44175ms)
|
||||
✔ the journal: an append after the file was swapped for a symlink refuses and writes nothing through it (0.325261ms)
|
||||
✔ the journal: a directory it cannot write or create refuses with exit 3 and names the path (0.427081ms)
|
||||
✔ digest content stays within Discord's 2000 characters (0.224717ms)
|
||||
✔ runLoop never overlaps ticks and stops after the one in flight (110.317845ms)
|
||||
✔ a human command refused with human-required prints the other-tree line and exits 3 (1.835984ms)
|
||||
✔ a --tester command refused with tester-required prints the other-tree line and exits 3 (0.6998ms)
|
||||
✔ other exit-3 refusals print no other-tree line (1.031995ms)
|
||||
✔ the line names no path (0.10438ms)
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (340.000184ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (373.309452ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (371.748173ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (246.58929ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (3029.181736ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (432.718868ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (147.220265ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (153.970984ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (139.3928ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (156.126031ms)
|
||||
✔ inherited service.d override refuses without changing the unit (156.78321ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (137.808649ms)
|
||||
✔ talk --tester sends a [mos test] message as tester from inside an agent and prints the role's reply (21.921316ms)
|
||||
✔ talk --tester refuses text without the [mos test] prefix before any call (7.625146ms)
|
||||
✔ the read verbs take --tester inside an agent, and the trail shows the tester as the sender (11.492424ms)
|
||||
✔ decide, stop and launches take no --tester (8.111199ms)
|
||||
✔ the tester transport runs tester-cli.mjs, and the tester's refusals exit 3 (0.287687ms)
|
||||
✔ with no stand-in transport, --tester runs tester-cli.mjs on the data root's socket (0.43304ms)
|
||||
task.close {} answered: invalid-request; fake saw 18 requests, first GET /info 200, GET /projects/1 200, GET /projects/1/views 200
|
||||
task.close on a missing task answered: task-not-found; it made GET /tasks/999 404
|
||||
✔ bootConfig trackers reach the S3 adapter in the real broker child, which goes ready against a fake Vikunja (240.256594ms)
|
||||
✔ the transport writes {business, verb, args} to the child and reads its JSON (25.944424ms)
|
||||
✔ a bus code on stderr becomes the exit code; garbage and timeouts are outcome problems (2124.15454ms)
|
||||
✔ busExit and refuseInsideAgent (0.506287ms)
|
||||
✔ talk sends a REQUEST, prints and reads everything that arrives, and stops at the reply (41.063771ms)
|
||||
✔ talk --wait 0 only sends; no reply within --wait exits 1 and says where it will show (1029.884472ms)
|
||||
✔ a late reply the Console has listed still reaches the next talk (2031.870118ms)
|
||||
✔ talk, stop and launches off/on refuse inside an agent run; bad arguments are usage errors (10.542966ms)
|
||||
✔ launches off and on go to the broker and change the business's launch state (8.67139ms)
|
||||
✔ launches list reads sessions.json and marks a stale entry; stop reports it and refuses a non-runner (8.677366ms)
|
||||
ℹ tests 195
|
||||
ℹ suites 0
|
||||
ℹ pass 195
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 49052.247764
|
||||
@@ -0,0 +1,92 @@
|
||||
✔ sessionModel: agent vars win, then the system's execution settings (7.880525ms)
|
||||
✔ a pi bundle: prompt, policy, tools and manifest, 0600 in a 0700 directory (3.468916ms)
|
||||
✔ a chief-of-staff bundle lists launch among the bus tools and the manifest's typed tools (1.678507ms)
|
||||
✔ a claude-code bundle adds the wrapped gate hook and the MCP config (1.913034ms)
|
||||
✔ the prompt's built-in tools line is the harness's own names, as the manifest lists them (5.835988ms)
|
||||
✔ the prompt names the project clones in the workspace, and none when there are none (3.854181ms)
|
||||
✔ the prompt explains the review loop to a role with push_working, and reviews to one with fetch_review (5.169287ms)
|
||||
✔ a bundle is written once: an existing file refuses (1.09281ms)
|
||||
✔ a path with a single quote can't go into the hook command (1.415052ms)
|
||||
✔ allow exits 0, a deny exits 2 with the reason on stderr (89.137653ms)
|
||||
✔ a missing or wrong policy, or a bad event, exits 2 (71.470185ms)
|
||||
✔ the bundle's wrapped command: a missing gate or node still blocks (1080.72187ms)
|
||||
✔ claude: typed tools through MCP, the hook blocks, builtins outside --tools don't exist (620.145966ms)
|
||||
✔ claude: the hook alone blocks a path outside the workspace (369.625247ms)
|
||||
✔ claude: a second turn resumes the first turn's session (643.645968ms)
|
||||
✔ claude adapter: --restricted is always passed (4.98042ms)
|
||||
✔ claude adapter: MOSAIC_CLAUDE_BIN wins over PATH and must be an absolute executable (15.556464ms)
|
||||
✔ claude adapter: a directory pin exits 2 before it runs; a pin with a space runs (5.418784ms)
|
||||
✔ claude: CLAUDE.md files and auto-memory don't reach the model; without --restricted they do (644.20235ms)
|
||||
✔ claude: a missing hook or MCP file refuses before claude starts (7.346147ms)
|
||||
✔ pi: policy tools and typed tools pass, anything else is blocked (2.388288ms)
|
||||
✔ claude: builtins map from pi names, typed tools need the mcp prefix (0.548783ms)
|
||||
✔ file tool paths must resolve inside the workspace (0.870998ms)
|
||||
✔ pi's own path normalisation can't be used to step out (0.690427ms)
|
||||
✔ a symlink inside the workspace that points out is outside (0.601458ms)
|
||||
✔ a dangling symlink is refused at any depth, in both harnesses (2.041946ms)
|
||||
✔ read is checked under every spelling pi's read would open, in both harnesses (10.132327ms)
|
||||
✔ other spellings cover directories, dangling links and pi's cwd (0.9835ms)
|
||||
✔ a relative path climbs from the workspace's real path, in both harnesses (3.122048ms)
|
||||
✔ claude path fields per tool (0.501216ms)
|
||||
✔ glob patterns stay inside the workspace (0.460037ms)
|
||||
✔ a path that can't be checked is blocked (0.28747ms)
|
||||
✔ fetch_review's have lists the working refs before origin's, and no more than HAVE_MAX (159.175003ms)
|
||||
✔ fetch_review's have orders the working refs newest first within each clone, one clone after another (113.964301ms)
|
||||
✔ a runner git past its time: SIGTERM reaches its process group, and SIGKILL follows after the grace period (1809.910991ms)
|
||||
✔ once a signalled runner git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (303.422681ms)
|
||||
✔ initialize, ping and tools/list (32.251342ms)
|
||||
✔ tools/call goes through the tool socket; a refusal is an isError result (26.605103ms)
|
||||
✔ replies are compact JSON; over the cap a tool error names the size and the cap (33.043512ms)
|
||||
✔ unknown tools and methods are JSON-RPC errors and never reach the socket (25.144155ms)
|
||||
✔ a missing argument is a usage error (23.318106ms)
|
||||
✔ pi: typed tools reach the socket, the gate blocks, agent_end writes the marker (305.900298ms)
|
||||
✔ pi: a reply over the cap is a tool error naming the size and the cap; list_tasks asks for open tasks (301.661418ms)
|
||||
✔ pi: a write through a dangling symlink is blocked, and nothing appears outside (304.792022ms)
|
||||
✔ pi: a read is refused when pi would open another spelling outside (301.543742ms)
|
||||
✔ pi: a relative path climbs from the real path of a workspace behind a symlink (289.257408ms)
|
||||
✔ pi: a relative path climbs from the real path of a dataRoot behind a symlink (292.942855ms)
|
||||
✔ pi: a missing extension refuses before any model call (6.203793ms)
|
||||
✔ pi: an extension without its configuration fails pi's start (235.729728ms)
|
||||
✔ founderCheck: founder variables, then a needed service without a usable token (0.8964ms)
|
||||
✔ turnRequest names the sender, class, reply and decision (0.159771ms)
|
||||
✔ turnRequest says a tester's message is a test and never Jason's instruction (0.251106ms)
|
||||
✔ turnRequest shows the message's own sent time, a day old as well as new (0.131427ms)
|
||||
✔ stateBlock names the launch state with its time and event, and the open tasks with the cap (0.198894ms)
|
||||
✔ a message becomes a turn, the answer goes back as a RESULT, SIGTERM releases and exits 0 (149.472315ms)
|
||||
✔ launches revoked and then restored: the turn's block reads allowed and gives the restore time (166.743317ms)
|
||||
✔ a task closed on the tracker is missing from the next turn's open list (165.906823ms)
|
||||
✔ a message read a day after it was sent shows the time it was sent (88.418801ms)
|
||||
✔ a decision the human resolves becomes a turn citing the decision and the answer (137.894872ms)
|
||||
✔ a failed state read fails the turn: no adapter runs, the sender hears why, the message is read (61.514628ms)
|
||||
✔ a SIGTERM before the claim stops the runner with exit 0 and no claim (46.071514ms)
|
||||
✔ typed tools carry the runner's capability; launch goes to the host's launch socket (246.153293ms)
|
||||
✔ a RESULT gets no automatic reply; failed turns reply with the reason (1185.705348ms)
|
||||
✔ SIGTERM during a turn kills the turn's process group and still exits 0 (91.07011ms)
|
||||
✔ founder credentials stop before the claim (20) (84.458581ms)
|
||||
✔ a refused claim exits 21; an ended run's capability exits 22 (92.161734ms)
|
||||
✔ the launch ending under a running session exits 22 (98.2236ms)
|
||||
✔ a broker that stays unreachable exits 23 after brokerRetries polls (196.114385ms)
|
||||
✔ a broker that is down at the claim exits 23, not 21 (42.265215ms)
|
||||
✔ no capability, or a malformed one, on stdin exits 2 (144.108979ms)
|
||||
✔ a missing or malformed policy exits 2 before the claim (80.431429ms)
|
||||
✔ the PM gets its task verbs and the reads, and no launch (5.320443ms)
|
||||
✔ the chief of staff gets launch and send_message, and no task verbs (1.454924ms)
|
||||
✔ the assistant gets send_message and the reads, no launch (1.669687ms)
|
||||
✔ list_requirements reads the requirement ids, for a task.create holder with a tracker (2.228087ms)
|
||||
✔ a coder gets no launch, no resolve_decision, and no task tools without a tracker (0.978613ms)
|
||||
✔ a coder with a tracker gets its own task tools and no task_reassign (0.979534ms)
|
||||
✔ launch only when the business's launch block names the instance as launcher (1.673752ms)
|
||||
✔ an action outside the instance's authority has no tool (1.346717ms)
|
||||
✔ the review loop: push_working and request_review for the coder, fetch_review and review_verdict for the reviewer, none for the PM (2.910057ms)
|
||||
✔ callTool: one JSON line out, the result back, a refusal rejects (6.475424ms)
|
||||
✔ list_tasks takes the broker's filters and pages; get_task takes a task_ref (1.855425ms)
|
||||
✔ callTool sends list_tasks done false unless the session names done; other tools as given (1.860916ms)
|
||||
✔ replyText: compact JSON up to the cap, an error naming the size and the cap over it (0.640863ms)
|
||||
ℹ tests 84
|
||||
ℹ suites 0
|
||||
ℹ pass 84
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 19086.783641
|
||||
@@ -0,0 +1,145 @@
|
||||
✔ a first launch clones the root at its branch, with the root's path as origin (30.814015ms)
|
||||
✔ the clone is not at its place until git clone has finished (20.026989ms)
|
||||
✔ a later launch fast-forwards a clean clone after a commit to the root, then finds it current (57.446875ms)
|
||||
✔ a clone ahead of the root keeps its commits and counts as current (36.080347ms)
|
||||
▶ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves
|
||||
✔ a modified file (41.975897ms)
|
||||
✔ an untracked file (42.394501ms)
|
||||
✔ a staged file (42.863196ms)
|
||||
✔ another branch (40.571095ms)
|
||||
✔ a detached HEAD (40.797834ms)
|
||||
✔ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves (209.696205ms)
|
||||
✔ a diverged clone gets the fetch into refs/remotes and is kept, not-fast-forward (41.72769ms)
|
||||
▶ a clone kept before the branch check, or for a failed status, gets no fetch
|
||||
✔ not-a-clone (22.444109ms)
|
||||
✔ hooks-present (23.64668ms)
|
||||
✔ submodule (29.332051ms)
|
||||
✔ config-changed (26.913897ms)
|
||||
✔ root-unreadable (26.098494ms)
|
||||
✔ root-detached (31.641575ms)
|
||||
✔ status-failed, on the root's branch and clean (34.243798ms)
|
||||
✔ status-failed, dirty (33.628961ms)
|
||||
✔ a clone kept before the branch check, or for a failed status, gets no fetch (229.088255ms)
|
||||
✔ a dirty clone whose fetch fails is kept, fetch-failed, exactly as it was (37.081784ms)
|
||||
✔ every git call the host makes, for a new clone and an existing one, carries maintenance.auto=false and gc.auto=0 (44.383561ms)
|
||||
✔ a clone with loose objects enough for gc --auto gets no maintenance or gc from the fetch and the merge (72.001105ms)
|
||||
▶ a clone with user.name or user.email in its config is kept, and git runs nothing in it
|
||||
✔ user.name (26.018712ms)
|
||||
✔ user.email (26.363696ms)
|
||||
✔ a clone with user.name or user.email in its config is kept, and git runs nothing in it (52.847706ms)
|
||||
✔ a commit git can't read after the fast-forward is null (46.657246ms)
|
||||
✔ a new clone whose commit can't be read refuses the launch and leaves nothing behind (19.274281ms)
|
||||
▶ a clone the session rigged is kept, and git runs nothing and writes nothing outside it
|
||||
✔ core.fsmonitor (34.271422ms)
|
||||
✔ core.hooksPath (33.966516ms)
|
||||
✔ a hook file (31.109331ms)
|
||||
✔ include.path (33.413953ms)
|
||||
✔ includeIf (34.016606ms)
|
||||
✔ a filter driver (33.843312ms)
|
||||
✔ origin moved (34.347227ms)
|
||||
✔ a second origin url (34.851059ms)
|
||||
✔ the origin url twice, both the root (36.514182ms)
|
||||
✔ an ext:: origin (34.637871ms)
|
||||
✔ a branch tracking another remote (34.473758ms)
|
||||
✔ a branch merging a tag (33.453804ms)
|
||||
✔ a fetch line onto local branches (34.404405ms)
|
||||
✔ no origin (33.872563ms)
|
||||
✔ a config file over the size cap (30.774817ms)
|
||||
✔ config a symlink to /dev/zero (31.311459ms)
|
||||
✔ the clone a symlink to the bait (30.976568ms)
|
||||
✔ the clone a file (31.104943ms)
|
||||
✔ the clone a plain directory (30.730901ms)
|
||||
✔ .git a gitdir: file (30.121057ms)
|
||||
✔ .git a symlink (30.911802ms)
|
||||
✔ .git/logs a symlink (30.677716ms)
|
||||
✔ .git/refs/heads a symlink (31.637689ms)
|
||||
✔ .git/objects a symlink (30.776609ms)
|
||||
✔ a reflog hard-linked to a file outside (30.760581ms)
|
||||
✔ HEAD a fifo (34.410164ms)
|
||||
✔ a commondir file (39.903169ms)
|
||||
✔ an alternates file (43.702223ms)
|
||||
✔ a gitlink staged, no .gitmodules (44.530393ms)
|
||||
✔ a gitlink and .gitmodules staged (45.160145ms)
|
||||
✔ a gitlink to a repository with its own gitlink (52.127784ms)
|
||||
✔ a gitlink and .gitmodules committed (48.387573ms)
|
||||
✔ a gitlink and submodule.active in config (45.334415ms)
|
||||
✔ a .git/modules with no gitlink (34.247653ms)
|
||||
✔ a clone the session rigged is kept, and git runs nothing and writes nothing outside it (1209.152306ms)
|
||||
▶ a root that can't be cloned refuses with the project id and leaves nothing behind
|
||||
✔ missing (10.596408ms)
|
||||
✔ not a repository (10.508374ms)
|
||||
✔ a plain directory inside another repository (15.108963ms)
|
||||
✔ unreadable (10.712174ms)
|
||||
✔ on no branch (12.037759ms)
|
||||
✔ missing an object (15.600063ms)
|
||||
✔ a root that can't be cloned refuses with the project id and leaves nothing behind (75.332628ms)
|
||||
✔ a clone whose root is on no branch, or gone, is kept and named (29.845742ms)
|
||||
✔ no credential or forge remote of the root reaches a clone (49.754809ms)
|
||||
✔ every project in the business file gets its own clone at its own branch (35.77472ms)
|
||||
✔ a clone past its time gets SIGTERM and refuses the launch, with nothing left in the workspace (514.118049ms)
|
||||
✔ a clone that ignores SIGTERM gets SIGKILL once the grace period is over (1018.030284ms)
|
||||
✔ a timeout signals git's process group, so a process git started dies with it (514.494641ms)
|
||||
✔ once a signalled git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (516.195318ms)
|
||||
✔ RUNNER_FILES is exactly what the runner and the harness sources it starts import (1.645592ms)
|
||||
✔ sandboxProblem names a missing bwrap and a bwrap that fails (8.657319ms)
|
||||
✔ every bind says why; the bundle and session file stay read-only over the run directory (1.203097ms)
|
||||
✔ the host's git socket is bound only when given, read-only and before the writable binds (0.859728ms)
|
||||
✔ the git identity is the instance's, at <instance>@<business>.mosaic.invalid, and sandboxArgv refuses without it (1.356127ms)
|
||||
✔ a confined session's shell reaches its own workspace and run directory and nothing of the founder's or another session's (1766.25384ms)
|
||||
✔ a bind that exposes a stand-in, or a missing workspace bind, fails the matching check (2648.999451ms)
|
||||
✔ a confined session that runs tester-cli.mjs is refused as tester, and the same shim outside the sandbox binds (211.424116ms)
|
||||
✔ resolveSeat: by name under --repo resolves the repo layout (1.301243ms)
|
||||
✔ resolveSeat: by path resolves the fleet layout (0.357989ms)
|
||||
✔ resolveSeat: refusals for missing dir, missing launch.sh, non-executable launch.sh, invalid name, and unknown layout (0.741351ms)
|
||||
✔ tmuxContext: outside tmux, default socket, custom socket, and exec failure (0.672294ms)
|
||||
✔ makeRegistration produces a record that validates; each shape violation throws SeatError (0.885207ms)
|
||||
✔ writeRegistration/readRegistration: round trip, permissions, absence, and malformed records (1.311949ms)
|
||||
✔ updateTask: changes task, taskSetBy and updatedAt only, and refuses appropriately (1.210543ms)
|
||||
✔ CLI launch: registers, execs the fake launch script, and passes args through (29.083784ms)
|
||||
✔ CLI launch: --harness lands in the record (30.471548ms)
|
||||
✔ CLI launch: the launch script's own exit code passes through (33.439309ms)
|
||||
✔ CLI launch: relaunching a seat rewrites the one registration record (56.065651ms)
|
||||
✔ CLI launch: omitting --task records an empty string, not null (29.044123ms)
|
||||
✔ CLI seat task: updates only the task after a launch, and refuses on an unlaunched seat (80.55892ms)
|
||||
✔ CLI refusals: no args, unknown flag, missing config, already-registered env, and exec failure (137.113804ms)
|
||||
✔ samePath: equal paths, symlinked dirs, distinct dirs, and non-strings (0.377661ms)
|
||||
✔ resolveSetBy: explicit --by wins over the environment; absent or empty environment gives unknown; invalid explicit or environment values refuse with exit 4 (0.554236ms)
|
||||
✔ validateRegistration/readRegistration: taskSetBy is optional; a record without it (written before #1511) still loads unchanged; an invalid one is refused; the version does not change (0.699041ms)
|
||||
✔ updateTask: records setBy, preserves startedAt and every unrelated field, upgrades an old record in place only when the task is set, and replaces a previous attribution (1.114176ms)
|
||||
✔ CLI seat task: --by beats MOSAIC_AGENT_NAME, the environment beats nothing, empty environment is unknown, invalid --by or environment refuses with exit 4 and leaves the record byte for byte (252.78003ms)
|
||||
✔ REQ-LIMIT-1: family substring matching is no longer exported (0.744983ms)
|
||||
✔ sessionEnv passes only the allowlist, the repo's bin on PATH, and the run id (0.685444ms)
|
||||
✔ sessionExit gives a runner's signal death back as the signal; a session credential is one whole set of nonempty variables (0.248315ms)
|
||||
✔ newRun: short ids, 0700 directories, and a refusal when the socket path won't fit (1.50821ms)
|
||||
✔ session file and launch log: 0600, the session file written once (1.005989ms)
|
||||
✔ endReason maps the runner's exit codes; a signal is killed (0.116729ms)
|
||||
✔ Registry mirrors to sessions.json; readSessions marks live entries; bad files refuse (1.231537ms)
|
||||
✔ stopSession refuses an unknown run, reports a stale one, and won't signal a pid that isn't a runner (0.936078ms)
|
||||
✔ a session runs in its sandbox as pid 1 of its namespace, claims, answers, and stops on mosaic stop (188.845858ms)
|
||||
✔ workRef and validBranch take only what a ref name can hold (1.123378ms)
|
||||
✔ a push lands as the task's work ref, a fast-forward lands after it, and main is the root's (98.768506ms)
|
||||
✔ a rewritten branch refuses non-fast-forward and the work ref stays (99.80719ms)
|
||||
✔ a branch with no history in common with main refuses unrelated-history (47.412052ms)
|
||||
✔ a bundle that needs commits the working repository lacks refuses missing-prerequisite (43.79553ms)
|
||||
✔ main is fetched from the root again before each push, so a clone of a newer root pushes (120.704892ms)
|
||||
✔ a root moved back after the clone leaves the push's base unknown: missing-prerequisite (73.346571ms)
|
||||
✔ a commit with a broken object refuses invalid-bundle, and only because fsck is on (70.509882ms)
|
||||
✔ only a v2 bundle with the named branch is read (56.092274ms)
|
||||
✔ a branch named main, or named for another task, moves only this task's work ref (96.493234ms)
|
||||
✔ a record that throws moves the work ref back, or removes a new one (134.717964ms)
|
||||
✔ a work ref that can't go back refuses rollback-failed, naming the ref and the commit (360.616955ms)
|
||||
✔ a root that can't be read refuses root-unreadable (37.628529ms)
|
||||
✔ a git past its time gets SIGTERM, leaves no ref lock, and the next push lands (2136.308964ms)
|
||||
✔ a git that ignores SIGTERM gets SIGKILL once the grace period is over (1027.540399ms)
|
||||
✔ a working repository path that isn't a directory refuses (24.502593ms)
|
||||
✔ review bundles a pushed commit as refs/mosaic/review, leaving out what the reviewer has (98.677203ms)
|
||||
✔ review of a project with no working repository refuses unknown-commit (12.760326ms)
|
||||
✔ the runner's git tools hold the host's limits and branch rule (1.123418ms)
|
||||
ℹ tests 132
|
||||
ℹ suites 0
|
||||
ℹ pass 132
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 15142.521329
|
||||
@@ -0,0 +1,105 @@
|
||||
✔ the boot config is checked before anything starts (13.629955ms)
|
||||
✔ a business with no tracker entry refuses task verbs (9.901902ms)
|
||||
✔ credential.expiring and .expired are recorded once per instance (21.944276ms)
|
||||
✔ a token file that changes on disk records credential.changed (10.29513ms)
|
||||
✔ autostart polls, reconciles and retries a startup the tracker was down for (33.510163ms)
|
||||
✔ a refusal a restart must clear is not retried by the poll (7.335997ms)
|
||||
✔ a poll that fires while two are queued is dropped (10.688979ms)
|
||||
✔ close waits for a running verb and refuses one that has not started (39.674804ms)
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (31.961928ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (26.099796ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (16.036128ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.907531ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.896774ms)
|
||||
✔ the bundled Vikunja is the pinned upstream image the runbook names (0.740586ms)
|
||||
✔ every published port is on 127.0.0.1, and no secret is in the file (0.286942ms)
|
||||
✔ the committed table loads frozen; its verbs are the broker task verbs (1.162806ms)
|
||||
✔ a write names a verb the table has as its own key, not one it inherits (0.941715ms)
|
||||
✔ the schema refuses any other shape (1.808027ms)
|
||||
✔ the Field table in the slice 1 plan names the verbs each field is written by (0.493906ms)
|
||||
✔ each verb refuses, asks for a decision and writes as the table and the role files say (133.933499ms)
|
||||
✔ the list holds the PRD's requirement ids, in its order, at its version (1.158317ms)
|
||||
✔ the committed list loads frozen (0.50695ms)
|
||||
✔ the schema refuses any other shape (2.053206ms)
|
||||
✔ the fake answers each route with the statuses and shapes Vikunja v2.7.0 sent (80.116418ms)
|
||||
✔ the project list holds recorded project objects in the recorded list envelope (7.174548ms)
|
||||
✔ the recorded task bodies pass the checks S3 applies to every read (0.404514ms)
|
||||
✔ the client works against the fake over real HTTP with the platform fetch (89.341426ms)
|
||||
✔ a correct install starts, and the first reconcile records tasks that already exist (21.630253ms)
|
||||
✔ verbs refuse while a business is starting and after startup refused it (12.02468ms)
|
||||
✔ startup refuses a token that can do more than its role needs (29.174946ms)
|
||||
✔ startup refuses an unsupported version and flags an untested one (19.924014ms)
|
||||
✔ startup refuses a board that the runbook did not install (24.68159ms)
|
||||
✔ startup refuses a project the sync bot cannot read (5.755174ms)
|
||||
✔ startup refuses a configured label the pm bot cannot see (6.751915ms)
|
||||
✔ startup refuses an expired credential and a missing sync credential (12.796302ms)
|
||||
✔ an unreachable tracker refuses with tracker-unavailable (5.255529ms)
|
||||
✔ an edit in the UI is recorded once, with the fields that changed (71.470331ms)
|
||||
✔ a move between open buckets is seen on the board, though updated does not change (36.439166ms)
|
||||
✔ a person's comment is counted and a bot's is not (62.780444ms)
|
||||
✔ the hourly reconcile catches a comment through comment_count (75.350571ms)
|
||||
✔ a task closed in the UI leaves the open view with its done bucket (109.900649ms)
|
||||
✔ a task that leaves the board is recorded as deleted, moved or out of reach (61.894273ms)
|
||||
✔ a poll that read before a verb wrote does not overwrite the verb (33.486326ms)
|
||||
✔ a tracker fault during a tick is reported and the next tick catches up (33.368087ms)
|
||||
✔ a malformed answer refuses the tick with tracker-shape (10.737421ms)
|
||||
✔ no token value reaches the database, the log or a refusal (43.331139ms)
|
||||
✔ the first look at a task counts only comments inside the window (32.345604ms)
|
||||
✔ with descendants off the adapter reads no project list and no child, as in v0 (40.043243ms)
|
||||
✔ a three-level tree is read per project, and a project outside it is not (17.748236ms)
|
||||
✔ a watch-only child keeps the business ready, and a failed child read refuses as transient (16.877198ms)
|
||||
✔ a root without the installed buckets refuses with descendants on (5.901551ms)
|
||||
✔ the project list refuses without read_all, and skips archived projects and saved filters (13.977911ms)
|
||||
✔ descendants must be true or false (6.169436ms)
|
||||
✔ a move inside the tree is a moved tombstone plus a snapshot under the new ref (57.040089ms)
|
||||
✔ a child made after startup joins the tree at the next reconcile (52.048415ms)
|
||||
✔ a child that leaves the tree has its tasks recorded missing, and the ledger keeps their history (56.856341ms)
|
||||
✔ a child deleted or hidden between reconciles drops out at the next tick, and the root still refuses (80.24672ms)
|
||||
✔ a reconcile that fails keeps the previous tree (32.267805ms)
|
||||
✔ a closed task the cursor missed takes its own project's done bucket (31.637608ms)
|
||||
✔ closed tasks read at startup take their own project's done bucket (8.61474ms)
|
||||
✔ a closed task the cursor returns takes its own project's done bucket (33.676788ms)
|
||||
✔ a task moved out of a child that leaves the tree at the same time is moved, not no-access (30.473087ms)
|
||||
✔ a task in a bucket outside the five keeps its raw bucket id (29.468364ms)
|
||||
✔ bucket 0 on a watch-only task never becomes a bucket or a state (77.383366ms)
|
||||
✔ a child whose kanban view is deleted still refuses the tick, and the reconcile reads it watch-only (54.885724ms)
|
||||
✔ a child dropped at a tick comes back at the next reconcile once the bot reads it again (33.432815ms)
|
||||
✔ task.create needs a recorded human request and a requirement id (29.557851ms)
|
||||
✔ task.create takes only an approved requirement id (16.441379ms)
|
||||
✔ task.create cites the request a received message carries, not the message's id (13.539503ms)
|
||||
✔ only labels named in the business file can be written (18.519991ms)
|
||||
✔ task.schedule sets and clears a due date and relations (23.353458ms)
|
||||
✔ assign and reassign move the role bots and record task.assigned (47.867571ms)
|
||||
✔ task.update.assigned is for the assignee and records task.state (43.780171ms)
|
||||
✔ a wrong expected digest records task.conflict and writes nothing (17.038807ms)
|
||||
✔ a cross-role verb needs a resolved decision, used once (21.667749ms)
|
||||
✔ task.close needs a verdict; after it every verb refuses with task-done (20.898162ms)
|
||||
✔ a task with pushed work closes only citing an approve verdict for its latest push, and a refusal writes nothing (26.951691ms)
|
||||
✔ a lost answer is settled by a re-read and never retried (22.807109ms)
|
||||
✔ a create whose answer is lost is reported uncertain, and the poll finds the task (34.157908ms)
|
||||
✔ a task the sync bot cannot read refuses and records nothing (14.047826ms)
|
||||
✔ verbs and polls for one business run one at a time (87.191096ms)
|
||||
✔ a due date with milliseconds is written to the second (61.114605ms)
|
||||
✔ every write landed and the final read failed: the verb succeeds and records what it wrote (35.516461ms)
|
||||
✔ some writes landed and the final read failed: write-uncertain, and nothing is recorded (12.603896ms)
|
||||
✔ a create whose final read fails succeeds and records task.created (31.174387ms)
|
||||
✔ an edit between the last write and the final read shows as external on the next poll (35.845088ms)
|
||||
✔ task.created is recorded when a later label write fails (12.684216ms)
|
||||
✔ every verb acts in an installed child, on the child's own board (39.88197ms)
|
||||
✔ task.create refuses a project outside the tree, a watch-only one and one that is not an id (21.965358ms)
|
||||
✔ with descendants off, task.create takes only the root project (11.244863ms)
|
||||
✔ a verb on a watch-only task, or a relation to one, refuses with project-not-installed (17.934748ms)
|
||||
✔ a related task is read before authority: in another project than its ref names, task-moved; missing, task-not-found (21.386007ms)
|
||||
✔ a task moved to another project of the tree refuses its old ref with task-moved and takes its new one (15.343634ms)
|
||||
✔ a verb and a create in the child record the final read of the child's board (14.569025ms)
|
||||
✔ a create in the child whose final read fails records the child's todo bucket (34.37208ms)
|
||||
✔ a lost answer in the child is settled by a re-read of the child's board (18.932468ms)
|
||||
✔ every related task is read before authority, not only the first (15.042806ms)
|
||||
ℹ tests 97
|
||||
ℹ suites 0
|
||||
ℹ pass 97
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 3368.95934
|
||||
@@ -0,0 +1,122 @@
|
||||
✔ the Board: held roles with no machine sessions, a claim with no address, the toggle kept across a reload, and Message addressed to the role (2953.91428ms)
|
||||
✔ a redirect answer on a Board read, a bus read, a conversation read, a board POST, a module read and a send signs the page out: one line, nothing stale, no further reads (4924.742697ms)
|
||||
✔ browser edge states: loading, empty, malformed, stale, hostile/long values, in-flight reply and appearance fallback (1060.205228ms)
|
||||
Rendered contrast: {"failures":[],"count":330,"lowest":4.504658476260286}
|
||||
✔ served Console browser: real board fixtures, keyboard, drafts, receipts, themes, 320px and failures (1120.382781ms)
|
||||
✔ the README says a refused field table names the file or the key at fault, never a path (0.708114ms)
|
||||
✔ S5 pages in a browser: real broker rows, inert text, Copy, routes, failures, layout and no writes (2730.802951ms)
|
||||
✔ bus routes serve the four reads from the reader view, unescaped JSON for the page to escape (54.882783ms)
|
||||
✔ decisions route serves the roles and recent lists from the reader view (27.06034ms)
|
||||
✔ credentials route serves the broker credential status from the reader view (7.548149ms)
|
||||
✔ replies route serves the replies to one message from the reader view (25.525087ms)
|
||||
✔ bus routes are GET-only, have no write verb, and keep the same-origin checks (47.442231ms)
|
||||
✔ bus refusals map to statuses and never carry a path or a stack (24.281782ms)
|
||||
✔ humanCall speaks the human transport protocol without blocking the server (1636.995326ms)
|
||||
✔ busReader takes --business, else the live bus host, else refuses (142.24143ms)
|
||||
✔ humanCall kills a transport that runs past its timeout (527.539618ms)
|
||||
✔ serve refuses a --business value that is not a business id (208.733971ms)
|
||||
✔ conversation view: full history, collapsed tools, hidden thinking, inert hostile content, malformed and reconcile markers (916.163971ms)
|
||||
✔ conversation view: a fork keeps the open branch, says so, and opens the new one on request (1263.189899ms)
|
||||
✔ conversation view: a newer session with no readable history keeps the marker (832.027183ms)
|
||||
✔ conversation view: seats without history say so and offer no reply (541.086384ms)
|
||||
✔ Discord row through real board/WebUI: independent brake/liveness, no Reply, literal content (560.853897ms)
|
||||
✔ return flow through the conversation view: send, tool call, delayed result, peer message, exact long answers, relaunch (51647.683824ms)
|
||||
✔ messages HTTP read pages and preserves metadata; bad arguments refuse before a read; other reads unchanged (68.278142ms)
|
||||
✔ Console Messages lists late unsolicited messages on polling with sender class time read state and trail; nav count includes beyond the page; reads never deliver (732.563013ms)
|
||||
✔ Messages nav count polls on Tasks and Board and clears on a Board refusal; messages 403 refuses local pages (1588.441809ms)
|
||||
✔ copy writes the Console paths at the full id, read-only, and leaves an existing copy alone (557.279562ms)
|
||||
✔ copy refuses a commit off refactor, an unknown one, a worktree and a bad copies directory (514.919712ms)
|
||||
✔ copy writes nothing when an archived path is missing at the commit (138.291706ms)
|
||||
✔ a copy that loses the rename race leaves no read-only temp directory behind (337.152895ms)
|
||||
✔ a copy whose rename fails with no target refuses, writes no copy and leaves no temp directory (323.440868ms)
|
||||
✔ a copy that meets a target holding files says exists: and moves nothing into it (322.35431ms)
|
||||
✔ a copy that meets an empty target directory replaces it by rename, not by moving into it (417.375268ms)
|
||||
✔ serve runs from a copy: /healthz 200, the config check, roles and RELEASE from the copy, the queue from --checkout (630.985292ms)
|
||||
✔ serve refuses a --checkout that is not an absolute directory path (214.468798ms)
|
||||
✔ consoleReads runs the queue read under queueRoot and reads RELEASE under root (50.225812ms)
|
||||
✔ preview options are all three or none, and each is checked (5.635288ms)
|
||||
✔ the CLI refuses a partial or invalid preview flag set at start (483.911487ms)
|
||||
✔ the CLI with all three flags serves the preview mode (105.773157ms)
|
||||
✔ a request for the public name needs the header equal to the user id, else 401 and nothing read (13.823371ms)
|
||||
✔ the header name matches without regard to case, and the value compare is exact (2.962758ms)
|
||||
✔ the public name with the header reads the bus views, and the Host and Origin are checked first (21.85639ms)
|
||||
✔ in preview mode every write answers 403 read-only, from the public name and loopback, and reaches nothing (8.329298ms)
|
||||
✔ loopback requests are unchanged in preview mode, and the bus views work with the board down (3.453609ms)
|
||||
✔ a proxy that rewrites Host to the loopback port gets 403 on its first request, whatever the user (12.540119ms)
|
||||
✔ a repeated Host is 400 before any other check, in preview mode and without it (5.512835ms)
|
||||
✔ without the preview flags the public name is refused and writes still reach the board (3.481001ms)
|
||||
✔ redactor: config, dataRoot, any absolute path, Discord ids and the JSON parser quote (1.102131ms)
|
||||
✔ credential state from the date alone, as the bus states it (0.126564ms)
|
||||
✔ queue: rows, one row, ids and methods, notes; no path or id from a row (306.908737ms)
|
||||
✔ queue: a refused read fails closed with the store's text, redacted (159.239178ms)
|
||||
✔ queue: a store that fails to load, or a child that dies, gives a fixed message with no path or stack (695.982126ms)
|
||||
✔ business: names, vars on the allowlist, authority, credential metadata only (9.244748ms)
|
||||
✔ business: missing or invalid file refuses with the module's text, redacted (5.413253ms)
|
||||
✔ business without --business: the live bus host, else no-bus-host; no system config: not-configured (5.960073ms)
|
||||
✔ settings: release, board, loopback address, notifier binding name only (91.165708ms)
|
||||
✔ task fields: the committed table with no reads configured, GET only; a bad table refuses with no path (16.156014ms)
|
||||
✔ both presentations replace old activity with relaunch notice, label retained history, then resume after new activity (648.575634ms)
|
||||
✔ reported return flow and relative Age: reply sent from the inspector, then the new answer appears there without manual refresh (20621.127884ms)
|
||||
✔ the send box: held roles, the draft and caret across a refresh, each receipt, one POST per Send, and the trail link; the board Reply on a 4xx and a 5xx (2141.52702ms)
|
||||
✔ a sent receipt lists its replies as the page refreshes, oldest first and capped, and marks none delivered or read (10911.803578ms)
|
||||
✔ startServer takes send only as a function and only with the preview mode (5.044922ms)
|
||||
✔ the CLI refuses --send without the preview flags, and without a configured bus (335.163729ms)
|
||||
✔ the CLI with --send and a configured bus sends through the human transport and logs one line (107.058744ms)
|
||||
✔ without --send the route is read-only like every other write, and config says no send (5.771527ms)
|
||||
✔ with --send every other write is still 403 read-only, and nothing reaches the board or bus (4.756679ms)
|
||||
✔ config says send only on the public name with --send on (1.517372ms)
|
||||
✔ a send without the signed-in user is 401 and is neither sent nor logged, loopback included (3.149924ms)
|
||||
✔ each request check refuses before anything is sent, and logs the refusal without the body (10.497804ms)
|
||||
✔ a send passes exactly to, body and in_reply_to, answers the id, and logs it (2.20328ms)
|
||||
✔ a crafted role name cannot forge a log line (1.67614ms)
|
||||
✔ a bus refusal is not sent, with its status; an outcome the bus could not confirm is unknown and never retried (5.368638ms)
|
||||
✔ through the human transport the request is exactly the business, message.send and the keys (70.893922ms)
|
||||
✔ against a real broker: the message is written once as a human send, and its refusals map (19.300515ms)
|
||||
✔ loopback host and board origin fail closed (5.245331ms)
|
||||
✔ real board fixture passes through WebUI; assets and isolated seen/reply work (61.973408ms)
|
||||
✔ proxy preserves exact request bytes, status and receipt, rejects forms and malformed JSON, never follows redirect (39.238197ms)
|
||||
✔ unreachable board reports URL; CLI rejects unsupported options (310.217111ms)
|
||||
✔ render prints the unit without the preview flags (8.463284ms)
|
||||
✔ render carries every serve flag, the preview set included (5.910101ms)
|
||||
✔ a partial preview set is refused (13.116683ms)
|
||||
✔ a value the unit cannot carry is refused, for every flag (218.041498ms)
|
||||
✔ the rendered unit names none of the human proof agent markers and sets no agent variable (15.810568ms)
|
||||
✔ install into --dir with --no-reload writes the file whole, then reports unchanged (43.934141ms)
|
||||
✔ install without --no-reload runs daemon-reload and nothing that starts the unit (19.036315ms)
|
||||
✔ uninstall refuses while the unit is running, with or without --no-reload, and removes it once it is not (97.307852ms)
|
||||
✔ status prints the unit state and GET /healthz on the installed port (149.434817ms)
|
||||
✔ usage: an unknown verb or flag, and start or enable, exit 4 (51.603277ms)
|
||||
✔ without --send, render is the template with its placeholders filled, byte for byte (24.176124ms)
|
||||
✔ render --send with the preview set ends ExecStart with --send and changes nothing else (38.350676ms)
|
||||
✔ --send without the whole preview set is refused and writes nothing (97.836146ms)
|
||||
✔ install --send into --dir with --no-reload writes the sending unit, and status says whether it sends (184.247219ms)
|
||||
✔ uninstall and status take no --send (27.216946ms)
|
||||
✔ install refuses while the unit is running, in any state but inactive or failed, and changes nothing (200.586642ms)
|
||||
✔ when the state read fails, install and uninstall refuse with one line and change nothing (51.069488ms)
|
||||
✔ install needs --copy naming a copy that exists, and refuses outside the canonical checkout without --allow-worktree (46.388876ms)
|
||||
✔ install refuses unless the bus unit runs from the same copy, naming both paths, and changes nothing (169.201585ms)
|
||||
✔ render --copy runs the copy and reads the queue in the checkout; without --copy the unit is unchanged (13.521184ms)
|
||||
✔ the uid header takes only an Authentik uid; the username header still takes a username (235.730187ms)
|
||||
✔ a preview value cannot start with - or . (24.380381ms)
|
||||
✔ status names the copy and whether refactor has moved past it, and says when the unit runs from no copy (338.846372ms)
|
||||
✔ Settings form shows every scope and held role; gated save, exact payload, retained draft and no automatic retry (954.232149ms)
|
||||
2026-10-15T16:16:06.468Z settings user="jason" changed
|
||||
✔ REQ-WEB-1 signed-in same-origin Settings write reaches exactly one human operation (13.834684ms)
|
||||
✔ REQ-WEB-1 Settings writes require enabled send, named Host, identity, exact Origin and same-origin Fetch Metadata (5.564984ms)
|
||||
✔ REQ-WEB-1 Settings validates JSON, size, revision and strict writable keys before broker call (4.575844ms)
|
||||
✔ tokens.css and icons.svg are byte copies of docs/design (0.696392ms)
|
||||
✔ JetBrains Mono files match the digests in their sources file, with the OFL text (1.314905ms)
|
||||
✔ shipped strings are unchanged, and the web keeps its write boundary (1.692209ms)
|
||||
✔ shell in a browser: System default, seeded states, 400px, focus and the Ctrl+K palette (5349.69571ms)
|
||||
✔ five states on Board, Inbox, Tasks, Agents and Trail (2201.556788ms)
|
||||
✔ Queue, Business and Settings in their five states, with no move button (2947.791789ms)
|
||||
✔ seeded secrets, Discord ids and paths reach no response and no page; business refusals in the module's words (1024.50571ms)
|
||||
✔ the server log names no config path when the system config refuses (212.038764ms)
|
||||
ℹ tests 112
|
||||
ℹ suites 0
|
||||
ℹ pass 112
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 131123.758343
|
||||
@@ -0,0 +1,161 @@
|
||||
[
|
||||
{
|
||||
"suite": "pkg-bus",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/bus/tests/agents.test.mjs",
|
||||
"packages/bus/tests/broker.test.mjs",
|
||||
"packages/bus/tests/business.test.mjs",
|
||||
"packages/bus/tests/comment-cursors.test.mjs",
|
||||
"packages/bus/tests/comment-migration.test.mjs",
|
||||
"packages/bus/tests/credential-status.test.mjs",
|
||||
"packages/bus/tests/credentials.test.mjs",
|
||||
"packages/bus/tests/decision-close.test.mjs",
|
||||
"packages/bus/tests/decisions.test.mjs",
|
||||
"packages/bus/tests/end-launch.test.mjs",
|
||||
"packages/bus/tests/human.test.mjs",
|
||||
"packages/bus/tests/limits.test.mjs",
|
||||
"packages/bus/tests/message-citation.test.mjs",
|
||||
"packages/bus/tests/messages.test.mjs",
|
||||
"packages/bus/tests/messaging.test.mjs",
|
||||
"packages/bus/tests/process.test.mjs",
|
||||
"packages/bus/tests/replies.test.mjs",
|
||||
"packages/bus/tests/requirements.test.mjs",
|
||||
"packages/bus/tests/review.test.mjs",
|
||||
"packages/bus/tests/schema.test.mjs",
|
||||
"packages/bus/tests/single-use.test.mjs",
|
||||
"packages/bus/tests/state.test.mjs",
|
||||
"packages/bus/tests/store.test.mjs",
|
||||
"packages/bus/tests/task-page.test.mjs",
|
||||
"packages/bus/tests/task-read.test.mjs",
|
||||
"packages/bus/tests/tasks.test.mjs",
|
||||
"packages/bus/tests/tester.test.mjs",
|
||||
"packages/bus/tests/transport.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-tasks",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/tasks/tests/adapter.test.mjs",
|
||||
"packages/tasks/tests/comment-restart.test.mjs",
|
||||
"packages/tasks/tests/deploy.test.mjs",
|
||||
"packages/tasks/tests/fields.test.mjs",
|
||||
"packages/tasks/tests/requirements.test.mjs",
|
||||
"packages/tasks/tests/shapes.test.mjs",
|
||||
"packages/tasks/tests/startup.test.mjs",
|
||||
"packages/tasks/tests/sync.test.mjs",
|
||||
"packages/tasks/tests/tree.test.mjs",
|
||||
"packages/tasks/tests/verbs.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-cli",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/cli/tests/app.test.mjs",
|
||||
"packages/cli/tests/cli.test.mjs",
|
||||
"packages/cli/tests/config.test.mjs",
|
||||
"packages/cli/tests/follow.test.mjs",
|
||||
"packages/cli/tests/format.test.mjs",
|
||||
"packages/cli/tests/git-socket.test.mjs",
|
||||
"packages/cli/tests/host.test.mjs",
|
||||
"packages/cli/tests/launch-limits.test.mjs",
|
||||
"packages/cli/tests/launcher.test.mjs",
|
||||
"packages/cli/tests/limits.test.mjs",
|
||||
"packages/cli/tests/notifier.test.mjs",
|
||||
"packages/cli/tests/other-tree.test.mjs",
|
||||
"packages/cli/tests/stack-copy.test.mjs",
|
||||
"packages/cli/tests/tester.test.mjs",
|
||||
"packages/cli/tests/trackers-boot.test.mjs",
|
||||
"packages/cli/tests/transport.test.mjs",
|
||||
"packages/cli/tests/verbs.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-webui",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/webui/tests/board-held.test.mjs",
|
||||
"packages/webui/tests/browser-edge.test.mjs",
|
||||
"packages/webui/tests/browser.test.mjs",
|
||||
"packages/webui/tests/bus-browser.test.mjs",
|
||||
"packages/webui/tests/bus.test.mjs",
|
||||
"packages/webui/tests/conversation.test.mjs",
|
||||
"packages/webui/tests/discord.test.mjs",
|
||||
"packages/webui/tests/history-return-flow.test.mjs",
|
||||
"packages/webui/tests/messages.test.mjs",
|
||||
"packages/webui/tests/pinned-copy.test.mjs",
|
||||
"packages/webui/tests/preview.test.mjs",
|
||||
"packages/webui/tests/reads.test.mjs",
|
||||
"packages/webui/tests/relaunch.test.mjs",
|
||||
"packages/webui/tests/return-flow.test.mjs",
|
||||
"packages/webui/tests/send-browser.test.mjs",
|
||||
"packages/webui/tests/send.test.mjs",
|
||||
"packages/webui/tests/serve.test.mjs",
|
||||
"packages/webui/tests/service.test.mjs",
|
||||
"packages/webui/tests/settings-form.test.mjs",
|
||||
"packages/webui/tests/settings-write.test.mjs",
|
||||
"packages/webui/tests/shell.test.mjs",
|
||||
"packages/webui/tests/views.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-harness",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/harness/tests/bundle.test.mjs",
|
||||
"packages/harness/tests/claude-gate.test.mjs",
|
||||
"packages/harness/tests/claude-session.test.mjs",
|
||||
"packages/harness/tests/gate.test.mjs",
|
||||
"packages/harness/tests/git-tools.test.mjs",
|
||||
"packages/harness/tests/mcp-server.test.mjs",
|
||||
"packages/harness/tests/pi-session.test.mjs",
|
||||
"packages/harness/tests/runner.test.mjs",
|
||||
"packages/harness/tests/tools.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "pkg-seat",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"node",
|
||||
"--test",
|
||||
"--test-concurrency=1",
|
||||
"--test-reporter=spec",
|
||||
"packages/seat/tests/checkout.test.mjs",
|
||||
"packages/seat/tests/sandbox.test.mjs",
|
||||
"packages/seat/tests/seat.test.mjs",
|
||||
"packages/seat/tests/session.test.mjs",
|
||||
"packages/seat/tests/working.test.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"suite": "script-land-work",
|
||||
"exit": 0,
|
||||
"command": [
|
||||
"bash",
|
||||
"scripts/test-land-work.sh"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,86 @@
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK --base next refuses before the config is read (got 2)
|
||||
OK a missing system config exits 3 (got 3)
|
||||
OK nobus: exit 3
|
||||
OK schema-table: exit 2, bus-schema
|
||||
OK schema-meta: exit 2, bus-schema
|
||||
OK openBus opens the database read-only
|
||||
OK other-business: exit 2, decision-not-found
|
||||
OK no-raise: exit 2, decision-not-found
|
||||
OK not-a-merge: exit 2, not-a-merge
|
||||
OK open: exit 2, not-resolved
|
||||
OK withdrawn: exit 2, not-resolved
|
||||
OK by-agent: exit 2, not-human
|
||||
OK via-webui: exit 2, not-human
|
||||
OK no-answer: exit 2, not-human
|
||||
OK answer-role: exit 2, not-human
|
||||
OK answer-run: exit 2, not-human
|
||||
OK answer-choice: exit 2, not-human
|
||||
OK two-answers: exit 2, not-human
|
||||
OK chose-no: exit 2, not-merge-option
|
||||
OK two-refs: exit 2, work-ref
|
||||
OK bad-ref: exit 2, work-ref
|
||||
OK task-ref-disagrees: exit 2, work-ref
|
||||
OK raise-task-disagrees: exit 2, work-ref
|
||||
OK target-main: exit 2, target-branch
|
||||
OK superseded-question: exit 2, superseded
|
||||
OK superseded-task: exit 2, superseded
|
||||
OK superseded-by: exit 2, superseded
|
||||
OK no-verdict: exit 2, no-verdict
|
||||
OK changes-later: exit 2, not-approved
|
||||
OK short-commit: exit 2, not-approved
|
||||
OK wrong-task-body: exit 2, not-approved
|
||||
OK args: exit 2, decision-not-found
|
||||
OK earlier-merge: exit 0
|
||||
OK ref-moved: exit 2, ref-moved
|
||||
OK root-top: exit 2, root-file
|
||||
OK root-newdir: exit 2, root-file
|
||||
OK root-src: exit 2, root-file
|
||||
OK unrelated: exit 2, base-conflict
|
||||
OK empty: exit 2, base-conflict
|
||||
OK an empty reviewed diff says so
|
||||
OK dirty-changed: exit 2, checkout-dirty
|
||||
OK dirty-staged: exit 2, checkout-dirty
|
||||
OK dirty-untracked: exit 2, checkout-dirty
|
||||
OK conflict: exit 2, base-conflict
|
||||
OK a refusal after the worktree is added leaves no worktree or scratch
|
||||
OK cleanup looks for the worktree's Docker network
|
||||
OK dirty-during: exit 2, checkout-dirty
|
||||
OK a reviewed path dirtied during the gate moves no ref
|
||||
OK drift: exit 2, patch-drift
|
||||
OK patch-drift leaves no worktree or scratch
|
||||
OK gate-pkg: exit 2, gate-failed
|
||||
OK gate-failed names the failing step's log, and it exists
|
||||
OK gate-failed leaves no worktree or scratch
|
||||
OK gate-script: exit 2, gate-failed
|
||||
OK a failing scripts/test-*.sh fails the gate
|
||||
OK a failed gate moves no ref
|
||||
OK nomods: exit 4
|
||||
OK a target without node_modules leaves no worktree or scratch
|
||||
OK moved: exit 2, base-moved
|
||||
OK base-moved keeps the base where it moved to
|
||||
OK dry: exit 0
|
||||
OK --dry-run writes no ref
|
||||
OK --dry-run prints the commit with --subject and --attribution
|
||||
OK --dry-run runs the gate
|
||||
OK --dry-run leaves no worktree or scratch
|
||||
OK land: exit 0
|
||||
OK the landing is one commit on the old base
|
||||
OK its diff is the reviewed diff by patch-id
|
||||
OK its tree is the dry run's
|
||||
OK the message has the option's subject, the citations and the attribution last
|
||||
OK it prints the line for the PM
|
||||
OK the checked-out base has the reviewed paths and keeps the unrelated edit
|
||||
OK only refs/heads/refactor exists in the target
|
||||
OK the work ref is unchanged
|
||||
OK the bus database is unchanged
|
||||
OK the gate ran each package suite but queue, and each scripts/test-*.sh
|
||||
OK the landing leaves no worktree or scratch
|
||||
OK the target's node_modules is still there, with its contents
|
||||
OK the worktree's Docker network is removed
|
||||
---
|
||||
land-work selftests: 84 passed, 0 failed
|
||||
@@ -0,0 +1,16 @@
|
||||
✔ the boot config is checked before anything starts (12.798887ms)
|
||||
✔ a business with no tracker entry refuses task verbs (10.016191ms)
|
||||
✔ credential.expiring and .expired are recorded once per instance (27.542602ms)
|
||||
✔ a token file that changes on disk records credential.changed (13.042913ms)
|
||||
✔ autostart polls, reconciles and retries a startup the tracker was down for (33.845629ms)
|
||||
✔ a refusal a restart must clear is not retried by the poll (6.91246ms)
|
||||
✔ a poll that fires while two are queued is dropped (8.694878ms)
|
||||
✔ close waits for a running verb and refuses one that has not started (37.517795ms)
|
||||
ℹ tests 8
|
||||
ℹ suites 0
|
||||
ℹ pass 8
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 217.170355
|
||||
@@ -0,0 +1,13 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (27.868582ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (22.01672ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.596605ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.359056ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.642195ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 5
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 155.68026
|
||||
@@ -0,0 +1,20 @@
|
||||
✔ shared copy: npm ci, pushed reachability, readonly/existing copy, webui delegation (329.961857ms)
|
||||
✔ wrapper preserves Q81 lease and marker, rejects foreign/symlink; check uses effective roots (368.201634ms)
|
||||
✔ bus unit copy/pm pins, install refuses all busy states and failed reads, drop-in refusal (362.665471ms)
|
||||
✔ missing package manifest refuses before npm; npm failure removes the unpublished temp copy (243.666219ms)
|
||||
✔ real pinned install loads bus and Console; same-copy mosaic talk passes proof, other trees refuse (2902.923188ms)
|
||||
✔ bus status reads effective copy/pm/drop-ins without writes; check refuses an overridden ExecStart (419.86055ms)
|
||||
✔ drop-ins in either override field and malformed metadata refuse; uninstall also checks --no-reload (146.350641ms)
|
||||
✔ install never shows a template name on systemd 261; template drop-ins still refuse (150.939192ms)
|
||||
✔ unlisted instance drop-in is found in another unit lookup directory; path discovery errors refuse (131.777818ms)
|
||||
✔ inherited mosaic-.service.d override refuses without changing the unit (155.930079ms)
|
||||
✔ inherited service.d override refuses without changing the unit (154.266269ms)
|
||||
✔ inherited drop-in unreadable directory or file refuses before writing (134.586347ms)
|
||||
ℹ tests 12
|
||||
ℹ suites 0
|
||||
ℹ pass 12
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 5557.378466
|
||||
@@ -0,0 +1,10 @@
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (12.403291ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.392897ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 2
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 71.458997
|
||||
@@ -0,0 +1,11 @@
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (38.746013ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (57.998919ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (36.131812ms)
|
||||
ℹ tests 3
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 185.10879
|
||||
@@ -0,0 +1,9 @@
|
||||
✔ v3b prototype refusals, views and append-only mutations (51.482534ms)
|
||||
ℹ tests 1
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 101.449473
|
||||
@@ -0,0 +1,19 @@
|
||||
✔ an edit in the UI is recorded once, with the fields that changed (72.343428ms)
|
||||
✔ a move between open buckets is seen on the board, though updated does not change (35.26329ms)
|
||||
✔ a person's comment is counted and a bot's is not (62.726388ms)
|
||||
✔ the hourly reconcile catches a comment through comment_count (75.197639ms)
|
||||
✔ a task closed in the UI leaves the open view with its done bucket (113.519552ms)
|
||||
✔ a task that leaves the board is recorded as deleted, moved or out of reach (62.450006ms)
|
||||
✔ a poll that read before a verb wrote does not overwrite the verb (34.073533ms)
|
||||
✔ a tracker fault during a tick is reported and the next tick catches up (34.711051ms)
|
||||
✔ a malformed answer refuses the tick with tracker-shape (11.792419ms)
|
||||
✔ no token value reaches the database, the log or a refusal (43.103079ms)
|
||||
✔ the first look at a task counts only comments inside the window (32.279025ms)
|
||||
ℹ tests 11
|
||||
ℹ suites 0
|
||||
ℹ pass 11
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 644.534818
|
||||
@@ -0,0 +1,118 @@
|
||||
packages/bus/src/broker.mjs
|
||||
packages/bus/src/business.mjs
|
||||
packages/bus/src/client.mjs
|
||||
packages/bus/src/credentials.mjs
|
||||
packages/bus/src/human-cli.mjs
|
||||
packages/bus/src/human.mjs
|
||||
packages/bus/src/index.mjs
|
||||
packages/bus/src/migrate-schema.mjs
|
||||
packages/bus/src/process.mjs
|
||||
packages/bus/src/runtime.mjs
|
||||
packages/bus/src/server.mjs
|
||||
packages/bus/src/store.mjs
|
||||
packages/bus/src/tester-cli.mjs
|
||||
packages/bus/src/tester.mjs
|
||||
packages/bus/tests/agents.test.mjs
|
||||
packages/bus/tests/broker.test.mjs
|
||||
packages/bus/tests/business.test.mjs
|
||||
packages/bus/tests/comment-cursors.test.mjs
|
||||
packages/bus/tests/comment-migration.test.mjs
|
||||
packages/bus/tests/credential-status.test.mjs
|
||||
packages/bus/tests/credentials.test.mjs
|
||||
packages/bus/tests/decision-close.test.mjs
|
||||
packages/bus/tests/decisions.test.mjs
|
||||
packages/bus/tests/end-launch.test.mjs
|
||||
packages/bus/tests/human.test.mjs
|
||||
packages/bus/tests/limits.test.mjs
|
||||
packages/bus/tests/message-citation.test.mjs
|
||||
packages/bus/tests/messages.test.mjs
|
||||
packages/bus/tests/messaging.test.mjs
|
||||
packages/bus/tests/process.test.mjs
|
||||
packages/bus/tests/replies.test.mjs
|
||||
packages/bus/tests/requirements.test.mjs
|
||||
packages/bus/tests/review.test.mjs
|
||||
packages/bus/tests/single-use.test.mjs
|
||||
packages/bus/tests/state.test.mjs
|
||||
packages/bus/tests/store.test.mjs
|
||||
packages/bus/tests/task-page.test.mjs
|
||||
packages/bus/tests/task-read.test.mjs
|
||||
packages/bus/tests/tasks.test.mjs
|
||||
packages/bus/tests/tester.test.mjs
|
||||
packages/bus/tests/transport.test.mjs
|
||||
packages/cli/src/app.mjs
|
||||
packages/cli/src/cli.mjs
|
||||
packages/cli/src/config.mjs
|
||||
packages/cli/src/index.mjs
|
||||
packages/cli/src/launcher.mjs
|
||||
packages/cli/src/limits.mjs
|
||||
packages/cli/src/notifier-process.mjs
|
||||
packages/cli/tests/app.test.mjs
|
||||
packages/cli/tests/cli.test.mjs
|
||||
packages/cli/tests/config.test.mjs
|
||||
packages/cli/tests/follow.test.mjs
|
||||
packages/cli/tests/git-socket.test.mjs
|
||||
packages/cli/tests/helpers.mjs
|
||||
packages/cli/tests/host.test.mjs
|
||||
packages/cli/tests/launch-limits.test.mjs
|
||||
packages/cli/tests/launcher.test.mjs
|
||||
packages/cli/tests/limits.test.mjs
|
||||
packages/cli/tests/notifier.test.mjs
|
||||
packages/cli/tests/other-tree.test.mjs
|
||||
packages/cli/tests/stack-copy.test.mjs
|
||||
packages/cli/tests/tester.test.mjs
|
||||
packages/cli/tests/trackers-boot.test.mjs
|
||||
packages/cli/tests/transport.test.mjs
|
||||
packages/cli/tests/verbs.test.mjs
|
||||
packages/harness/src/runner.mjs
|
||||
packages/harness/tests/claude-session.test.mjs
|
||||
packages/harness/tests/pi-session.test.mjs
|
||||
packages/harness/tests/runner.test.mjs
|
||||
packages/harness/tests/tools.test.mjs
|
||||
packages/seat/tests/sandbox.test.mjs
|
||||
packages/seat/tests/session.test.mjs
|
||||
packages/tasks/src/adapter.mjs
|
||||
packages/tasks/src/digest.mjs
|
||||
packages/tasks/src/fake.mjs
|
||||
packages/tasks/src/fields.mjs
|
||||
packages/tasks/src/index.mjs
|
||||
packages/tasks/src/startup.mjs
|
||||
packages/tasks/src/sync.mjs
|
||||
packages/tasks/src/verbs.mjs
|
||||
packages/tasks/src/vikunja.mjs
|
||||
packages/tasks/tests/adapter.test.mjs
|
||||
packages/tasks/tests/comment-restart.test.mjs
|
||||
packages/tasks/tests/fields.test.mjs
|
||||
packages/tasks/tests/shapes.test.mjs
|
||||
packages/tasks/tests/startup.test.mjs
|
||||
packages/tasks/tests/sync.test.mjs
|
||||
packages/tasks/tests/tree.test.mjs
|
||||
packages/tasks/tests/verbs.test.mjs
|
||||
packages/tasks/tests/world.mjs
|
||||
packages/webui/src/cli.mjs
|
||||
packages/webui/src/reads.mjs
|
||||
packages/webui/src/serve.mjs
|
||||
packages/webui/tests/board-held.test.mjs
|
||||
packages/webui/tests/browser-edge.test.mjs
|
||||
packages/webui/tests/browser.test.mjs
|
||||
packages/webui/tests/bus-browser.test.mjs
|
||||
packages/webui/tests/bus.test.mjs
|
||||
packages/webui/tests/conversation.test.mjs
|
||||
packages/webui/tests/discord.test.mjs
|
||||
packages/webui/tests/fixture.mjs
|
||||
packages/webui/tests/history-fixture.mjs
|
||||
packages/webui/tests/history-return-flow.test.mjs
|
||||
packages/webui/tests/messages.test.mjs
|
||||
packages/webui/tests/pinned-copy.test.mjs
|
||||
packages/webui/tests/preview.test.mjs
|
||||
packages/webui/tests/reads.test.mjs
|
||||
packages/webui/tests/relaunch.test.mjs
|
||||
packages/webui/tests/return-flow.test.mjs
|
||||
packages/webui/tests/send-browser.test.mjs
|
||||
packages/webui/tests/send.test.mjs
|
||||
packages/webui/tests/serve.test.mjs
|
||||
packages/webui/tests/settings-form.test.mjs
|
||||
packages/webui/tests/settings-write.test.mjs
|
||||
packages/webui/tests/shell.test.mjs
|
||||
packages/webui/tests/views.test.mjs
|
||||
scripts/land-work/fixture.mjs
|
||||
scripts/land-work/read.mjs
|
||||
@@ -0,0 +1,5 @@
|
||||
16:export const SCHEMA_SHA256 = '179ffe356d4ff19a49b5ebad39b6c6bfd7771deb8e1b7c55b5e746f039d69e65';
|
||||
27:if (hex(ddl) !== SCHEMA_SHA256) throw Error('schema-source-mismatch');
|
||||
107: this.run('INSERT INTO meta(key,value) VALUES (?,?)', 'schema_version', '3b');
|
||||
113: this.get("SELECT value FROM meta WHERE key='schema_version'")?.value !== '3b' ||
|
||||
179ffe356d4ff19a49b5ebad39b6c6bfd7771deb8e1b7c55b5e746f039d69e65 -
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python3
|
||||
"""One deliberate fault per check. Restore bytes, isolate process groups, never count timeouts as kills."""
|
||||
import hashlib,json,os,pathlib,signal,subprocess,sys
|
||||
root=pathlib.Path('/mnt/storage/src/mosaic-stack-rocko-49')
|
||||
out=pathlib.Path(__file__).resolve().parent/'mutants';out.mkdir(exist_ok=True)
|
||||
restart='packages/tasks/tests/comment-restart.test.mjs'
|
||||
cursors='packages/bus/tests/comment-cursors.test.mjs'
|
||||
migration='packages/bus/tests/comment-migration.test.mjs'
|
||||
cases=[]
|
||||
def add(id,path,old,new,test): cases.append(dict(id=id,path=path,old=old,new=new,test=test))
|
||||
adapter='packages/tasks/src/adapter.mjs';sync='packages/tasks/src/sync.mjs';broker='packages/bus/src/broker.mjs';store='packages/bus/src/store.mjs'
|
||||
add('01-restore-durable-ids',adapter,'new Map(comments.cursors.map((c) => [c.task_id, c.last_comment]))','new Map()',restart)
|
||||
add('02-persist-observed-ids',broker,'for (const x of commentCursors)', 'for (const x of [])',restart)
|
||||
add('03-startup-comment-read',sync,'if (before === undefined || count !== before)','if (before !== undefined && count !== before)',restart)
|
||||
add('04-exclude-bots',sync,'fresh && !ctx.bots.has(c.author.id)','fresh',restart)
|
||||
add('05-strict-new-id',sync,'c.id > last','c.id >= last',restart)
|
||||
add('06-cache-after-commit',sync,' if (out.snapshots.length || out.events.length || out.commentCursors.length)',
|
||||
' for (const c of out.commentCursors) ctx.lastComment.set(c.task_id, c.last_comment);\n if (out.snapshots.length || out.events.length || out.commentCursors.length)',restart)
|
||||
add('07-event-cursor-atomicity',sync,'ctx.broker.recordTask({ business: ctx.business, ...out });',
|
||||
'ctx.broker.recordTask({ business: ctx.business, ...out, commentCursors: [] });\n if (out.commentCursors.length) ctx.broker.recordTask({ business: ctx.business, commentCursors: out.commentCursors });',restart)
|
||||
add('08-no-empty-poll-row',sync,'if (top > (last ?? 0))','if (true)',restart)
|
||||
add('09-initial-clock-margin',sync,'ctx.commentEpoch - WINDOW_MS','ctx.commentEpoch',restart)
|
||||
add('10-durable-initial-epoch',adapter,'commentEpoch: Date.parse(comments.epoch)','commentEpoch: clock()',restart)
|
||||
add('11-validate-cursor-input',broker,"if (![x.task_id, x.last_comment].every((n) => Number.isSafeInteger(n) && n > 0))",'if (false)',cursors)
|
||||
add('12-sync-only-cursor-write',broker,"if (cap !== null && commentCursors.length) fail('agent-required');",'/* sync-only check omitted */',cursors)
|
||||
add('13-business-isolation',broker,"ORDER BY task_id`, business,","ORDER BY task_id`, 'demo',",cursors)
|
||||
add('14-explicit-offline-only',store,'if (!fresh && migrateSchema) this.#migrateSchema();','if (!fresh) this.#migrateSchema();',migration)
|
||||
add('15-pinned-source-metadata',store,'this.get("SELECT value FROM meta WHERE key=\'schema_digest\'")?.value !== step.fromDigest ||','false ||',migration)
|
||||
add('16-chain-all-steps',store,'while (version !== SCHEMA_VERSION)','if (version !== SCHEMA_VERSION)',migration)
|
||||
add('17-preserve-source-copy',store,'this.#db.exec(step.sql);',"this.#db.exec(step.sql);\n this.#db.exec(\"DROP TRIGGER events_no_delete; DELETE FROM events; CREATE TRIGGER events_no_delete BEFORE DELETE ON events BEGIN SELECT RAISE(ABORT, 'events is append-only'); END\");",migration)
|
||||
add('18-land-work-version','scripts/land-work/read.mjs',"meta('schema_version') !== SCHEMA_VERSION","meta('schema_version') !== '3b'",'scripts/test-land-work.sh')
|
||||
add('21-exclusive-writer-lock',store,"fd = openSync(this.#lock, 'wx', 0o600);","fd = openSync(this.#lock, 'w', 0o600);",migration)
|
||||
add('22-migration-command','packages/bus/src/migrate-schema.mjs','migrateSchema: true','migrateSchema: false',migration)
|
||||
results=[]
|
||||
for c in cases:
|
||||
file=root/c['path'];before=file.read_bytes();source=before.decode();n=source.count(c['old'])
|
||||
if n!=1: raise RuntimeError(f"{c['id']}: expected one mutation site, found {n}")
|
||||
file.write_text(source.replace(c['old'],c['new']))
|
||||
try:
|
||||
command=['bash',c['test']] if c['test'].endswith('.sh') else ['node','--test',c['test']]
|
||||
with (out/(c['id']+'.log')).open('w') as log:
|
||||
p=subprocess.Popen(command,cwd=root,env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'},
|
||||
stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try: rc=p.wait(timeout=180)
|
||||
except subprocess.TimeoutExpired: os.killpg(p.pid,signal.SIGKILL);p.wait();rc='timeout'
|
||||
content=(out/(c['id']+'.log')).read_text()
|
||||
invalid=any(x in content for x in ['SyntaxError:', 'ERR_MODULE_NOT_FOUND', 'schema-source-mismatch', 'migration-target-mismatch'])
|
||||
verdict='INVALID' if invalid else 'TIMEOUT' if rc=='timeout' else 'SURVIVED' if rc==0 else 'KILLED'
|
||||
result={k:c[k] for k in ['id','path','test']};result.update(result=verdict,exit=rc)
|
||||
results.append(result);(out/'results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
print(c['id'],verdict,rc,flush=True)
|
||||
finally:file.write_bytes(before)
|
||||
if verdict!='KILLED':sys.exit(1)
|
||||
sys.exit(0)
|
||||
@@ -0,0 +1,40 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (28.005928ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (18.960515ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (14.603286ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (11.999457ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (11.083573ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 152.910563
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (18.960515ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:52:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:61:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (14.603286ms)
|
||||
Error: adapter-failed
|
||||
at Object.restart (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/world.mjs:157:56)
|
||||
at async TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:69:3)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,49 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (28.517177ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (10.900855ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (17.175169ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (11.629073ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.342446ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 143.625558
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (10.900855ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:37:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:61:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (17.175169ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:70:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (25.941362ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (17.089876ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (15.120332ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.028781ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (11.259771ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 148.303354
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:17:1
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (25.941362ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:24:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (17.089876ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
1 !== 2
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:51:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 2,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (29.183359ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (18.710754ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.073767ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (11.617748ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.721692ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 152.517053
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (18.710754ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:52:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (28.316491ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (19.895057ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (15.111054ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (11.651132ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (11.241306ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 156.324758
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (19.895057ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
3 !== 2
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:51:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 3,
|
||||
expected: 2,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:61:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (15.111054ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:70:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (28.545386ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (22.402873ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.808901ms)
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (13.910082ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.751415ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 163.092499
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:75:1
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (13.910082ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:82:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (29.254906ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (23.04829ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (15.866562ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.728213ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.650272ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 160.600869
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:61:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (15.866562ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:70:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (19.782582ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (8.479875ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (8.142129ms)
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (9.392503ms)
|
||||
✖ initial cursor accepts a comment within the stated one-minute clock skew margin (8.950959ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 5
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 128.140802
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:17:1
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (19.782582ms)
|
||||
Error: invalid-request
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:76:9)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:613:90
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:169:16)
|
||||
at reconcile (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:264:3) {
|
||||
code: 'invalid-request'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:31:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (8.479875ms)
|
||||
Error: invalid-request
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:76:9)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:613:90
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:169:16)
|
||||
at reconcile (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:264:3) {
|
||||
code: 'invalid-request'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:61:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (8.142129ms)
|
||||
Error: invalid-request
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:76:9)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:613:90
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:169:16)
|
||||
at reconcile (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:264:3) {
|
||||
code: 'invalid-request'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:75:1
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (9.392503ms)
|
||||
Error: invalid-request
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:76:9)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:613:90
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:169:16)
|
||||
at reconcile (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:264:3) {
|
||||
code: 'invalid-request'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:87:1
|
||||
✖ initial cursor accepts a comment within the stated one-minute clock skew margin (8.950959ms)
|
||||
Error: invalid-request
|
||||
at fail (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:76:9)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:613:90
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:169:16)
|
||||
at reconcile (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/src/sync.mjs:264:3) {
|
||||
code: 'invalid-request'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (28.64484ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (23.666868ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.221301ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.560194ms)
|
||||
✖ initial cursor accepts a comment within the stated one-minute clock skew margin (9.83601ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 157.825837
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:87:1
|
||||
✖ initial cursor accepts a comment within the stated one-minute clock skew margin (9.83601ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:96:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (27.250983ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (22.74315ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.223463ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.305807ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (10.000772ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 155.212154
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:17:1
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (27.250983ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:24:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (10.284426ms)
|
||||
✖ only trusted sync writes validated cursors; events and cursor share rollback (7.210591ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 70.431667
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-cursors.test.mjs:37:1
|
||||
✖ only trusted sync writes validated cursors; events and cursor share rollback (7.210591ms)
|
||||
AssertionError [ERR_ASSERTION]: The validation function is expected to return "true". Received false
|
||||
|
||||
Caught error:
|
||||
|
||||
Error: CHECK constraint failed: task_id > 0
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:43:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: Error: CHECK constraint failed: task_id > 0
|
||||
at Store.run (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:192:34)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:614:21
|
||||
at Store.transaction (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:213:22)
|
||||
at Broker.recordTask (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/broker.mjs:610:24)
|
||||
at record (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:18:64)
|
||||
at assert.throws.record.task_id (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:43:25)
|
||||
at getActual (node:assert:580:5)
|
||||
at strict.throws (node:assert:728:24)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:43:12)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14),
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
✔ comment cursors isolate businesses, move only forward and remain append-only (10.674228ms)
|
||||
✖ only trusted sync writes validated cursors; events and cursor share rollback (7.31472ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 70.371053
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-cursors.test.mjs:37:1
|
||||
✖ only trusted sync writes validated cursors; events and cursor share rollback (7.31472ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:45:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.527912ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.435787ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 70.128434
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-cursors.test.mjs:21:1
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.527912ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
|
||||
+ actual - expected
|
||||
|
||||
[
|
||||
{
|
||||
+ last_comment: 15,
|
||||
- last_comment: 2,
|
||||
task_id: 7
|
||||
}
|
||||
]
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:27:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: [ { task_id: 7, last_comment: 15 } ],
|
||||
expected: [ { task_id: 7, last_comment: 2 } ],
|
||||
operator: 'deepStrictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (32.552296ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (60.748386ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (37.060975ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (29.074581ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (95.244116ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 303.209541
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:31:1
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (32.552296ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:34:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /schema-mismatch/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (39.540678ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (57.244122ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (36.896082ms)
|
||||
✖ migration refuses mismatched source metadata without changing schema or evidence (31.467615ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (102.735849ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 319.923127
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:94:1
|
||||
✖ migration refuses mismatched source metadata without changing schema or evidence (31.467615ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:99:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /schema-mismatch/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (37.342944ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (56.790949ms)
|
||||
✖ named migration registry chains 3b through 3c to a fixture-only future version in order (35.878789ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (29.134341ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (103.552105ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 310.603264
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:65:1
|
||||
✖ named migration registry chains 3b through 3c to a fixture-only future version in order (35.878789ms)
|
||||
Error: schema-mismatch
|
||||
at new Store (file:///mnt/storage/scratch/tmp/comment-migration-0xrMeg/future-bus/src/store.mjs:145:15)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:85:18)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,31 @@
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (34.369883ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (56.180221ms)
|
||||
✖ named migration registry chains 3b through 3c to a fixture-only future version in order (35.04965ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (29.700367ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (102.526376ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 3
|
||||
ℹ fail 2
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 308.691614
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:31:1
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (34.369883ms)
|
||||
TypeError: Cannot read properties of undefined (reading 'body')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:37:73)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17)
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:65:1
|
||||
✖ named migration registry chains 3b through 3c to a fixture-only future version in order (35.04965ms)
|
||||
TypeError: Cannot read properties of undefined (reading 'id')
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:89:51)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7)
|
||||
@@ -0,0 +1,106 @@
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 2, target-branch
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK args: exit 4
|
||||
OK --base next refuses before the config is read (got 2)
|
||||
OK a missing system config exits 3 (got 3)
|
||||
OK nobus: exit 3
|
||||
OK schema-table: exit 2, bus-schema
|
||||
OK schema-meta: exit 2, bus-schema
|
||||
file:///mnt/storage/src/mosaic-stack-rocko-49/scripts/land-work/read.mjs:33
|
||||
throw new Refusal(reason, detail);
|
||||
^
|
||||
|
||||
Refusal [Error]: meta says version 3c, digest d7b8a781f2ac
|
||||
at refuse (file:///mnt/storage/src/mosaic-stack-rocko-49/scripts/land-work/read.mjs:33:9)
|
||||
at checkSchema (file:///mnt/storage/src/mosaic-stack-rocko-49/scripts/land-work/read.mjs:82:5)
|
||||
at openBus (file:///mnt/storage/src/mosaic-stack-rocko-49/scripts/land-work/read.mjs:55:5)
|
||||
at file:///mnt/storage/src/mosaic-stack-rocko-49/[eval1]:3:12
|
||||
at ModuleJob.run (node:internal/modules/esm/module_job:569:25)
|
||||
at async node:internal/modules/esm/loader:226:26
|
||||
at async ModuleLoader.executeModuleJob (node:internal/modules/esm/loader:223:20)
|
||||
at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:101:5) {
|
||||
reason: 'bus-schema'
|
||||
}
|
||||
|
||||
Node.js v26.8.1
|
||||
FAIL openBus opens the database read-only
|
||||
FAIL other-business: exit 2, wanted 2 decision-not-found: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL no-raise: exit 2, wanted 2 decision-not-found: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL not-a-merge: exit 2, wanted 2 not-a-merge: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL open: exit 2, wanted 2 not-resolved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL withdrawn: exit 2, wanted 2 not-resolved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL by-agent: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL via-webui: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL no-answer: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL answer-role: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL answer-run: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL answer-choice: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL two-answers: exit 2, wanted 2 not-human: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL chose-no: exit 2, wanted 2 not-merge-option: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL two-refs: exit 2, wanted 2 work-ref: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL bad-ref: exit 2, wanted 2 work-ref: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL task-ref-disagrees: exit 2, wanted 2 work-ref: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL raise-task-disagrees: exit 2, wanted 2 work-ref: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL target-main: exit 2, wanted 2 target-branch: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL superseded-question: exit 2, wanted 2 superseded: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL superseded-task: exit 2, wanted 2 superseded: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL superseded-by: exit 2, wanted 2 superseded: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL no-verdict: exit 2, wanted 2 no-verdict: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL changes-later: exit 2, wanted 2 not-approved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL short-commit: exit 2, wanted 2 not-approved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL wrong-task-body: exit 2, wanted 2 not-approved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL args: exit 2, wanted 2 decision-not-found: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL earlier-merge: exit 2, wanted 0: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL ref-moved: exit 2, wanted 2 ref-moved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL root-top: exit 2, wanted 2 root-file: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL root-newdir: exit 2, wanted 2 root-file: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL root-src: exit 2, wanted 2 root-file: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL unrelated: exit 2, wanted 2 base-conflict: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL empty: exit 2, wanted 2 base-conflict: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL an empty reviewed diff says so
|
||||
FAIL dirty-changed: exit 2, wanted 2 checkout-dirty: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL dirty-staged: exit 2, wanted 2 checkout-dirty: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL dirty-untracked: exit 2, wanted 2 checkout-dirty: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL conflict: exit 2, wanted 2 base-conflict: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
OK a refusal after the worktree is added leaves no worktree or scratch
|
||||
OK cleanup looks for the worktree's Docker network
|
||||
FAIL dirty-during: exit 2, wanted 2 checkout-dirty: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
OK a reviewed path dirtied during the gate moves no ref
|
||||
FAIL drift: exit 2, wanted 2 patch-drift: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
OK patch-drift leaves no worktree or scratch
|
||||
FAIL gate-pkg: exit 2, wanted 2 gate-failed: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL gate-failed names the failing step's log, and it exists
|
||||
OK gate-failed leaves no worktree or scratch
|
||||
FAIL gate-script: exit 2, wanted 2 gate-failed: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL a failing scripts/test-*.sh fails the gate
|
||||
OK a failed gate moves no ref
|
||||
FAIL nomods: exit 2, wanted 4: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
OK a target without node_modules leaves no worktree or scratch
|
||||
FAIL moved: exit 2, wanted 2 base-moved: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL base-moved keeps the base where it moved to
|
||||
FAIL dry: exit 2, wanted 0: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
OK --dry-run writes no ref
|
||||
FAIL --dry-run prints the commit with --subject and --attribution
|
||||
FAIL --dry-run runs the gate
|
||||
OK --dry-run leaves no worktree or scratch
|
||||
FAIL land: exit 2, wanted 0: land-work: refused: bus-schema meta says version 3c, digest d7b8a781f2ac: bus-schema meta says version 3c, digest d7b8a781f2ac
|
||||
FAIL the landing is one commit on the old base
|
||||
fatal: bad object d37df7db28eb71d11b670275b506e2226e65436e
|
||||
OK its diff is the reviewed diff by patch-id
|
||||
FAIL its tree is the dry run's
|
||||
fatal: bad object d37df7db28eb71d11b670275b506e2226e65436e
|
||||
FAIL the message has the option's subject, the citations and the attribution last
|
||||
FAIL it prints the line for the PM
|
||||
FAIL the checked-out base has the reviewed paths and keeps the unrelated edit
|
||||
OK only refs/heads/refactor exists in the target
|
||||
OK the work ref is unchanged
|
||||
OK the bus database is unchanged
|
||||
grep: /gate.log: No such file or directory
|
||||
FAIL the gate ran each package suite but queue, and each scripts/test-*.sh
|
||||
OK the landing leaves no worktree or scratch
|
||||
OK the target's node_modules is still there, with its contents
|
||||
OK the worktree's Docker network is removed
|
||||
---
|
||||
land-work selftests: 26 passed, 58 failed
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.078382ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.151096ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 69.411141
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-cursors.test.mjs:21:1
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.078382ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:33:13)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /append-only/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.405908ms)
|
||||
✔ only trusted sync writes validated cursors; events and cursor share rollback (7.068233ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 67.73242
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-cursors.test.mjs:21:1
|
||||
✖ comment cursors isolate businesses, move only forward and remain append-only (11.405908ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-cursors.test.mjs:28:47)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /must advance/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (45.090871ms)
|
||||
✖ migration refuses active writers and drifted legacy schemas, with no partial upgrade (60.538001ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (37.422878ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (31.85347ms)
|
||||
✔ offline command migrates only the supplied fixture root and reports usage errors (103.245046ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 325.810621
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:49:1
|
||||
✖ migration refuses active writers and drifted legacy schemas, with no partial upgrade (60.538001ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:62:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.processPendingSubtests (node:internal/test_runner/test:974:18)
|
||||
at Test.postRun (node:internal/test_runner/test:1542:19)
|
||||
at Test.run (node:internal/test_runner/test:1467:12)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /writer-locked/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
✔ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (37.363022ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (58.699075ms)
|
||||
✔ named migration registry chains 3b through 3c to a fixture-only future version in order (37.858983ms)
|
||||
✔ migration refuses mismatched source metadata without changing schema or evidence (30.150316ms)
|
||||
✖ offline command migrates only the supplied fixture root and reports usage errors (62.20026ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 4
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 274.872082
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:106:1
|
||||
✖ offline command migrates only the supplied fixture root and reports usage errors (62.20026ms)
|
||||
AssertionError [ERR_ASSERTION]: migration refused: schema-mismatch
|
||||
|
||||
|
||||
1 !== 0
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:111:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 1,
|
||||
expected: 0,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
[
|
||||
{
|
||||
"id": "01-restore-durable-ids",
|
||||
"path": "packages/tasks/src/adapter.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "02-persist-observed-ids",
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "03-startup-comment-read",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "04-exclude-bots",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "05-strict-new-id",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "06-cache-after-commit",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "07-event-cursor-atomicity",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "08-no-empty-poll-row",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "09-initial-clock-margin",
|
||||
"path": "packages/tasks/src/sync.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "10-durable-initial-epoch",
|
||||
"path": "packages/tasks/src/adapter.mjs",
|
||||
"test": "packages/tasks/tests/comment-restart.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "11-validate-cursor-input",
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"test": "packages/bus/tests/comment-cursors.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "12-sync-only-cursor-write",
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"test": "packages/bus/tests/comment-cursors.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "13-business-isolation",
|
||||
"path": "packages/bus/src/broker.mjs",
|
||||
"test": "packages/bus/tests/comment-cursors.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "14-explicit-offline-only",
|
||||
"path": "packages/bus/src/store.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "15-pinned-source-metadata",
|
||||
"path": "packages/bus/src/store.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "16-chain-all-steps",
|
||||
"path": "packages/bus/src/store.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "17-preserve-source-copy",
|
||||
"path": "packages/bus/src/store.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "18-land-work-version",
|
||||
"path": "scripts/land-work/read.mjs",
|
||||
"test": "scripts/test-land-work.sh",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "21-exclusive-writer-lock",
|
||||
"path": "packages/bus/src/store.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "22-migration-command",
|
||||
"path": "packages/bus/src/migrate-schema.mjs",
|
||||
"test": "packages/bus/tests/comment-migration.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"id": "19-append-only-cursor-evidence",
|
||||
"path": "packages/bus/schema.sql + matching migration DDL",
|
||||
"test": "packages/bus/tests/comment-cursors.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
},
|
||||
{
|
||||
"id": "20-monotonic-cursor",
|
||||
"path": "packages/bus/schema.sql + matching migration DDL",
|
||||
"test": "packages/bus/tests/comment-cursors.test.mjs",
|
||||
"result": "KILLED",
|
||||
"exit": 1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,71 @@
|
||||
c65046eb1b2420a87ea17bdf2118d6a4dafebc3195eb1f002f9ba00ce24a9730 BUILD.md
|
||||
b753f630301bf125e9e286b4156d0736930dd8fb9cd8eb2ebf316688f9191a07 DDL.sql
|
||||
a881909e64eb8d9eb142d069098b2490c9cd6b8142a56457c5bfe2134d0cf600 HANDOFF.md
|
||||
5839f2df034baae6f980e81111f006ece4367232cec519e073bd264456e8f37e MIGRATION.md
|
||||
e693ff8400534fae44e475ce1422390ce6598533dab697480165518fb532c50e MUTANTS.md
|
||||
41d4ac89273398fb4677b9341a1d8d677f4d7f92bd8ab44752f8bafff5535bab base.txt
|
||||
35546194585146904441e06b6fe3ba87cead7464f2a570a632cfb4b404415a04 build.patch
|
||||
ba45d57c9b255311bb220598f90c1a4fb01b420511974c28f102881cbd7df21a busy-before-mutants.log
|
||||
ba45d57c9b255311bb220598f90c1a4fb01b420511974c28f102881cbd7df21a busy-check.log
|
||||
f96467d1db869496c274d0ac92284130f38f60af074af0580eb423eff30355d6 busy.py
|
||||
87ef1321a1a08be64a20499889fc24b5549b47d6d33abfd86db95f62fb3cb6d0 candidate-manifest.sha256
|
||||
3e2f603acf5c007b96b0dae6e37985a9e7e966015f4db961cc7ddcf43053e2c8 gate/pkg-bus.log
|
||||
ee78575d3f14f385f5a85d47d62f53b127bb053782b3386aa632ce5c823a4247 gate/pkg-cli.log
|
||||
82b4a1e4bdc90c09115504f74b4ffff76c9c1a498a18d65137df11841343e4d0 gate/pkg-harness.log
|
||||
5daf1b9018f053eede5e32a3a75d18426846a7d9a6a3f8ee9dfe93cb8048ba79 gate/pkg-seat.log
|
||||
2eb73f9f9a5303ee5a1eab424ac90690dc40bcc7a3bbaa2a6fd60b2c678b585d gate/pkg-tasks.log
|
||||
b3f044a8e3d37d8dae19c7f6ea4025625f1292dc95dcad205ba77f339d5dd717 gate/pkg-webui.log
|
||||
5e2eb19c92025dfd5553e760b05578270396d8814871572cc3d1bc1de5715b8f gate/results.json
|
||||
8e2254aa3e1bb9b205ab72c68273d447c0328c9f156ccba2a46f3a0476468b58 gate/script-land-work.log
|
||||
428da18d15f3ca0b42b4f7d2b39d92a6b1a32556bc94f46c70a95ac2b5c42133 gate-copy-failure/pkg-bus.log
|
||||
e16912290b0dbee3a97b109ab69307a4235147dc38a8fe3ff940cf1deeeaa96a gate-copy-failure/pkg-cli.log
|
||||
529f978905bd1d655a40c868dd605831e99fb230be21afd3b15d572adb62177c gate-copy-failure/pkg-tasks.log
|
||||
0bf0dab068f6bb86bd2df9851c99c383ef4218a3081b5d1b905f2784b6213279 gate-copy-failure/results.json
|
||||
333e2e7b516cf4fd5743f68ee088ee55c0363efdc5f2f949087efeb2e7d7d1b6 gate-setup-failure/pkg-bus.log
|
||||
7f524659d60b9b6c40460424dce7d70e33cec4a54b63d8e7d8d1c204f7afccab gate-setup-failure/pkg-cli.log
|
||||
8cd14dabf01294b2ec507df3684f1cc75f91cd37ee4e5c91020aa40a42062877 gate-setup-failure/pkg-tasks.log
|
||||
0bf0dab068f6bb86bd2df9851c99c383ef4218a3081b5d1b905f2784b6213279 gate-setup-failure/results.json
|
||||
e3cf413b6529fbd2933d599bd061015a2e66ae300a6e5bd1e8776afc0bd822a3 gate.py
|
||||
20aee40b264a01a38f600ef03a4ccdf7cbedde6d41c178f9888ac06cf8b005a4 green-adapter.log
|
||||
832965736cde51e7535efcec29f55f7c09e117c84446bfcf528d9b2ae111bf6d green-comments.log
|
||||
eb467b8e1609749b5bbb8f58b22fe764936a046ea84388b925f4faec272b6521 green-copy.log
|
||||
2f02ef5e3e9463bb036adbe0d69e77ebefcc29518fc440a8a45b425f4203f7fd green-cursors.log
|
||||
e587c2e5d47709c76f5ac404ffdb01de6a3a8d93aa0e77d498faaca88e98d5b7 green-migration.log
|
||||
c2dd9873f3babad5b7a81e907aa1c81b24b2868cd5353b0dcd662002da17e239 green-schema.log
|
||||
9591cb77d6d2f842e5499a69c6dd2d8e79163a8caa9aff2ad8e9984774bd1a96 green-sync.log
|
||||
d6e9b1eeddb2bc05f18ef690948cb815856345c60ab52c1225a86c57e1a69151 import-consumers.txt
|
||||
4b028a9dc2541914d4e4b961de66b4abca7bfe8afe43b0999cc833d3bd3abef5 live-schema-evidence.txt
|
||||
4613a426b620a1a2e9207fdb67af48a34fd1e563041e938579b6abede19fa839 mutants/01-restore-durable-ids.log
|
||||
e438a8e33e654ae686367b1d764f121eb825bfb257b1b9bd79ad73d06ac553e5 mutants/02-persist-observed-ids.log
|
||||
260dcb4134f0112fea864bd15bf580093e5793cb121306fbdb3b538f5e469a40 mutants/03-startup-comment-read.log
|
||||
2b5ff04af374084cc33845644c4cdbb953e0a1b21a13135e5021b0d50f2f637d mutants/04-exclude-bots.log
|
||||
dadff25d58729cd26dcad856c21e038ed84758724a847a92130e98c1a1dd16eb mutants/05-strict-new-id.log
|
||||
3cbe24b3ecce666d786e6a436ccba1435b88e2a304a8efc521a8ea2e90cdd688 mutants/06-cache-after-commit.log
|
||||
a82b7aa4590acef6e9af1c748afc7c1847a94d7a368b1a6abdfec6632a995699 mutants/07-event-cursor-atomicity.log
|
||||
484185b9dd18f0fd7137c6717370d72e2ba20395d2ea0ed94ba038302ed3ea07 mutants/08-no-empty-poll-row.log
|
||||
9f592a70dd5fc3c2f9e4a5d04fac362373d32d1b1f350c21c3c55a5bf73ac188 mutants/09-initial-clock-margin.log
|
||||
3721d552fe450c79cac2d409f254afc6fab048b5b94b8379bfc7dd478c7a020b mutants/10-durable-initial-epoch.log
|
||||
59065844d77a4ee61315d7033fe6b84963076a03862aa6ccedf7735dcf0f544f mutants/11-validate-cursor-input.log
|
||||
09e131da5363ac4f0811ce55d1ceeda12cf11b13ebb50f94e664667a1eb8d8cb mutants/12-sync-only-cursor-write.log
|
||||
75d30a0ca429bda8809b00b5376776a5e50dcb97582b6dbcaa9cbebc83c2fe16 mutants/13-business-isolation.log
|
||||
71f800f47b21e1ed8527da7fe9b8228e0cb86569afebe0f23119d592e24c37fd mutants/14-explicit-offline-only.log
|
||||
567fcd48fc383d3c3460454afb60a900c6d57ecbc94288d40580fc0a6d8de033 mutants/15-pinned-source-metadata.log
|
||||
8d88cf03632974857ad3761763c4f2c6f2406691a0dada33ae73cbe874a099a3 mutants/16-chain-all-steps.log
|
||||
d57c4bc21ade8f9de14b76e97cf4399fa7b961a1c41102b0103627ee1e8a49bd mutants/17-preserve-source-copy.log
|
||||
7a54737de63d88b702f54ed78b419e1a62a5360ad5ded9108977aa2c2c124da5 mutants/18-land-work-version.log
|
||||
8da216b35a3812114ae8b5af7798c99e76303e1699e0561f03945231fdd107ca mutants/19-append-only-cursor-evidence.log
|
||||
d1efb3fdad0d2e093bc20b930a7ef8a7c121cea45b59653be1a6d5c7ae73d29a mutants/20-monotonic-cursor.log
|
||||
ee88d369aebd9c54fb093580d3f33fee80ac4248035cf8f4d4eb927315b4d317 mutants/21-exclusive-writer-lock.log
|
||||
6c3233e554756513dd2244441901be1111588a4f96703e4e418988f1f387f3bf mutants/22-migration-command.log
|
||||
e10e4fc5f8a0536d69708b48ebcbec7d28d4a02fc444ff17155a511ade0ff939 mutants/results.json
|
||||
c4c2d3967de1ef39127b07bb03ad0976c52b8da1e4d7c17b878d2cf8a08e1c44 mutants/sql-results.json
|
||||
16796b6a1fcd28c4602187992446e1fdf7ecc20ba3dd732c74d3e818f9be6a98 mutants.py
|
||||
d777d5f548e9b05cd58615867b7b68980204fc8032c3e07135002b98ac54ea00 prepare.py
|
||||
37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570 process-sweep.json
|
||||
43998241cf266f2581366e3b1b9366f2b6fd5dca6a5a243ffc80a6ff622012ae rebuild-manifest.txt
|
||||
688e6f76d653e3b3b963a34f58be7318071f68296b48be30774afc345f76577a red-comments.log
|
||||
a9bdff1d3e8a0f94c8b4297dd0eec4611a223f4ddb9cca9b7da1c1942cc9755c red-migration.log
|
||||
4ddc7f058bdaea97ff65349c94811af6b826a24ce56653ac3eaf4a9428acdf4b restored-comments.log
|
||||
3c478ec3216185a386636aebf540a0064288e66b66413d4a9941e42c1ad2c586 restored-manifest.txt
|
||||
9da83b2b48feb2461ece011c78dc7ae06c8b67bcc51d30e2cc532e031fd89e0e scan.json
|
||||
366cdf3d4bf64018e5a2fc9f1adac5b50eec8c8a654c3bbc67c0a3dc7de20a4d sql-mutants.py
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
import hashlib,pathlib,subprocess
|
||||
root=pathlib.Path('/mnt/storage/src/mosaic-stack-rocko-49');out=pathlib.Path(__file__).resolve().parent
|
||||
tracked=subprocess.check_output(['git','diff','--name-only'],cwd=root,text=True).splitlines()
|
||||
new=subprocess.check_output(['git','ls-files','--others','--exclude-standard','--','packages/bus/src','packages/bus/tests','packages/tasks/tests'],cwd=root,text=True).splitlines()
|
||||
paths=sorted(set(tracked+new))
|
||||
assert all(p.startswith(('packages/bus/','packages/tasks/','scripts/land-work/')) for p in paths)
|
||||
patch=subprocess.check_output(['git','diff','--binary','--no-ext-diff'],cwd=root)
|
||||
for path in sorted(new):
|
||||
r=subprocess.run(['git','diff','--no-index','--binary','--','/dev/null',path],cwd=root,stdout=subprocess.PIPE)
|
||||
assert r.returncode==1
|
||||
patch+=r.stdout
|
||||
(out/'build.patch').write_bytes(patch)
|
||||
(out/'candidate-manifest.sha256').write_text(''.join(hashlib.sha256((root/p).read_bytes()).hexdigest()+' '+p+'\n' for p in paths))
|
||||
(out/'base.txt').write_bytes(subprocess.check_output(['git','rev-parse','HEAD'],cwd=root))
|
||||
print('candidate files',len(paths),'manifest sha',hashlib.sha256((out/'candidate-manifest.sha256').read_bytes()).hexdigest())
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,17 @@
|
||||
packages/bus/README.md: OK
|
||||
packages/bus/schema.sql: OK
|
||||
packages/bus/src/broker.mjs: OK
|
||||
packages/bus/src/migrate-schema.mjs: OK
|
||||
packages/bus/src/migrations/3b-3c.sql: OK
|
||||
packages/bus/src/migrations/3b.sql: OK
|
||||
packages/bus/src/store.mjs: OK
|
||||
packages/bus/tests/comment-cursors.test.mjs: OK
|
||||
packages/bus/tests/comment-migration.test.mjs: OK
|
||||
packages/bus/tests/fixtures/schema-3b.sql: OK
|
||||
packages/bus/tests/schema.test.mjs: OK
|
||||
packages/tasks/README.md: OK
|
||||
packages/tasks/src/adapter.mjs: OK
|
||||
packages/tasks/src/sync.mjs: OK
|
||||
packages/tasks/tests/comment-restart.test.mjs: OK
|
||||
packages/tasks/tests/world.mjs: OK
|
||||
scripts/land-work/read.mjs: OK
|
||||
@@ -0,0 +1,78 @@
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (31.224532ms)
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (13.150195ms)
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (23.243094ms)
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (12.860134ms)
|
||||
ℹ tests 4
|
||||
ℹ suites 0
|
||||
ℹ pass 0
|
||||
ℹ fail 4
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 162.21039
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:16:1
|
||||
✖ stopped bus resumes an empty task cursor after a long outage, exactly once (31.224532ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:23:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async startSubtestAfterBootstrap (node:internal/test_runner/harness:387:3) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:30:1
|
||||
✖ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (13.150195ms)
|
||||
Error: no such table: task_comment_cursors
|
||||
at Store.get (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/src/store.mjs:128:21)
|
||||
at rows (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:35:30)
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:36:16)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
code: 'ERR_SQLITE_ERROR',
|
||||
errcode: 1,
|
||||
errstr: 'SQL logic error'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:60:1
|
||||
✖ commit followed by crash before cache advance neither loses nor duplicates a comment (23.243094ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
2 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:71:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 2,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
|
||||
test at packages/tasks/tests/comment-restart.test.mjs:74:1
|
||||
✖ failed event insert rolls back cursor and a retry still emits the comment once (12.860134ms)
|
||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||
|
||||
0 !== 1
|
||||
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/tasks/tests/comment-restart.test.mjs:81:10)
|
||||
at async Test.run (node:internal/test_runner/test:1409:7)
|
||||
at async Test.processPendingSubtests (node:internal/test_runner/test:974:7) {
|
||||
generatedMessage: true,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: 0,
|
||||
expected: 1,
|
||||
operator: 'strictEqual',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (33.45361ms)
|
||||
✔ migration refuses active writers and drifted legacy schemas, with no partial upgrade (57.816901ms)
|
||||
ℹ tests 2
|
||||
ℹ suites 0
|
||||
ℹ pass 1
|
||||
ℹ fail 1
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 140.115716
|
||||
|
||||
✖ failing tests:
|
||||
|
||||
test at packages/bus/tests/comment-migration.test.mjs:31:1
|
||||
✖ explicit 3b copy migration preserves evidence and opens as 3c; normal startup never migrates (33.45361ms)
|
||||
AssertionError [ERR_ASSERTION]: Missing expected exception.
|
||||
at TestContext.<anonymous> (file:///mnt/storage/src/mosaic-stack-rocko-49/packages/bus/tests/comment-migration.test.mjs:34:10)
|
||||
at Test.runInAsyncScope (node:async_hooks:226:14)
|
||||
at Test.run (node:internal/test_runner/test:1402:25)
|
||||
at Test.start (node:internal/test_runner/test:1262:17)
|
||||
at startSubtestAfterBootstrap (node:internal/test_runner/harness:387:17) {
|
||||
generatedMessage: false,
|
||||
code: 'ERR_ASSERTION',
|
||||
actual: undefined,
|
||||
expected: /schema-mismatch/,
|
||||
operator: 'throws',
|
||||
diff: 'simple'
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
✔ stopped bus resumes an empty task cursor after a long outage, exactly once (30.685468ms)
|
||||
✔ persisted IDs avoid replay, exclude bots and bound rows to observed new comments (23.936732ms)
|
||||
✔ commit followed by crash before cache advance neither loses nor duplicates a comment (14.604568ms)
|
||||
✔ failed event insert rolls back cursor and a retry still emits the comment once (12.157324ms)
|
||||
✔ initial cursor accepts a comment within the stated one-minute clock skew margin (9.925179ms)
|
||||
ℹ tests 5
|
||||
ℹ suites 0
|
||||
ℹ pass 5
|
||||
ℹ fail 0
|
||||
ℹ cancelled 0
|
||||
ℹ skipped 0
|
||||
ℹ todo 0
|
||||
ℹ duration_ms 160.500044
|
||||
@@ -0,0 +1 @@
|
||||
17/17 candidate hashes restored after mutants
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files": 70,
|
||||
"findings": [],
|
||||
"scope": "packet bytes only; no live config, secrets or database read"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
import hashlib,json,os,pathlib,re,signal,subprocess,sys
|
||||
root=pathlib.Path('/mnt/storage/src/mosaic-stack-rocko-49')
|
||||
out=pathlib.Path(__file__).resolve().parent/'mutants'
|
||||
paths=['packages/bus/schema.sql','packages/bus/src/migrations/3b-3c.sql','packages/bus/src/store.mjs']
|
||||
original={path:(root/path).read_bytes() for path in paths}
|
||||
results=[]
|
||||
for id,pattern in [
|
||||
('19-append-only-cursor-evidence',r'CREATE TRIGGER task_comment_cursors_no_(?:update|delete|replace)\b.*?END;\n'),
|
||||
('20-monotonic-cursor',r'CREATE TRIGGER task_comment_cursors_forward\b.*?END;\n'),
|
||||
]:
|
||||
try:
|
||||
for path in paths[:2]:
|
||||
text=original[path].decode();text,n=re.subn(pattern,'',text,flags=re.S)
|
||||
assert n==(3 if id.startswith('19') else 1)
|
||||
(root/path).write_text(text)
|
||||
sha=hashlib.sha256((root/paths[0]).read_bytes()).hexdigest()
|
||||
(root/paths[2]).write_text(re.sub(r"export const SCHEMA_SHA256 = '[a-f0-9]+';",f"export const SCHEMA_SHA256 = '{sha}';",original[paths[2]].decode()))
|
||||
with (out/(id+'.log')).open('w') as log:
|
||||
p=subprocess.Popen(['node','--test','packages/bus/tests/comment-cursors.test.mjs'],cwd=root,
|
||||
env={**os.environ,'DOCKER_HOST':'unix:///nonexistent.sock'},stdout=log,stderr=subprocess.STDOUT,start_new_session=True)
|
||||
try:rc=p.wait(timeout=90)
|
||||
except subprocess.TimeoutExpired:os.killpg(p.pid,signal.SIGKILL);p.wait();rc='timeout'
|
||||
content=(out/(id+'.log')).read_text()
|
||||
invalid=any(x in content for x in ['SyntaxError:', 'ERR_MODULE_NOT_FOUND','schema-source-mismatch','migration-target-mismatch'])
|
||||
verdict='INVALID' if invalid else 'TIMEOUT' if rc=='timeout' else 'SURVIVED' if rc==0 else 'KILLED'
|
||||
results.append(dict(id=id,path='packages/bus/schema.sql + matching migration DDL',test='packages/bus/tests/comment-cursors.test.mjs',result=verdict,exit=rc))
|
||||
print(id,verdict,rc,flush=True)
|
||||
finally:
|
||||
for path,data in original.items():(root/path).write_bytes(data)
|
||||
(out/'sql-results.json').write_text(json.dumps(results,indent=2)+'\n')
|
||||
sys.exit(0 if all(r['result']=='KILLED' for r in results) else 1)
|
||||
@@ -984,3 +984,4 @@ are never rewritten or removed; corrections are new entries.
|
||||
2026-10-15 15:55:15 UTC | Sage (Opus 5.5, 1ef1e4f8) | decision 78 ready | Jason via Mos sage-0204 (Q161): "D4 yes"; recorded as lead decision 146 in be9377a91: ready = row 42's acceptance run passes with Jason on the live mosaic-stack business; merge plan starts then, step 4 merge stays Jason's
|
||||
2026-10-15 15:58:40 UTC | Sage (Opus 5.5, 1ef1e4f8) | launch ready rows | Mos sage-0205: rows 121 #1615 (darkwing, design first), 123 #1617 (researcher), 131 #1626 (dewey) launched in sage-0291 to 0293; row 49 #1535 reassigned sage to rocko (rev 1268, queue ffb7d3f5f) and launched in sage-0294; row 99 stays blocked with its recorded reason (Mos decision 133)
|
||||
2026-10-15 16:20:14 UTC | Rocko (Codex gpt-6.1-sol, d99326cc) | row 49 #1535 comment cursor across restarts r1 | built on 7b166a0f1; explicit 3b→3c named migration, durable IDs/epoch, atomic events/cursors, no empty-poll rows; gate bus178 tasks97 cli195 webui112 harness84 seat132 land-work84 green; 22/22 mutants killed; 17/17 rebuild/restored hashes, sweep empty, slot clear16:18:57; packet agents/rocko/work/queue-49/r1 manifest87ef1321; in-review1276/requestfailed1277 exit1 missing token, Sage posts; no live action
|
||||
2026-10-15 16:21:33 UTC | Sage (Opus 5.5, 1ef1e4f8) | row 121 design, slot, row 49 review | row 121 #1615 design approved with five changes in 28556 (delivery_same_thread scoped to the thread's instance; threadIdleSeconds optional, default 900; one-assistant refusal; id pattern on store path; chief chain refusal text), sage-0308; queue revs 1269-1275 committed cf12c25e9, which also swept Rocko's 1276-1277; slot Rocko to Dewey (sage-0309, sage-0310); row 49 review request posted as jarvis, 28557, revs 1278-1279 uncommitted (Dewey holds the slot); Researcher sent row 49 r1 for the 3c to 3d rebase (sage-0311); Rocko packet r1 committed after PACKET_OK and a clean secrets scan (candidate 87ef1321, packet a37384d8) | done
|
||||
|
||||
Reference in New Issue
Block a user