✔ a first launch clones the root at its branch, with the root's path as origin (55.129034ms)
✔ the clone is not at its place until git clone has finished (42.434942ms)
✔ a later launch fast-forwards a clean clone after a commit to the root, then finds it current (88.059355ms)
✔ a clone ahead of the root keeps its commits and counts as current (54.277329ms)
▶ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves
  ✔ a modified file (67.05712ms)
  ✔ an untracked file (67.64398ms)
  ✔ a staged file (67.740963ms)
  ✔ another branch (54.779448ms)
  ✔ a detached HEAD (61.865239ms)
✔ a dirty clone and one on another branch are fetched, and nothing but refs/remotes moves (320.666248ms)
✔ a diverged clone gets the fetch into refs/remotes and is kept, not-fast-forward (63.98781ms)
▶ a clone kept before the branch check, or for a failed status, gets no fetch
  ✔ not-a-clone (30.847315ms)
  ✔ hooks-present (27.949904ms)
  ✔ submodule (32.446806ms)
  ✔ config-changed (29.021583ms)
  ✔ root-unreadable (42.147369ms)
  ✔ root-detached (78.267198ms)
  ✔ status-failed, on the root's branch and clean (58.798955ms)
  ✔ status-failed, dirty (42.729782ms)
✔ a clone kept before the branch check, or for a failed status, gets no fetch (343.804239ms)
✔ a dirty clone whose fetch fails is kept, fetch-failed, exactly as it was (41.340173ms)
✔ every git call the host makes, for a new clone and an existing one, carries maintenance.auto=false and gc.auto=0 (45.118955ms)
✔ a clone with loose objects enough for gc --auto gets no maintenance or gc from the fetch and the merge (73.886235ms)
▶ a clone with user.name or user.email in its config is kept, and git runs nothing in it
  ✔ user.name (27.170178ms)
  ✔ user.email (26.680098ms)
✔ a clone with user.name or user.email in its config is kept, and git runs nothing in it (54.290865ms)
✔ a commit git can't read after the fast-forward is null (45.746196ms)
✔ a new clone whose commit can't be read refuses the launch and leaves nothing behind (18.555457ms)
▶ a clone the session rigged is kept, and git runs nothing and writes nothing outside it
  ✔ core.fsmonitor (36.201285ms)
  ✔ core.hooksPath (34.977817ms)
  ✔ a hook file (32.978016ms)
  ✔ include.path (33.949682ms)
  ✔ includeIf (32.739314ms)
  ✔ a filter driver (33.572499ms)
  ✔ origin moved (33.265937ms)
  ✔ a second origin url (33.381831ms)
  ✔ the origin url twice, both the root (37.521812ms)
  ✔ an ext:: origin (41.394889ms)
  ✔ a branch tracking another remote (35.167234ms)
  ✔ a branch merging a tag (36.32183ms)
  ✔ a fetch line onto local branches (38.776444ms)
  ✔ no origin (39.058652ms)
  ✔ a config file over the size cap (31.278954ms)
  ✔ config a symlink to /dev/zero (30.031049ms)
  ✔ the clone a symlink to the bait (30.529654ms)
  ✔ the clone a file (30.490781ms)
  ✔ the clone a plain directory (31.040718ms)
  ✔ .git a gitdir: file (32.848292ms)
  ✔ .git a symlink (31.097617ms)
  ✔ .git/logs a symlink (31.656183ms)
  ✔ .git/refs/heads a symlink (31.139275ms)
  ✔ .git/objects a symlink (31.005991ms)
  ✔ a reflog hard-linked to a file outside (30.91947ms)
  ✔ HEAD a fifo (31.531146ms)
  ✔ a commondir file (30.955263ms)
  ✔ an alternates file (30.77278ms)
  ✔ a gitlink staged, no .gitmodules (42.701948ms)
  ✔ a gitlink and .gitmodules staged (43.979349ms)
  ✔ a gitlink to a repository with its own gitlink (52.020991ms)
  ✔ a gitlink and .gitmodules committed (47.89971ms)
  ✔ a gitlink and submodule.active in config (44.215563ms)
  ✔ a .git/modules with no gitlink (32.621176ms)
