6.9 KiB
Gate environment rows: the memory slug and the leaked compose networks
Found during row 219's gate (#1720) on 10-23. Mos named both as rows in mos-1434 and mos-1438, to be
added after 219 landed (5fdfd7275). Vikunja 590 and 591.
Brief: claude-session test builds the memory slug the way the CLI does (Vikunja 590)
Gitea #1811. Owner Rocko. Reviewer Dewey. Gate owner Sage.
packages/harness/tests/claude-session.test.mjs "CLAUDE.md files and auto-memory don't reach the
model" (:270) plants MARKER-MEMORY under projects/<slug>/memory/MEMORY.md. It builds the slug at
:272 with realpathSync(workspace).replace(/[/.]/g, "-"). Claude Code 2.1.309 maps _ to - as
well. Under a TMPDIR with _ (Python tempfile.mkdtemp, for example rh85v_4j3), the planted file
sits in a directory the CLI never reads. The control run without --restricted then misses
MARKER-MEMORY and the test fails at :298. The mos-1432 diagnostic on clean 07802dc57 showed it: an
alphanumeric TMPDIR passed 10/0, and a TMPDIR with _ failed 9/1 at :298.
Change (test-only, in a pre-existing test, so the exact diff goes to Mos through Sage before the
build under mos-1272): at :272 only, build the slug with .replace(/[^A-Za-z0-9]/g, "-"). Before
changing it, check the mapping against the installed CLI. Run the test under a TMPDIR that has _
and under one that has -, and record both results in BUILD.md. If the CLI maps anything
differently from that regex, stop and report it to Sage. Nothing else in the test changes.
Gate: Dewey approves the diff. On Sage's gate, in a gap, packages/harness/tests/claude-session.test.mjs
runs whole and green three times: under a mktemp TMPDIR, under a TMPDIR whose name has _, and
under one with a space if the CLI accepts it (record it if it doesn't). Mutant: revert :272 to the
old regex; under the _ TMPDIR it must fail at :298.
Mos approved the :272 change under mos-1272 (mos-1442 point 1). No assertion changes. With the
fix, the :298 control plants MARKER-MEMORY where the CLI reads it, so the restricted check at :291
no longer passes vacuously for the memory marker under a _ TMPDIR.
Until this row lands, every gate keeps using an alphanumeric mktemp TMPDIR (mos-1432).
Brief: shell suites remove the compose network they create (Vikunja 591)
Gitea #1812. Owner Gizmoduck. Reviewer Filbert. Gate owner Sage.
scripts/run-task.sh reaches packages/processing-control/src/containers.mjs containerArgs
(:16), which runs docker compose run --rm. --rm removes the container but leaves the project's
<project>_default bridge network behind. With no COMPOSE_PROJECT_NAME, compose names the
project after the checkout directory, so every gate worktree leaves one network. By 10-23 the
leftovers had used up Docker's default address pools (about 31 bridge networks). test-release.sh's
health check (release.sh :41-57) then failed activate at :68, and row 219's gate went 11/3.
Sage removed 18 unused _default networks under mos-1437/1438, and test-release.sh passed 14/0.
Change, in scripts/test-release.sh and scripts/test-task.sh, the two suites that run tasks:
- export
COMPOSE_PROJECT_NAME=mosaic-test-<suite>-<id>, where<id>is the lowercase alphanumeric suffix of that run's mktemp sandbox.compose.yamlnames its image explicitly, so the project name changes only the network and the default container names; - in the existing EXIT trap, run
docker network rm "${COMPOSE_PROJECT_NAME}_default". A network that was never created is fine. Any other failure prints one stderr line naming the network and changes no exit status; - never run
docker compose down, and never remove any other network. A test run from the canonical checkout must not touch the live stack's project, and with this change it doesn't use that project name.
Each suite adds one check of its own after its last Docker step. Call the cleanup function the trap
uses, then assert that docker network ls -q --filter name=^${COMPOSE_PROJECT_NAME}_default$ is
empty. New assertions in existing suites go to Mos through Sage with the diff before the build.
No product file changes. packages/processing-control and scripts/run-task.sh stay as they are.
Gate: Filbert approves the diff. On Sage's gate, in a gap, both suites run whole and green. Before
and after each run, record docker network ls filtered to that run's project name: the network
must be absent after the run. Mutant: drop the network rm, and the new check must fail.
Mos approved the export, the trap's network rm and one new check per suite under mos-1272
(mos-1442 point 2). Both existing traps (test-task.sh:11, test-release.sh:15) keep everything they
do now, including the RELEASE restore and the sandbox rm. The rm is only added. Before building on
the export, confirm that COMPOSE_PROJECT_NAME reaches compose: containers.mjs:25 passes
options to spawnSync, and compose.yaml has no top-level name:. scripts/mosaic-task.mjs:326
builds spawnEnv from process.env, so the task path looks like it carries the variable. Check
every path the two suites take. If any path drops it, stop and report to Sage, and change no
product file.
Until this row lands, each gate removes its own <dir>_default network at the end (mos-1438).
Brief: a revoked run's late bus call stops it instead of exiting 22 (295 N1)
Gitea #1813. Owner Morgana. Reviewer Dewey. Gate owner Sage. After row 272 is done, because both rows touch the broker.
Row 295 (#1801, 2efd127ce) ends a revoked user's thread claims in one transaction (#revokeLost,
packages/bus/src/broker.mjs:1012), and the launcher then sends SIGTERM. A run that calls the bus
between the claim end and the SIGTERM fails #agent (:1068-1070) with not-holder. The runner
(packages/harness/src/runner.mjs:486-498) counts not-holder as a gone session and exits 22, so
the run record reads error. Row 302 gave the launcher's own release the answer launcher-released,
which the runner maps to stopped. It covers threadIdle and landRelease only (#launcherReleased,
:431).
Change: a run whose claim #revokeLost ended answers thread-revoked on every call that needs the
claim, until the run ends. The runner maps thread-revoked from a call to stopped, the same way it
maps launcher-released. A new claim keeps refusing thread-revoked (:1371) as it does now. Not-holder
from any other cause is unchanged.
Tests, red first under mos-1272:
- a forcing test holds the window open after the sweep and before SIGTERM, makes one bus call, and checks the thread-revoked answer and the runner's stopped exit;
- a run that lost its claim some other way still gets not-holder.
Mutants:
- drop the revoked check in
#agent; - have the runner map thread-revoked to 22;
- mark every ended claim as revoked.
Changes to existing tests go to Mos through Sage first.
Gate: Dewey approves the design and then the manifest. On Sage's gate, the bus, harness and cli
suites run green, along with every scripts/test-*.sh.