✔ a clone the session rigged is kept, and git runs nothing and writes nothing outside it (1202.479513ms)
▶ a root that can't be cloned refuses with the project id and leaves nothing behind
  ✔ missing (9.895926ms)
  ✔ not a repository (9.904509ms)
  ✔ a plain directory inside another repository (14.558613ms)
  ✔ unreadable (10.024951ms)
  ✔ on no branch (12.379787ms)
  ✔ missing an object (15.052973ms)
✔ a root that can't be cloned refuses with the project id and leaves nothing behind (72.604936ms)
✔ a clone whose root is on no branch, or gone, is kept and named (27.914895ms)
✔ no credential or forge remote of the root reaches a clone (48.136408ms)
✔ every project in the business file gets its own clone at its own branch (34.066848ms)
✔ a clone past its time gets SIGTERM and refuses the launch, with nothing left in the workspace (513.385596ms)
✔ a clone that ignores SIGTERM gets SIGKILL once the grace period is over (1018.500569ms)
✔ a timeout signals git's process group, so a process git started dies with it (517.042096ms)
✔ once a signalled git has closed, its group gets SIGKILL, so a process that ignored SIGTERM dies too (512.63261ms)
✔ rootHits: a top-level file, a new top-level directory, src/ and v1/ are the root; paths under known directories aren't (1.340421ms)
✔ gateEnv keeps the named variables that are strings and drops everything else (0.206825ms)
✔ isMosaicStack: a checkout whose HEAD descends from the root commit and has node_modules; nothing else (38.21332ms)
✔ gateSteps: each package with tests but queue in name order, then each scripts/test-*.sh (2.4486ms)
✔ runGate: every step passes, each with its own log and a summary line, under the environment it was given (227.182735ms)
✔ runGate: the first failing step stops the gate and names its log (323.290338ms)
✔ runGate: an abort stops the running step and everything in its group, and runs nothing after it (188.197043ms)
✔ the CLI: root-file prints the hits and exits 2, or exits 0; gate exits 0, or 2 with the step and its log; anything else is usage (608.161978ms)
✔ RUNNER_FILES is exactly what the runner and the harness sources it starts import (3.632198ms)
✔ sandboxProblem names a missing bwrap and a bwrap that fails (15.082467ms)
✔ every bind says why; the bundle and session file stay read-only over the run directory (2.813839ms)
✔ REQ-THREAD-2 a thread store binds its session directory and Claude transcripts, and nothing more (1.958305ms)
✔ the host's git socket is bound only when given, read-only and before the writable binds (1.061098ms)
✔ the git identity is the instance's, at <instance>@<business>.mosaic.invalid, and sandboxArgv refuses without it (1.445659ms)
✔ a confined session's shell reaches its own workspace and run directory and nothing of the founder's or another session's (1851.216316ms)
✔ a bind that exposes a stand-in, or a missing workspace bind, fails the matching check (2413.677025ms)
✔ a confined session that runs tester-cli.mjs is refused as tester, and the same shim outside the sandbox binds (209.100389ms)
✔ resolveSeat: by name under --repo resolves the repo layout (2.255128ms)
✔ resolveSeat: by path resolves the fleet layout (0.594926ms)
✔ resolveSeat: refusals for missing dir, missing launch.sh, non-executable launch.sh, invalid name, and unknown layout (1.175736ms)
✔ tmuxContext: outside tmux, default socket, custom socket, and exec failure (1.13409ms)
✔ makeRegistration produces a record that validates; each shape violation throws SeatError (1.375682ms)
✔ writeRegistration/readRegistration: round trip, permissions, absence, and malformed records (2.161829ms)
✔ updateTask: changes task, taskSetBy and updatedAt only, and refuses appropriately (2.165102ms)
✔ CLI launch: registers, execs the fake launch script, and passes args through (50.136853ms)
✔ CLI launch: --harness lands in the record (46.078127ms)
✔ CLI launch: the launch script's own exit code passes through (42.734175ms)
✔ CLI launch: relaunching a seat rewrites the one registration record (78.081991ms)
✔ CLI launch: omitting --task records an empty string, not null (43.778252ms)
✔ CLI seat task: updates only the task after a launch, and refuses on an unlaunched seat (117.543566ms)
✔ CLI refusals: no args, unknown flag, missing config, already-registered env, and exec failure (172.574347ms)
✔ samePath: equal paths, symlinked dirs, distinct dirs, and non-strings (0.559714ms)
✔ resolveSetBy: explicit --by wins over the environment; absent or empty environment gives unknown; invalid explicit or environment values refuse with exit 4 (0.668929ms)
✔ 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.805628ms)
✔ 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.10384ms)
✔ 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 (356.921317ms)
✔ REQ-LIMIT-1: family substring matching is no longer exported (1.361665ms)
✔ sessionEnv passes only the allowlist, the repo's bin on PATH, and the run id (0.888781ms)
✔ sessionExit gives a runner's signal death back as the signal; a session credential is one whole set of nonempty variables (0.319013ms)
✔ newRun: short ids, 0700 directories, and a refusal when the socket path won't fit (2.042065ms)
✔ session file and launch log: 0600, the session file written once (1.770938ms)
✔ endReason maps the runner's exit codes; a signal is killed (0.186306ms)
✔ Registry mirrors to sessions.json; readSessions marks live entries; bad files refuse (3.383906ms)
✔ REQ-THREAD-1 Registry.running keys a thread run by business, instance and thread (2.073898ms)
✔ REQ-THREAD-2 REQ-LAUNCH-1 threadStore checks both segments before the join and refuses an unsafe directory (2.566145ms)
✔ stopSession refuses an unknown run, reports a stale one, and won't signal a pid that isn't a runner (1.654145ms)
✔ a session runs in its sandbox as pid 1 of its namespace, claims, answers, and stops on mosaic stop (257.411679ms)
✔ workRef and validBranch take only what a ref name can hold (1.804167ms)
✔ a push lands as the task's work ref, a fast-forward lands after it, and main is the root's (170.853987ms)
✔ a rewritten branch refuses non-fast-forward and the work ref stays (133.731932ms)
✔ a branch with no history in common with main refuses unrelated-history (77.653679ms)
✔ a bundle that needs commits the working repository lacks refuses missing-prerequisite (61.685207ms)
✔ the root is fetched again before each push and main follows it, so a clone of a newer root pushes (145.673121ms)
✔ a root moved back after the clone leaves the push's base unknown: missing-prerequisite (80.282929ms)
✔ a commit with a broken object refuses invalid-bundle, and only because fsck is on (69.179235ms)
✔ only a v2 bundle with the named branch is read (98.325002ms)
✔ a branch named main, or named for another task, moves only this task's work ref (119.064869ms)
✔ a record that throws moves the work ref back, or removes a new one (112.374811ms)
✔ a work ref that can't go back refuses rollback-failed, naming the ref and the commit (369.412809ms)
✔ a root that can't be read refuses root-unreadable (27.284282ms)
✔ a git past its time gets SIGTERM, leaves no ref lock, and the next push lands (2139.795164ms)
✔ a git that ignores SIGTERM gets SIGKILL once the grace period is over (1029.986316ms)
✔ a working repository path that isn't a directory refuses (24.134654ms)
✔ review bundles a pushed commit as refs/mosaic/review, leaving out what the reviewer has (109.85921ms)
✔ review of a project with no working repository refuses unknown-commit (13.217968ms)
✔ the runner's git tools hold the host's limits and branch rule (1.146971ms)
✔ a reseed moves root but leaves a landed main, and main forwards once root contains it (175.682312ms)
✔ after a landing, a push built on the root still lands and main stays where the landing put it (114.502826ms)
✔ once the root shares no history with a landed main, a push is checked against main, not the root (168.161576ms)
✔ a landing squashes the reviewed diff onto main as the bus host and moves main only at finish (105.287462ms)
✔ a landing refuses ref-moved, base-conflict and root-file before it makes a commit (296.264852ms)
✔ a landing whose applied diff isn't the reviewed one refuses patch-drift and leaves no worktree (120.423597ms)
✔ finish refuses base-moved when main moved, and a record that throws moves main back (255.525206ms)
ℹ tests 150
ℹ suites 0
ℹ pass 150
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 6102.706302
