From a94a943c92e245cbe8b931d7c7f9fdf14d051ab8 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Wed, 14 Oct 2026 15:39:45 -0500 Subject: [PATCH] work: Rocko row 114 round 1 packet (#1608), candidate manifest 68c60a799146 Co-Authored-By: Claude Opus 5.5 --- agents/rocko/work/queue-114/r1/BUILD.md | 116 ++++++ agents/rocko/work/queue-114/r1/base.txt | 1 + agents/rocko/work/queue-114/r1/build.patch | 392 ++++++++++++++++++ .../queue-114/r1/candidate-manifest.sha256 | 7 + agents/rocko/work/queue-114/r1/files.txt | 7 + agents/rocko/work/queue-114/r1/gate.py | 27 ++ agents/rocko/work/queue-114/r1/mutants.py | 22 + .../r1/out/checkout-render-after.txt | 39 ++ .../r1/out/checkout-render-before.txt | 39 ++ .../queue-114/r1/out/final-verification.txt | 1 + .../queue-114/r1/out/full/gate-results.json | 68 +++ .../queue-114/r1/out/full/node-discord.txt | 191 +++++++++ .../work/queue-114/r1/out/full/test-auth.txt | 17 + .../queue-114/r1/out/full/test-conductor.txt | 23 + .../queue-114/r1/out/full/test-config.txt | 26 ++ .../queue-114/r1/out/full/test-discord.txt | 82 ++++ .../r1/out/full/test-extension-package.txt | 21 + .../queue-114/r1/out/full/test-foundation.txt | 53 +++ .../queue-114/r1/out/full/test-land-work.txt | 86 ++++ .../work/queue-114/r1/out/full/test-queue.txt | 36 ++ .../queue-114/r1/out/full/test-release.txt | 7 + .../work/queue-114/r1/out/full/test-task.txt | 32 ++ .../work/queue-114/r1/out/green-final.txt | 13 + agents/rocko/work/queue-114/r1/out/green.txt | 35 ++ .../r1/out/mutants/checkout-execstart.txt | 30 ++ .../r1/out/mutants/missing-pi-accepted.txt | 30 ++ .../r1/out/mutants/offline-calls-getMe.txt | 31 ++ .../queue-114/r1/out/mutants/summary.json | 17 + .../work/queue-114/r1/out/network-clear.txt | 1 + .../work/queue-114/r1/out/network-inspect.txt | 2 + .../work/queue-114/r1/out/process-clear.txt | 1 + .../work/queue-114/r1/out/queue-in-review.txt | 3 + .../work/queue-114/r1/out/red-offline.txt | 67 +++ .../work/queue-114/r1/out/red-service.txt | 53 +++ .../work/queue-114/r1/out/suite-counts.json | 126 ++++++ .../queue-114/r1/out/test-discord-first.txt | 82 ++++ .../work/queue-114/r1/packet-manifest.sha256 | 38 ++ .../rocko/work/queue-114/r1/process-sweep.py | 13 + agents/rocko/work/queue-114/r1/verify.sh | 10 + 39 files changed, 1845 insertions(+) create mode 100644 agents/rocko/work/queue-114/r1/BUILD.md create mode 100644 agents/rocko/work/queue-114/r1/base.txt create mode 100644 agents/rocko/work/queue-114/r1/build.patch create mode 100644 agents/rocko/work/queue-114/r1/candidate-manifest.sha256 create mode 100644 agents/rocko/work/queue-114/r1/files.txt create mode 100644 agents/rocko/work/queue-114/r1/gate.py create mode 100644 agents/rocko/work/queue-114/r1/mutants.py create mode 100644 agents/rocko/work/queue-114/r1/out/checkout-render-after.txt create mode 100644 agents/rocko/work/queue-114/r1/out/checkout-render-before.txt create mode 100644 agents/rocko/work/queue-114/r1/out/final-verification.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/gate-results.json create mode 100644 agents/rocko/work/queue-114/r1/out/full/node-discord.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-auth.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-conductor.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-config.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-discord.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-extension-package.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-foundation.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-land-work.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-queue.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-release.txt create mode 100644 agents/rocko/work/queue-114/r1/out/full/test-task.txt create mode 100644 agents/rocko/work/queue-114/r1/out/green-final.txt create mode 100644 agents/rocko/work/queue-114/r1/out/green.txt create mode 100644 agents/rocko/work/queue-114/r1/out/mutants/checkout-execstart.txt create mode 100644 agents/rocko/work/queue-114/r1/out/mutants/missing-pi-accepted.txt create mode 100644 agents/rocko/work/queue-114/r1/out/mutants/offline-calls-getMe.txt create mode 100644 agents/rocko/work/queue-114/r1/out/mutants/summary.json create mode 100644 agents/rocko/work/queue-114/r1/out/network-clear.txt create mode 100644 agents/rocko/work/queue-114/r1/out/network-inspect.txt create mode 100644 agents/rocko/work/queue-114/r1/out/process-clear.txt create mode 100644 agents/rocko/work/queue-114/r1/out/queue-in-review.txt create mode 100644 agents/rocko/work/queue-114/r1/out/red-offline.txt create mode 100644 agents/rocko/work/queue-114/r1/out/red-service.txt create mode 100644 agents/rocko/work/queue-114/r1/out/suite-counts.json create mode 100644 agents/rocko/work/queue-114/r1/out/test-discord-first.txt create mode 100644 agents/rocko/work/queue-114/r1/packet-manifest.sha256 create mode 100644 agents/rocko/work/queue-114/r1/process-sweep.py create mode 100755 agents/rocko/work/queue-114/r1/verify.sh diff --git a/agents/rocko/work/queue-114/r1/BUILD.md b/agents/rocko/work/queue-114/r1/BUILD.md new file mode 100644 index 000000000..1adff7e5d --- /dev/null +++ b/agents/rocko/work/queue-114/r1/BUILD.md @@ -0,0 +1,116 @@ +# Row 114 — Discord connector unit on a pinned copy (#1608) + +Rocko, GPT-6.1-Sol. Reviewer Filbert. Base 72c9ac36c, after row108's +landing (base.txt). Detached /mnt/storage/src/mosaic-stack-rocko-114. +Started rev1185; Sage assigned sage-0228 and granted slot sage-0229. +No candidate code commit, push or live Discord action. + +## Implementation and choices + +Service render/install --copy selects a full 40-character lowercase id +under the shared XDG_DATA_HOME/mosaic-stack/copies location or --copies. +A missing CLI or pi refuses exit1 before unit-directory/temp creation. +Explicit empty id is distinct from an omitted flag and also refuses. +Copy directory/node paths use the same plain path alphabet as the other +service scripts. Without --copy, renderer produces the original checkout +bytes; install names the checkout and recommends --copy. + +The template is deliberately untouched. Rendering first substitutes the +same original README/PATH/checkout placeholders, then changes only +WorkingDirectory and ExecStart when --copy is given. ExecStart calls Node +on the copy's CLI directly, --supervised --repo copy. Copies have neither +the discord.sh wrapper nor the systemd template, and require neither at +runtime. Every other rendered line, including docs, restart/brake/stop, +PATH and NoNewPrivileges, remains byte-identical. Test compares all such +lines; out/checkout-render-before/after.txt also compare exactly. + +Status reads actual WorkingDirectory from the user manager, prints its tree +and copy id or checkout path, including effective drop-ins. It does not +infer the tree from an install flag. Tests use a stub manager and isolated +HOME/config paths; no real unit/binding/token is read by this build. + +CLI accepts --offline only for check. It executes the original prepare, +readToken and local reporting paths, returns before constructing REST and +gateway, and ends with an explicit no-network line. The existing local +checks include binding, context against --repo, tool roots, pi/token file +and journal/STOP reporting. It retains the normal check's diagnostic STOP +behavior: reports presence, does not clear STOP/create a journal/claim a +run or launch pi. Online check and the run body are unchanged. Run with +--offline refuses usage before reading config. + +## Evidence and correction + +New focused tests initially refused the unrecognized flags/missing status. +After implementation, the positive offline test's overly plain synthetic +token failed the existing token-format check. Changed only fixture content +to the existing helper's non-live dummy value; no validation weakening. +Five focused tests pass (out/green-final.txt). The offline fixture traps +fetch/WebSocket, marks attempted network calls, and proves offline passes +without attempts while normal check still reaches REST and is trapped. +Bad0644 token mode, missing context under selected repo and run flag misuse +are pinned. Copy tests pin identical legacy bytes, unchanged other lines, +empty/short/missing id, missing CLI/pi without any unit, and effective cwd. +Shell cases also cover temporary --dir --no-reload installs, all required +refusals, status and wrapper offline/run misuse. + +The three prescribed mutants run independently in own process groups; +timeouts kill the whole group, and source restores in finally. They +reintroduce checkout ExecStart, remove pi existence refusal and make offline +call getMe. Final gate/count/mutation and process/network receipts follow. +DOCKER_HOST=unix:///nonexistent.sock; Docker-dependent cases explicitly skip. + +## Protected live plan — unexecuted + +This patch touches packages/discord; Sage must notify Mos before and after +landing, and every intervening Discord landing stays flagged while the +live connector runs the checkout. Live switching waits for the SetSpark +freeze to lift and Mos's separate window. Sage prepares a pushed copy; +Mos's operator runs Node on that copy's cli.mjs check binding --repo copy +--offline (the copy has no discord.sh), preserves the prior unit, installs +--copy and reloads/restarts only on Mos's go. Binding context.files resolve +inside the copy, so uncopied files refuse. Rollback restores the saved unit, +daemon-reloads/restarts on Mos's go and keeps both copies. No live check, +REST call, unit install/enable/reload/restart or private binding/token access +performed; fixtures only. stack-copy.sh/check/COPY_PATHS remain untouched; +connector pin is independent. Decision137 doc-only review fixes ship in a +separate packet after landing. + +## Final gate + +| Suite | Passed | Failure / coverage | +| --- | ---: | --- | +| Discord node | 183 | 0 failed, skipped or cancelled | +| test-auth.sh | 15 | 0 | +| test-conductor.sh | 17 | 0 | +| test-config.sh | 24 | 0 | +| test-discord.sh | 78 | 0; includes Discord183 | +| test-extension-package.sh | 18 | 0 | +| test-foundation.sh | 44 | 0; includes foundation node80 | +| test-land-work.sh | 84 | 0 | +| test-queue.sh | 28 | 0; includes queue node156; canonical-root verify/render skipped | +| test-release.sh | 4 | 0; Docker state machine skipped | +| test-task.sh | 26 | 0; four Docker blocks skipped | + +Gate ran20:30:20-20:31:48 UTC, all11 steps exit0. Dead Docker socket for +all commands; no Docker/provider coverage claimed. Task skips adapter/ +mission/retry/skills/roles/seat/policy/user injection, workspace/capability, +live task/fork and live user recall blocks. No observed recurrence of the +reported gate faults. Source hashes and diff/patch checks pass after mutants. + +| Mutant | Exit | Result | +| --- | ---: | --- | +| checkout-execstart | 1 | killed | +| missing-pi-accepted | 1 | killed | +| offline-calls-getMe | 1 | killed | + +3/3 prescribed mutants killed, no timeout. All runners exited; process +sweep exit0 busy[]. Docker inspect explicitly reported the named network +mosaic-stack-rocko-114_default not found. No removal needed. Slot returned +20:32:57 UTC; no subsequent tests. Final manifest7/7 verified: +68c60a79914692f3f6d4923f7bcff41de109ccca33bf6fba687fb88efa24bcac. + +Claimant in-review move rev1186, round1; expected missing-token request +failure rev1187, command exit1 (out/queue-in-review.txt). Sage requests +as jarvis, Filbert reviews. No protected live step executed. + +Own logs-only commit: 618d71ebbb48d2a36512f84ca1c29624289a4423. No candidate source commit. diff --git a/agents/rocko/work/queue-114/r1/base.txt b/agents/rocko/work/queue-114/r1/base.txt new file mode 100644 index 000000000..8bbf03a65 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/base.txt @@ -0,0 +1 @@ +72c9ac36c33ebb43bf0585bc3ae797969f5ae112 diff --git a/agents/rocko/work/queue-114/r1/build.patch b/agents/rocko/work/queue-114/r1/build.patch new file mode 100644 index 000000000..d76d4ea3b --- /dev/null +++ b/agents/rocko/work/queue-114/r1/build.patch @@ -0,0 +1,392 @@ +diff --git a/docs/TOOLS.md b/docs/TOOLS.md +index 20be532e9..fc38cefab 100644 +--- a/docs/TOOLS.md ++++ b/docs/TOOLS.md +@@ -469,7 +469,19 @@ user entry may carry `channels`, an allowlist of listed channel ids. + `scripts/discord-service.sh install` renders and writes the systemd user + unit `mosaic-discord@.service` (one instance per binding, restart on + failure, exit 3 never retried, SIGTERM on `systemctl --user stop`, SIGHUP on +-`systemctl --user reload`). An optional `tools` key in the binding declares ++`systemctl --user reload`). With ++`install --copy ID [--copies DIR]`, a full id selects an existing shared ++copy holding the Discord CLI and pi; ExecStart runs Node on that CLI with ++--repo and WorkingDirectory in the copy. Without --copy the checkout unit ++is unchanged. Status names its effective cwd/copy id, including drop-ins. ++`check --offline` validates local binding/context/tool roots/pi/token mode ++and reports journal/STOP without REST or gateway calls; run refuses this ++flag. For a Mos-approved re-pin after the SetSpark freeze: make the copy, ++run `node /packages/discord/src/cli.mjs check --repo --offline`, ++save the installed unit, install --copy, then restart on Mos's go. Context ++files resolve inside the copy and missing files refuse. Rollback restores ++the saved unit and daemon-reloads/restarts on Mos's go; keep both copies. ++The connector's pin is independent of stack-copy.sh check. An optional `tools` key in the binding declares + file roots; pi then runs with its own tools off and the package's + extension providing `list_dir`, `read_file` and `search` confined to those + roots, plus `write_file` and `edit_file` for roots marked `"write": true` +diff --git a/packages/discord/README.md b/packages/discord/README.md +index 8f235b556..29b9fc7cc 100644 +--- a/packages/discord/README.md ++++ b/packages/discord/README.md +@@ -17,7 +17,7 @@ CHAT-03 conversation controller exists. + ## Commands + + ``` +-scripts/discord.sh check ++scripts/discord.sh check [--offline] + scripts/discord.sh run [--supervised] + scripts/discord.sh stop + scripts/discord.sh unlock +@@ -34,6 +34,9 @@ scripts/discord-service.sh render | install | uninstall | status + every listed channel over REST; opens one gateway connection, waits for + READY, closes it. Nothing is sent to a channel. Close code 4014 is reported + as the message-content intent not being granted in the developer portal. ++ `check --offline` stops after local binding/context/tool roots/pi/token-mode ++ validation and journal/STOP reporting. It makes no REST or gateway call ++ and says so in its last line. `run --offline` is a usage error. + - `run` refuses when `STOP` exists or an unresolved delivery cannot be + reconciled. Otherwise it starts pi, connects, and serves turns until + SIGTERM, SIGINT or `stop`. Run it under the service unit below, or by hand +@@ -121,6 +124,25 @@ at runtime, as before. Surviving logout and reboot needs + `uninstall` refuses while an instance is active. The log goes to journald: + `run` writes no message text to stderr, only ids, counts and state. + ++Pinned install: `scripts/discord-service.sh install --copy ID [--copies DIR]` ++uses a full 40-character copy id under the shared mosaic-stack/copies ++location. It requires the copy's Discord CLI and node_modules/.bin/pi, ++runs Node directly on that CLI with --repo and WorkingDirectory set to ++the copy, and retains the unit's restart, brake and stop behavior. Without ++--copy the unit still runs the checkout; install explicitly recommends ++pinning. Status reads effective WorkingDirectory, including drop-ins, and ++prints the tree and copy id or checkout path. ++ ++Every live step requires Mos's go after the SetSpark freeze lifts. Re-pin: ++make the new pushed copy with stack-copy.sh; run ++`node /packages/discord/src/cli.mjs check --repo --offline`; ++preserve the old installed unit file; install --copy ID; reload/restart on ++Mos's go. The copy has no scripts/discord.sh, so use its CLI directly. ++Binding context.files resolve against the copy: a file not copied refuses ++at start/check. Rollback restores the saved unit file, daemon-reloads and ++restarts only on Mos's go; retain both copies. This connector pin is ++independent of the bus/Console/CLI pin and stack-copy.sh check. ++ + ## The binding + + Deployment policy for one seat on one server. It carries Discord ids of real +diff --git a/packages/discord/src/cli.mjs b/packages/discord/src/cli.mjs +index 045f4918e..ca8c8bdde 100755 +--- a/packages/discord/src/cli.mjs ++++ b/packages/discord/src/cli.mjs +@@ -1,6 +1,6 @@ + #!/usr/bin/env node + // Usage: +-// mosaic-discord check [--config PATH] [--repo PATH] ++// mosaic-discord check [--config PATH] [--repo PATH] [--offline] + // mosaic-discord run [--config PATH] [--repo PATH] [--supervised] + // mosaic-discord stop [--config PATH] + // mosaic-discord unlock [--config PATH] +@@ -61,7 +61,7 @@ import { createConnector } from "./connector.mjs"; + import { ensureJournal, requestStop, stopRequested, readPid, stopTarget, writePid, clearPid, unlock, recover, appendReload, BRAKE_EXIT } from "./journal.mjs"; + + const USAGE = [ +- "usage: mosaic-discord check [--config PATH] [--repo PATH]", ++ "usage: mosaic-discord check [--config PATH] [--repo PATH] [--offline]", + " mosaic-discord run [--config PATH] [--repo PATH] [--supervised]", + " mosaic-discord stop [--config PATH]", + " mosaic-discord unlock [--config PATH]", +@@ -70,7 +70,7 @@ const USAGE = [ + ].join("\n"); + + function parse(argv) { +- const opts = { command: null, binding: null, config: defaultConfigPath(), repo: process.cwd(), supervised: false }; ++ const opts = { command: null, binding: null, config: defaultConfigPath(), repo: process.cwd(), supervised: false, offline: false }; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === "--config" || a === "--repo") { +@@ -80,6 +80,8 @@ function parse(argv) { + opts.command = "help"; + } else if (a === "--supervised") { + opts.supervised = true; ++ } else if (a === "--offline") { ++ opts.offline = true; + } else if (a.startsWith("--")) throw new DiscordError(`unknown argument: ${a}\n${USAGE}`, 4); + else if (opts.command === null) opts.command = a; + else if (opts.binding === null) opts.binding = a; +@@ -89,6 +91,7 @@ function parse(argv) { + if (!["check", "run", "stop", "unlock", "recover", "reload"].includes(opts.command)) throw new DiscordError(USAGE, 4); + if (opts.binding === null) throw new DiscordError(`${opts.command} needs a binding name\n${USAGE}`, 4); + if (opts.supervised && opts.command !== "run") throw new DiscordError(`--supervised applies to run only\n${USAGE}`, 4); ++ if (opts.offline && opts.command !== "check") throw new DiscordError(`--offline applies to check only\n${USAGE}`, 4); + return opts; + } + +@@ -123,6 +126,11 @@ async function check(opts) { + say(toolRoots ? `tools: ${enabledToolNames(toolRoots).join(",")}; roots ${toolRoots.roots.map((r) => `${r.name}=${r.path}${r.write ? " (writable)" : ""}`).join(" ")}, ${toolRoots.maxCallsPerTurn} calls/message, ${toolRoots.maxFileBytes} bytes/file${toolRoots.web ? `, web via ${toolRoots.web.searxng} (${toolRoots.web.maxFetchBytes} bytes/page)` : ""}${toolRoots.setspark ? `, setspark via ${toolRoots.setspark.baseUrl} as ${toolRoots.setspark.principal}` : ""}` : "tools: none"); + say(`token file mode 0600 ok; STOP ${stopRequested(journalDir) ? "PRESENT" : "absent"}`); + ++ if (opts.offline) { ++ say("offline check passed; no REST or gateway calls were made"); ++ return; ++ } ++ + const rest = createRest({ token, log: warn }); + const me = await rest.getMe(); + if (me.id !== binding.botUserId) throw new DiscordError(`token belongs to bot ${me.id}, binding says ${binding.botUserId}`); +diff --git a/packages/discord/tests/copy-service.test.mjs b/packages/discord/tests/copy-service.test.mjs +new file mode 100644 +index 000000000..c2445701f +--- /dev/null ++++ b/packages/discord/tests/copy-service.test.mjs +@@ -0,0 +1,26 @@ ++import test from 'node:test'; ++import assert from 'node:assert/strict'; ++import {spawnSync} from 'node:child_process'; ++import {readFileSync,writeFileSync,mkdirSync,unlinkSync,chmodSync,existsSync} from 'node:fs'; ++import {join,dirname} from 'node:path'; ++import {fileURLToPath} from 'node:url'; ++import {makeRoot} from './helpers.mjs'; ++const ROOT=fileURLToPath(new URL('../../../',import.meta.url)).replace(/\/$/,''); ++const SCRIPT=join(ROOT,'scripts/discord-service.sh'); ++function setup(){const root=makeRoot(),copies=join(root,'copies'),id='a'.repeat(40),copy=join(copies,id),units=join(root,'units');mkdirSync(join(copy,'packages/discord/src'),{recursive:true});mkdirSync(join(copy,'node_modules/.bin'),{recursive:true});writeFileSync(join(copy,'packages/discord/src/cli.mjs'),'// fixture');writeFileSync(join(copy,'node_modules/.bin/pi'),'#!/bin/sh\nexit 0\n',{mode:0o755});const env={PATH:process.env.PATH,HOME:root,XDG_CONFIG_HOME:join(root,'config')};const run=args=>spawnSync(SCRIPT,args,{env,encoding:'utf8',timeout:5000});return {root,copies,id,copy,units,run,env};} ++test('pinned Discord render/install and missing prerequisites; checkout bytes unchanged',()=>{ ++ const s=setup(),args=['--copy',s.id,'--copies',s.copies],r=s.run(['render',...args]);assert.equal(r.status,0,r.stderr); ++ assert.ok(r.stdout.includes(`WorkingDirectory=${s.copy}\n`));assert.ok(r.stdout.includes(`ExecStart=${process.execPath} ${s.copy}/packages/discord/src/cli.mjs run %i --supervised --repo ${s.copy}\n`)); ++ for(const line of r.stdout.split('\n').filter(l=>/^(ExecStart|WorkingDirectory)=/.test(l)))assert.ok(!line.includes(ROOT),line); ++ const legacy=s.run(['render']);assert.equal(legacy.status,0,legacy.stderr); ++ const nodeDir=dirname(process.execPath),originalPath='/usr/local/bin:/usr/bin:/bin',path=originalPath.split(':').includes(nodeDir)?originalPath:nodeDir+':'+originalPath; ++ const expected=readFileSync(join(ROOT,'packages/discord/systemd/mosaic-discord@.service.in'),'utf8').replaceAll('@REPO@',ROOT).replaceAll('@PATH@',path);assert.equal(legacy.stdout,expected); ++ assert.equal(r.stdout.split('\n').filter(l=>!/^(ExecStart|WorkingDirectory)=/.test(l)).join('\n'),legacy.stdout.split('\n').filter(l=>!/^(ExecStart|WorkingDirectory)=/.test(l)).join('\n')); ++ const installed=s.run(['install',...args,'--dir',s.units,'--no-reload']);assert.equal(installed.status,0,installed.stderr);assert.equal(readFileSync(join(s.units,'mosaic-discord@.service'),'utf8'),r.stdout); ++ for(const id of ['','short','b'.repeat(40)])assert.equal(s.run(['install','--copy',id,'--copies',s.copies,'--dir',join(s.root,'missing'),'--no-reload']).status,1); ++ assert.ok(!existsSync(join(s.root,'missing/mosaic-discord@.service'))); ++ const cli=join(s.copy,'packages/discord/src/cli.mjs');unlinkSync(cli);assert.equal(s.run(['install',...args,'--dir',join(s.root,'missing-cli'),'--no-reload']).status,1);assert.ok(!existsSync(join(s.root,'missing-cli/mosaic-discord@.service')));writeFileSync(cli,'// fixture');unlinkSync(join(s.copy,'node_modules/.bin/pi'));assert.equal(s.run(['install',...args,'--dir',join(s.root,'missing-pi'),'--no-reload']).status,1);assert.ok(!existsSync(join(s.root,'missing-pi/mosaic-discord@.service'))); ++}); ++test('Discord status reports effective WorkingDirectory from a fake user manager',()=>{ ++ const s=setup(),bin=join(s.root,'bin');mkdirSync(bin);const script=join(bin,'systemctl');writeFileSync(script,`#!/bin/sh\ncase "$*" in *show*)echo 'WorkingDirectory=${s.copy}';; *)echo inactive;;esac\n`);chmodSync(script,0o755);s.env.PATH=bin+':'+s.env.PATH;const r=s.run(['status','fixture']);assert.equal(r.status,0,r.stderr);assert.ok(r.stdout.includes(`copy: ${s.id}`));assert.ok(r.stdout.includes(`tree: ${s.copy}`)); ++}); +diff --git a/packages/discord/tests/offline-check.test.mjs b/packages/discord/tests/offline-check.test.mjs +new file mode 100644 +index 000000000..ae069322b +--- /dev/null ++++ b/packages/discord/tests/offline-check.test.mjs +@@ -0,0 +1,26 @@ ++import test from 'node:test'; ++import assert from 'node:assert/strict'; ++import {spawnSync} from 'node:child_process'; ++import {writeFileSync,chmodSync,unlinkSync,existsSync} from 'node:fs'; ++import {join} from 'node:path'; ++import {fileURLToPath} from 'node:url'; ++import {makeRoot,makeRepo,makeDeployment} from './helpers.mjs'; ++const CLI=fileURLToPath(new URL('../src/cli.mjs',import.meta.url)); ++function setup(){ ++ const root=makeRoot(),repo=makeRepo(root),d=makeDeployment(root,{}, {tokenContent:'MTAw.abcdefghijklmnopqrstuvwxyz0123456789'}),calls=join(root,'network-called'),preload=join(root,'no-network.mjs'); ++ writeFileSync(preload,`import {writeFileSync} from 'node:fs';const refuse=()=>{writeFileSync(${JSON.stringify(calls)},'called');throw Error('fixture refuses network')};globalThis.fetch=refuse;globalThis.WebSocket=class{constructor(){refuse()}};`); ++ const run=(command='check',args=[])=>spawnSync(process.execPath,['--import',preload,CLI,command,d.raw.name,'--config',d.config,'--repo',repo,...args],{encoding:'utf8',timeout:5000}); ++ return {root,repo,d,calls,run}; ++} ++test('check --offline validates local fixture without REST or gateway calls',()=>{ ++ const s=setup(),r=s.run('check',['--offline']);assert.equal(r.status,0,r.stderr);assert.match(r.stdout,/token file mode 0600 ok; STOP absent/);assert.match(r.stdout,/offline check passed; no REST or gateway calls were made\n$/);assert.ok(!existsSync(s.calls)); ++ // Online check still reaches REST: the trap fails it immediately. ++ const online=s.run();assert.equal(online.status,1);assert.ok(existsSync(s.calls));assert.match(online.stderr,/fixture refuses network/); ++}); ++test('check --offline refuses token mode and missing context under the selected repo',()=>{ ++ const s=setup();chmodSync(s.d.tokenFile,0o644);const bad=s.run('check',['--offline']);assert.equal(bad.status,2,bad.stderr);assert.match(bad.stderr,/0600/);assert.ok(!existsSync(s.calls)); ++ chmodSync(s.d.tokenFile,0o600);unlinkSync(join(s.repo,'contracts/CONSTITUTION.md'));const context=s.run('check',['--offline']);assert.equal(context.status,2,context.stderr);assert.ok(!existsSync(s.calls)); ++}); ++test('run --offline is a usage refusal before reading config or networking',()=>{ ++ const s=setup();unlinkSync(s.d.config);const r=s.run('run',['--offline']);assert.equal(r.status,4,r.stderr);assert.match(r.stderr,/--offline/);assert.ok(!existsSync(s.calls)); ++}); +diff --git a/scripts/discord-service.sh b/scripts/discord-service.sh +index fd2da1de1..ea726e08e 100755 +--- a/scripts/discord-service.sh ++++ b/scripts/discord-service.sh +@@ -6,8 +6,8 @@ + # instance per binding (mosaic-discord@). Nothing here reads the + # binding or the token. See packages/discord/README.md, "Service unit". + # +-# render print the rendered unit on stdout +-# install [--dir DIR] [--no-reload] ++# render [--copy ID [--copies DIR]] print the rendered unit on stdout ++# install [--copy ID [--copies DIR]] [--dir DIR] [--no-reload] + # write the unit (write to a temp file, then + # rename) and run `systemctl --user daemon-reload` + # uninstall [--dir DIR] [--no-reload] +@@ -19,20 +19,44 @@ set -euo pipefail + REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + TEMPLATE="$REPO/packages/discord/systemd/mosaic-discord@.service.in" + UNIT_NAME="mosaic-discord@.service" +-USAGE="usage: scripts/discord-service.sh render | install [--dir DIR] [--no-reload] | uninstall [--dir DIR] [--no-reload] | status " ++USAGE="usage: scripts/discord-service.sh render [--copy ID [--copies DIR]] | install [--copy ID [--copies DIR]] [--dir DIR] [--no-reload] | uninstall [--dir DIR] [--no-reload] | status " + + die() { echo "discord-service: $*" >&2; exit 1; } + usage() { echo "$USAGE" >&2; exit 4; } + ++COPY_ID="" ++COPY_SET=0 ++COPIES="${XDG_DATA_HOME:-$HOME/.local/share}/mosaic-stack/copies" ++copy_root() { ++ [[ "$COPY_ID" =~ ^[0-9a-f]{40}$ ]] || die '--copy must be a full 40-character commit id' ++ case "$COPIES" in /*) ;; *) die 'copies directory must be absolute' ;; esac ++ case "$COPIES" in *[!A-Za-z0-9/._+-]*) die 'copies directory contains a character the unit cannot carry' ;; esac ++ local root="$COPIES/$COPY_ID" ++ [ -f "$root/packages/discord/src/cli.mjs" ] || die "copy lacks packages/discord/src/cli.mjs: $root" ++ [ -f "$root/node_modules/.bin/pi" ] || die "copy lacks node_modules/.bin/pi: $root" ++ echo "$root" ++} ++ + render() { + [ -f "$TEMPLATE" ] || die "template missing: $TEMPLATE" ++ local root="" ++ [ "$COPY_SET" = 0 ] || root="$(copy_root)" || return 1 + local node_dir + node_dir="$(dirname "$(command -v node || true)")" + [ -n "$node_dir" ] && [ "$node_dir" != "." ] || die "node not found on PATH" + local path="/usr/local/bin:/usr/bin:/bin" + case ":$path:" in *":$node_dir:"*) ;; *) path="$node_dir:$path" ;; esac + case "$REPO" in *@*|*'|'*) die "repository path contains a character the template cannot carry: $REPO" ;; esac +- sed -e "s|@REPO@|$REPO|g" -e "s|@PATH@|$path|g" "$TEMPLATE" ++ local unit ++ unit="$(sed -e "s|@REPO@|$REPO|g" -e "s|@PATH@|$path|g" "$TEMPLATE")" || return 1 ++ if [ -n "$root" ]; then ++ local node ++ node="$(command -v node)" ++ case "$node" in *[!A-Za-z0-9/._+-]*) die 'node path contains a character the unit cannot carry' ;; esac ++ sed -e "s|^WorkingDirectory=.*$|WorkingDirectory=$root|" -e "s|^ExecStart=.*$|ExecStart=$node $root/packages/discord/src/cli.mjs run %i --supervised --repo $root|" <<< "$unit" ++ else ++ printf '%s\n' "$unit" ++ fi + } + + # Parse --dir and --no-reload for install and uninstall. +@@ -41,8 +65,10 @@ RELOAD=1 + parse_flags() { + while [ $# -gt 0 ]; do + case "$1" in +- --dir) [ $# -ge 2 ] || usage; UNIT_DIR="$2"; shift 2 ;; +- --no-reload) RELOAD=0; shift ;; ++ --copy) [ "$cmd" != uninstall ] && [ $# -ge 2 ] || usage; COPY_ID="$2"; COPY_SET=1; shift 2 ;; ++ --copies) [ "$cmd" != uninstall ] && [ $# -ge 2 ] || usage; COPIES="$2"; shift 2 ;; ++ --dir) [ "$cmd" != render ] && [ $# -ge 2 ] || usage; UNIT_DIR="$2"; shift 2 ;; ++ --no-reload) [ "$cmd" != render ] || usage; RELOAD=0; shift ;; + *) usage ;; + esac + done +@@ -50,10 +76,12 @@ parse_flags() { + + install_unit() { + parse_flags "$@" ++ local rendered ++ rendered="$(render)" || exit 1 + mkdir -p "$UNIT_DIR" + local target="$UNIT_DIR/$UNIT_NAME" tmp + tmp="$(mktemp "$UNIT_DIR/.$UNIT_NAME.XXXXXX")" +- render > "$tmp" ++ printf '%s\n' "$rendered" > "$tmp" + chmod 0644 "$tmp" + if [ -f "$target" ] && cmp -s "$tmp" "$target"; then + rm -f "$tmp" +@@ -66,6 +94,11 @@ install_unit() { + systemctl --user daemon-reload || die "daemon-reload failed" + echo "daemon-reload done" + fi ++ if [ -n "$COPY_ID" ]; then ++ echo "copy: $COPY_ID" ++ else ++ echo "checkout: $REPO (use --copy ID to pin the connector)" ++ fi + cat < start now and at login +@@ -106,6 +139,17 @@ status_unit() { + echo " enabled: $(systemctl --user is-enabled "$unit" 2>&1 || true)" + echo " active: $(systemctl --user is-active "$unit" 2>&1 || true)" + systemctl --user show "$unit" -p MainPID -p NRestarts -p ExecMainStartTimestamp -p Result 2>/dev/null | sed 's/^/ /' ++ local working id ++ working="$(systemctl --user show "$unit" -p WorkingDirectory --value 2>/dev/null)" || working="" ++ # Accept property-form output too, for systemctl fixtures and older wrappers. ++ working="${working#WorkingDirectory=}" ++ echo " tree: ${working:-absent (WorkingDirectory unavailable)}" ++ id="${working##*/}" ++ if [[ "$id" =~ ^[0-9a-f]{40}$ ]] && [ -f "$working/packages/discord/src/cli.mjs" ]; then ++ echo " copy: $id" ++ elif [ -n "$working" ]; then ++ echo " checkout: $working" ++ fi + local config="${XDG_CONFIG_HOME:-$HOME/.config}/mosaic-dev/config.json" + local data_root + data_root="$(node -e 'const c=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8")); process.stdout.write(String(c.dataRoot||""))' "$config" 2>/dev/null || true)" +@@ -130,7 +174,7 @@ status_unit() { + [ $# -ge 1 ] || usage + cmd="$1"; shift + case "$cmd" in +- render) [ $# -eq 0 ] || usage; render ;; ++ render) parse_flags "$@"; render ;; + install) install_unit "$@" ;; + uninstall) uninstall_unit "$@" ;; + status) status_unit "$@" ;; +diff --git a/scripts/test-discord.sh b/scripts/test-discord.sh +index 9ec4ddda5..109dfdfa5 100755 +--- a/scripts/test-discord.sh ++++ b/scripts/test-discord.sh +@@ -209,6 +209,62 @@ env -u USER scripts/discord-service.sh install --dir "$SANDBOX/units-nouser" --n + && grep -qF "enable-linger $(id -un)" "$SANDBOX/install.nouser" + check "service install with USER unset finishes and names the account for lingering" $? + ++# --- pinned copy service, fixture paths only --- ++COPY_ID="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ++COPIES="$SANDBOX/copies" ++COPY="$COPIES/$COPY_ID" ++mkdir -p "$COPY/packages/discord/src" "$COPY/node_modules/.bin" ++printf '// fixture\n' > "$COPY/packages/discord/src/cli.mjs" ++printf '#!/bin/sh\nexit 0\n' > "$COPY/node_modules/.bin/pi" ++chmod 755 "$COPY/node_modules/.bin/pi" ++scripts/discord-service.sh render --copy "$COPY_ID" --copies "$COPIES" >"$SANDBOX/unit.copy" 2>&1 \ ++ && grep -qxF "WorkingDirectory=$COPY" "$SANDBOX/unit.copy" \ ++ && grep -qxF "ExecStart=$(command -v node) $COPY/packages/discord/src/cli.mjs run %i --supervised --repo $COPY" "$SANDBOX/unit.copy" \ ++ && ! sed -n '/^WorkingDirectory=/p;/^ExecStart=/p' "$SANDBOX/unit.copy" | grep -qF "$REPO_DIR" ++check "pinned render runs copy CLI with copy cwd/repo and no checkout executable" $? ++scripts/discord-service.sh install --copy "$COPY_ID" --copies "$COPIES" --dir "$SANDBOX/pinned-units" --no-reload >"$SANDBOX/pinned-install" 2>&1 \ ++ && cmp -s "$SANDBOX/pinned-units/mosaic-discord@.service" "$SANDBOX/unit.copy" ++check "pinned install writes the rendered unit in a temporary unit directory" $? ++for kind in short missing cli pi; do ++ id="$COPY_ID" ++ case "$kind" in short) id=short;; missing) id=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;; cli) rm "$COPY/packages/discord/src/cli.mjs";; pi) printf '// fixture\n' > "$COPY/packages/discord/src/cli.mjs";rm "$COPY/node_modules/.bin/pi";; esac ++ scripts/discord-service.sh install --copy "$id" --copies "$COPIES" --dir "$SANDBOX/refused-$kind" --no-reload >"$SANDBOX/refused-$kind.log" 2>&1 ++ rc=$? ++ [ "$rc" -eq 1 ] && [ ! -e "$SANDBOX/refused-$kind/mosaic-discord@.service" ] ++ check "pinned install refuses $kind prerequisite and writes no unit" $? ++done ++printf '#!/bin/sh\nexit 0\n' > "$COPY/node_modules/.bin/pi" ++mkdir -p "$SANDBOX/fake-bin" ++cat >"$SANDBOX/fake-bin/systemctl" <"$SANDBOX/status.copy" 2>&1 \ ++ && grep -qF "copy: $COPY_ID" "$SANDBOX/status.copy" \ ++ && grep -qF "tree: $COPY" "$SANDBOX/status.copy" ++check "status names the copy from fake systemctl effective cwd" $? ++grep -qF "checkout: $REPO_DIR" "$SANDBOX/install.1" && grep -qF -- '--copy' "$SANDBOX/install.1" ++check "checkout install explicitly recommends --copy" $? ++ ++# Offline wrapper entrypoint. Only a synthetic token/binding/config are used. ++node - "$SANDBOX" <<'EOF_OFFLINE' ++const fs=require('fs'),p=require('path'),root=process.argv[2]; ++const data=p.join(root,'offline-data');fs.mkdirSync(p.join(data,'discord'),{recursive:true}); ++const b=JSON.parse(fs.readFileSync('packages/discord/fixtures/binding.example.json','utf8')); ++b.name='offline-fixture';b.tokenFile=p.join(root,'offline-token');b.context.files=['packages/discord/README.md'];delete b.tools; ++fs.writeFileSync(b.tokenFile,'MTAw.abcdefghijklmnopqrstuvwxyz0123456789\n',{mode:0o600}); ++fs.writeFileSync(p.join(data,'discord',b.name+'.json'),JSON.stringify(b),{mode:0o600}); ++fs.writeFileSync(p.join(root,'offline-config'),JSON.stringify({dataRoot:data})); ++fs.writeFileSync(p.join(root,'offline-trap.mjs'),`globalThis.fetch=()=>{throw Error('network forbidden in offline fixture')};globalThis.WebSocket=class{constructor(){throw Error('gateway forbidden in offline fixture')}};`); ++EOF_OFFLINE ++NODE_OPTIONS="--import=$SANDBOX/offline-trap.mjs" scripts/discord.sh check offline-fixture --config "$SANDBOX/offline-config" --offline >"$SANDBOX/offline.out" 2>&1 \ ++ && grep -qF 'offline check passed; no REST or gateway calls were made' "$SANDBOX/offline.out" ++check "wrapper check --offline passes local fixture and makes no network call" $? ++NODE_OPTIONS="--import=$SANDBOX/offline-trap.mjs" scripts/discord.sh run offline-fixture --config "$SANDBOX/offline-config" --offline >"$SANDBOX/offline-run.out" 2>&1 ++[ $? -eq 4 ] ++check "wrapper run --offline refuses usage" $? ++ + echo + echo "discord suite: $PASS passed, $FAIL failed" + [ "$FAIL" -eq 0 ] diff --git a/agents/rocko/work/queue-114/r1/candidate-manifest.sha256 b/agents/rocko/work/queue-114/r1/candidate-manifest.sha256 new file mode 100644 index 000000000..875beac1e --- /dev/null +++ b/agents/rocko/work/queue-114/r1/candidate-manifest.sha256 @@ -0,0 +1,7 @@ +1cd5abf22a24b985e262a7d0baed7c5bf66e7a3cbafb47c06dd51eace4afe9f6 docs/TOOLS.md +5949914eb943139d18cac183755319e96830ea92be3b33f3bd056536467655d2 packages/discord/README.md +8f18ee5bb7e0c2a049670caf20438cc35c44bcd5333943e9084f0abb6c9e2234 packages/discord/src/cli.mjs +75a84d470cc5cb77f0a9252f8828dfbe29645958f423884846a0ac39d9e51ced packages/discord/tests/copy-service.test.mjs +c56f4f93e66bc979f0e95e52c2ab2a09b149191071de09b8d739b0a0592df8fe packages/discord/tests/offline-check.test.mjs +bc290fcf852930f398b44689f0731d00412c475781b3eae51c0a01beaf5d1102 scripts/discord-service.sh +f5b42da59265a3195fa5c87053dbc3dcdcec9ecc9d5468cbadeb683346e62e34 scripts/test-discord.sh diff --git a/agents/rocko/work/queue-114/r1/files.txt b/agents/rocko/work/queue-114/r1/files.txt new file mode 100644 index 000000000..ec7faefaf --- /dev/null +++ b/agents/rocko/work/queue-114/r1/files.txt @@ -0,0 +1,7 @@ +docs/TOOLS.md +packages/discord/README.md +packages/discord/src/cli.mjs +packages/discord/tests/copy-service.test.mjs +packages/discord/tests/offline-check.test.mjs +scripts/discord-service.sh +scripts/test-discord.sh diff --git a/agents/rocko/work/queue-114/r1/gate.py b/agents/rocko/work/queue-114/r1/gate.py new file mode 100644 index 000000000..4e6a971d2 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/gate.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +"""Run shell suites from a detached worktree, capture every exit.""" +import pathlib, subprocess, json, datetime, sys, os +root=pathlib.Path.cwd() +if root == pathlib.Path('/mnt/storage/src/mosaic-stack'): + raise SystemExit('gate refuses canonical checkout') +if subprocess.check_output(['git','branch','--show-current'],text=True).strip(): + raise SystemExit('gate requires detached HEAD') +if os.environ.get('DOCKER_HOST') != 'unix:///nonexistent.sock': + raise SystemExit('decision 127 requires DOCKER_HOST=unix:///nonexistent.sock') +out=pathlib.Path(sys.argv[1]); out.mkdir(parents=True,exist_ok=True) +results=[] +commands=[] +for package in [root/'packages/discord']: + tests=sorted(package.glob('tests/**/*.test.mjs')) + if tests: commands.append(('node-'+package.name,['node','--test',*[str(t.relative_to(root)) for t in tests]],600)) +for suite in sorted(root.glob('scripts/test-*.sh')): + commands.append((suite.stem,['bash',str(suite)],600)) +for name,command,timeout in commands: + began=datetime.datetime.now(datetime.timezone.utc).isoformat() + with (out/(name+'.txt')).open('w') as log: + p=subprocess.run(command,cwd=root,stdout=log,stderr=subprocess.STDOUT,timeout=timeout) + row={'suite':name,'exit':p.returncode,'began':began,'ended':datetime.datetime.now(datetime.timezone.utc).isoformat()} + results.append(row) + (out/'gate-results.json').write_text(json.dumps(results,indent=2)+'\n') + print(json.dumps(row),flush=True) +sys.exit(any(r['exit'] for r in results)) diff --git a/agents/rocko/work/queue-114/r1/mutants.py b/agents/rocko/work/queue-114/r1/mutants.py new file mode 100644 index 000000000..5c5041889 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/mutants.py @@ -0,0 +1,22 @@ +import pathlib,subprocess,sys,json,os,signal +root=pathlib.Path.cwd();out=pathlib.Path(sys.argv[1]);out.mkdir(parents=True,exist_ok=True) +assert root != pathlib.Path('/mnt/storage/src/mosaic-stack') +assert os.environ.get('DOCKER_HOST')=='unix:///nonexistent.sock' +muts=[ + ('checkout-execstart','scripts/discord-service.sh','ExecStart=$node $root/packages/discord/src/cli.mjs run %i --supervised --repo $root','ExecStart=$REPO/scripts/discord.sh run %i --supervised','pinned Discord'), + ('missing-pi-accepted','scripts/discord-service.sh','[ -f "$root/node_modules/.bin/pi" ] || die',': || die','pinned Discord'), + ('offline-calls-getMe','packages/discord/src/cli.mjs','if (opts.offline) {','if (false) {','check --offline validates'), +] +results=[] +for name,file,old,new,pattern in muts: + p=root/file;original=p.read_text();assert original.count(old)==1,(name,original.count(old)) + try: + p.write_text(original.replace(old,new,1)) + with (out/(name+'.txt')).open('w') as log: + child=subprocess.Popen(['node','--test','--test-name-pattern='+pattern,'packages/discord/tests/copy-service.test.mjs' if name!='offline-calls-getMe' else 'packages/discord/tests/offline-check.test.mjs'],stdout=log,stderr=subprocess.STDOUT,start_new_session=True) + try:code=child.wait(timeout=60);status='killed' if code else 'survived' + except subprocess.TimeoutExpired:os.killpg(child.pid,signal.SIGKILL);child.wait();code=124;status='timeout' + row={'name':name,'exit':code,'status':status};results.append(row);print(json.dumps(row),flush=True) + (out/'summary.json').write_text(json.dumps(results,indent=2)+'\n') + finally:p.write_text(original) +sys.exit(any(r['status']!='killed' for r in results)) diff --git a/agents/rocko/work/queue-114/r1/out/checkout-render-after.txt b/agents/rocko/work/queue-114/r1/out/checkout-render-after.txt new file mode 100644 index 000000000..d772ebc3c --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/checkout-render-after.txt @@ -0,0 +1,39 @@ +# Mosaic Discord connector, one instance per binding: mosaic-discord@. +# Rendered by scripts/discord-service.sh from packages/discord/systemd/; +# /mnt/storage/src/mosaic-stack-rocko-114 and /usr/local/bin:/usr/bin:/bin are filled in at install time. Edit the template and +# reinstall; do not edit the installed copy. +[Unit] +Description=Mosaic Discord connector (%i) +Documentation=file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/README.md +After=network-online.target +Wants=network-online.target +StartLimitIntervalSec=600 +StartLimitBurst=5 + +[Service] +Type=simple +WorkingDirectory=/mnt/storage/src/mosaic-stack-rocko-114 +Environment=PATH=/usr/local/bin:/usr/bin:/bin +# A supervised run first clears a lock left by a crash or a reboot, and +# refuses with exit 3 while STOP is present or the binding is held. Exit 3 +# is never retried: the brake belongs to the operator. This happens inside +# the main process on purpose: systemd honours RestartPreventExitStatus only +# for the main process, so a refusing ExecStartPre would loop. +ExecStart=/mnt/storage/src/mosaic-stack-rocko-114/scripts/discord.sh run %i --supervised +# `systemctl --user reload` re-reads the binding in place (channels, users, +# limits); the connector refuses and keeps the old binding when the file is +# invalid or a fixed key changed. See reloads.jsonl under the journal. +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +RestartSec=15 +RestartPreventExitStatus=3 +# `systemctl --user stop` sends SIGTERM; the connector finishes the turn in +# flight, then exits 0. The stop timeout covers the largest turn timeout a +# binding may set (3600 s) plus margin; a normal stop takes seconds. +KillSignal=SIGTERM +KillMode=mixed +TimeoutStopSec=3700 +NoNewPrivileges=yes + +[Install] +WantedBy=default.target diff --git a/agents/rocko/work/queue-114/r1/out/checkout-render-before.txt b/agents/rocko/work/queue-114/r1/out/checkout-render-before.txt new file mode 100644 index 000000000..d772ebc3c --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/checkout-render-before.txt @@ -0,0 +1,39 @@ +# Mosaic Discord connector, one instance per binding: mosaic-discord@. +# Rendered by scripts/discord-service.sh from packages/discord/systemd/; +# /mnt/storage/src/mosaic-stack-rocko-114 and /usr/local/bin:/usr/bin:/bin are filled in at install time. Edit the template and +# reinstall; do not edit the installed copy. +[Unit] +Description=Mosaic Discord connector (%i) +Documentation=file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/README.md +After=network-online.target +Wants=network-online.target +StartLimitIntervalSec=600 +StartLimitBurst=5 + +[Service] +Type=simple +WorkingDirectory=/mnt/storage/src/mosaic-stack-rocko-114 +Environment=PATH=/usr/local/bin:/usr/bin:/bin +# A supervised run first clears a lock left by a crash or a reboot, and +# refuses with exit 3 while STOP is present or the binding is held. Exit 3 +# is never retried: the brake belongs to the operator. This happens inside +# the main process on purpose: systemd honours RestartPreventExitStatus only +# for the main process, so a refusing ExecStartPre would loop. +ExecStart=/mnt/storage/src/mosaic-stack-rocko-114/scripts/discord.sh run %i --supervised +# `systemctl --user reload` re-reads the binding in place (channels, users, +# limits); the connector refuses and keeps the old binding when the file is +# invalid or a fixed key changed. See reloads.jsonl under the journal. +ExecReload=/bin/kill -HUP $MAINPID +Restart=on-failure +RestartSec=15 +RestartPreventExitStatus=3 +# `systemctl --user stop` sends SIGTERM; the connector finishes the turn in +# flight, then exits 0. The stop timeout covers the largest turn timeout a +# binding may set (3600 s) plus margin; a normal stop takes seconds. +KillSignal=SIGTERM +KillMode=mixed +TimeoutStopSec=3700 +NoNewPrivileges=yes + +[Install] +WantedBy=default.target diff --git a/agents/rocko/work/queue-114/r1/out/final-verification.txt b/agents/rocko/work/queue-114/r1/out/final-verification.txt new file mode 100644 index 000000000..7d4ea78ec --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/final-verification.txt @@ -0,0 +1 @@ +7/7 hashes match; patch equals final detached diff; detached base matches; checkout before/after renders match; canonical patch applies and diff clean; own logs-only commit 618d71ebbb48d2a36512f84ca1c29624289a4423; protected live actions unexecuted. diff --git a/agents/rocko/work/queue-114/r1/out/full/gate-results.json b/agents/rocko/work/queue-114/r1/out/full/gate-results.json new file mode 100644 index 000000000..8fcbef6f5 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/gate-results.json @@ -0,0 +1,68 @@ +[ + { + "suite": "node-discord", + "exit": 0, + "began": "2026-10-14T20:30:20.823230+00:00", + "ended": "2026-10-14T20:30:23.493776+00:00" + }, + { + "suite": "test-auth", + "exit": 0, + "began": "2026-10-14T20:30:23.494015+00:00", + "ended": "2026-10-14T20:30:24.109265+00:00" + }, + { + "suite": "test-conductor", + "exit": 0, + "began": "2026-10-14T20:30:24.109530+00:00", + "ended": "2026-10-14T20:30:30.287430+00:00" + }, + { + "suite": "test-config", + "exit": 0, + "began": "2026-10-14T20:30:30.287694+00:00", + "ended": "2026-10-14T20:30:31.955466+00:00" + }, + { + "suite": "test-discord", + "exit": 0, + "began": "2026-10-14T20:30:31.955716+00:00", + "ended": "2026-10-14T20:30:38.736178+00:00" + }, + { + "suite": "test-extension-package", + "exit": 0, + "began": "2026-10-14T20:30:38.736435+00:00", + "ended": "2026-10-14T20:30:40.052900+00:00" + }, + { + "suite": "test-foundation", + "exit": 0, + "began": "2026-10-14T20:30:40.053145+00:00", + "ended": "2026-10-14T20:31:17.005136+00:00" + }, + { + "suite": "test-land-work", + "exit": 0, + "began": "2026-10-14T20:31:17.005438+00:00", + "ended": "2026-10-14T20:31:25.637399+00:00" + }, + { + "suite": "test-queue", + "exit": 0, + "began": "2026-10-14T20:31:25.637691+00:00", + "ended": "2026-10-14T20:31:45.992880+00:00" + }, + { + "suite": "test-release", + "exit": 0, + "began": "2026-10-14T20:31:45.993134+00:00", + "ended": "2026-10-14T20:31:46.157295+00:00" + }, + { + "suite": "test-task", + "exit": 0, + "began": "2026-10-14T20:31:46.157584+00:00", + "ended": "2026-10-14T20:31:48.126073+00:00" + } +] diff --git a/agents/rocko/work/queue-114/r1/out/full/node-discord.txt b/agents/rocko/work/queue-114/r1/out/full/node-discord.txt new file mode 100644 index 000000000..77a36a4be --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/node-discord.txt @@ -0,0 +1,191 @@ +✔ approvals: a request is validated before anything is posted; the rendering shows names and never ids (7.7375ms) +✔ approvals: the ledger is appended and folded into open requests with bind and approval states (1.728755ms) +✔ approvals: a reply approves only when it points at a request, says exactly approve, and comes from a listed approver once (0.660941ms) +✔ approvals: a button approves only on its own request message with the matching custom id (0.480185ms) +✔ approvals flow: a turn that opened a request posts the message with the button, records it, binds it, and both approvers approve (17.296632ms) +✔ approvals flow: a non-approver, a repeat, a wrong custom id and a service refusal each get their fixed line and a drop entry (6.588519ms) +✔ approvals flow: an invalid request from the model, a refused post, and no api client are recorded and post nothing (7.386651ms) +✔ approvals flow: start retries a bind and an approval left as unknown, under their original keys (2.280338ms) +✔ authorize: open channel, listed user (1.82861ms) +✔ authorize: wrong guild (0.184147ms) +✔ authorize: no guild (DM) (0.172822ms) +✔ authorize: unlisted channel (0.174402ms) +✔ authorize: unknown channel, no info (0.177221ms) +✔ authorize: thread of listed parent (0.21491ms) +✔ authorize: thread of unlisted parent (0.154106ms) +✔ authorize: text channel that is not a thread and not listed (0.137261ms) +✔ authorize: unlisted user (0.987234ms) +✔ authorize: no author (0.258428ms) +✔ authorize: bot author (listed id, bot flag) (0.130292ms) +✔ authorize: system author (0.116261ms) +✔ authorize: the bot itself (0.09737ms) +✔ authorize: webhook (0.098117ms) +✔ authorize: mention channel without mention (0.168159ms) +✔ authorize: mention channel with bot mention (0.157334ms) +✔ authorize: mention channel with @everyone only (0.126031ms) +✔ authorize: mention channel mentioning someone else (0.079199ms) +✔ authorize: mention channel, content says @bot but mentions empty (0.211148ms) +✔ authorize: private thread under mention channel, mentioned (0.096633ms) +✔ authorize: private thread under mention channel, not mentioned (0.075681ms) +✔ authorize: thread in another guild per channel info (0.096333ms) +✔ authorize: not an object (0.069499ms) +✔ authorize: no id (0.101974ms) +✔ authorize: oversize content is accepted and flagged (0.072529ms) +✔ authorize: exactly the limit is not oversize (0.062169ms) +✔ authorize: a user's channel allowlist drops them outside it, threads count as the parent, others are unaffected (0.572655ms) +✔ authorize: order puts wrong guild before user, and user before channel (no channel lookup for strangers) (0.220375ms) +✔ binding: a complete binding validates and is frozen (2.592724ms) +✔ binding: unknown key, missing field, wrong type refuse with exit 2 (1.277499ms) +✔ binding: empty allowlists refuse (0.484324ms) +✔ binding: a user's channel allowlist must be non-empty, listed and unique; absent means every listed channel (1.35884ms) +✔ reloadDiff: reloadable keys are summarised by id; every fixed key refuses with exit 2 (1.544901ms) +✔ binding: dmRecipient is optional, a snowflake, one of the listed users, and a fixed key (2.632685ms) +✔ binding: file must be 0600, regular, not a symlink (1.696578ms) +✔ binding: token file mode, symlink, emptiness and shape are checked; token never appears in errors (1.650015ms) +✔ cli: check refuses a non-0600 token file with exit 2 before any network use (110.716888ms) +✔ context files: absolute paths, traversal, symlinks and out-of-repo targets refuse; in-repo files resolve (2.727265ms) +✔ cli: check refuses a missing context file and a missing binding with exit 2; usage is exit 4 (311.22442ms) +✔ cli: reload validates the file first (exit 2), then needs a live owner (exit 1); usage is exit 4 (188.64441ms) +✔ cli: run refuses when STOP is present, before any network use (127.115842ms) +✔ binding: tools is optional, validated strictly, a fixed key for reload, and its roots are resolved against the data root (2.407766ms) +✔ binding: a git key is validated at load and reaches the extension whole, and only on a writable root (1.414096ms) +✔ delivery: an accepted message is in the inbox before the turn, the reply is chunked with one nonce per chunk, and the turn record is write-once (20.411015ms) +✔ delivery: refused and unknown outcomes are journaled; a later chunk is not sent after a failure (16.46198ms) +✔ delivery: restart with an unknown entry re-sends the same nonce once and reconciles before accepting traffic (1.651165ms) +✔ delivery: an unknown entry older than the dedupe window is marked refused, not re-sent; a still-unknown one refuses start (1.257068ms) +✔ delivery: repeated unknown reconciliations never refresh the dedupe window; the original intent time decides (1.394563ms) +✔ turn: a failed engine turn posts the fixed line, never model output, and writes a failed record (3.649376ms) +✔ turn: a second message during a turn is held by the engine, both get their own reply and record (33.223894ms) +✔ turn: a thread under a listed channel is answered in the thread; an unknown thread is looked up once (3.349565ms) +✔ drop: an unlisted user gets silence and one drop line; no inbox entry, no REST call, no engine call (1.081032ms) +✔ drop: an oversize message is accepted into the inbox, answered with the fixed line and journaled as a drop (1.035414ms) +✔ restart: an inbox with three ids and a replay of the same three produces zero turns (42.067365ms) +✔ stop: STOP present refuses start; STOP written while running refuses new turns and the current one finishes (32.137564ms) +✔ ceiling: the ceiling plus one is refused and journaled; one fixed line per UTC day; a new day accepts again (6.021324ms) +✔ ceiling: a burst arriving while turns are still running cannot queue past the ceiling (4.161459ms) +✔ ceiling: a turn interrupted by a crash still counts after restart; admissions are durable (2.513163ms) +✔ ceiling: the daily notice survives a same-day restart; one delivery attempt in total, even when the first attempt crashed mid-flight (4.309453ms) +✔ duplicate: the same event delivered twice while the thread lookup is held yields one prompt, one admission and one reply (2.219847ms) +✔ journal: no token-shaped string and no model output on the drop path reaches disk (0.495667ms) +✔ receipt: an admitted message gets one eyes reaction on the inbound message; drops and refusals get none; a failed reaction is recorded and does not fail the turn (2.66673ms) +✔ receipt: Discord refusing the reaction leaves the turn intact and records ok false (2.170439ms) +✔ reload: a new user is silent before and answered after; a removed channel goes silent; a lower ceiling applies at once (3.946203ms) +✔ reload: a fixed key refuses with exit 2 and the old binding stays in force (1.991666ms) +✔ tools: with a tools binding the turn record lists every read and its outcome; without one the field is null (2.529012ms) +✔ context: the Discord block names the server, channels and modes, and states the rules from Q15 and Q16 (2.626272ms) +✔ context: with tools the block names the roots, keeps file content as data, and says to state refusals plainly (0.755232ms) +✔ context: a writable root adds the write rules and says a write is real only once Jason commits (1.828371ms) +✔ context: the envelope is one bracketed line then the text; names cannot break the line (1.09758ms) +✔ context: a git root swaps the terminal-commit line for the git verbs, and a vault root adds the id protocol (2.720755ms) +✔ context: assembleContext concatenates files in launcher format and appends the block; sha256 is stable (1.18ms) +✔ context: splitReply keeps paragraphs together under the limit and splits long ones at lines, spaces, then hard (0.640898ms) +✔ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (90.714262ms) +✔ Discord status reports effective WorkingDirectory from a fake user manager (49.6019ms) +✔ engine: buildPiArgs carries the fixed flags, engine settings, session dir and prompt file (3.009851ms) +✔ engine: with tools, buildPiArgs turns pi's own tools off, loads the extension explicitly and allowlists exactly our three (0.442298ms) +✔ engine: a run with tool turns settles once, on the answer, with every tool call in the result (61.214272ms) +✔ engine: a run that ends on a tool-only turn fails the prompt as empty; a retried run settles on the real end (41.922629ms) +✔ engine: one prompt, one turn, text and usage come back (42.573884ms) +✔ engine: a prompt while streaming is held until pi settles, then sent as its own run, and answered in order (343.382019ms) +✔ engine: a held prompt that times out before pi settles fails on its own and is never sent (230.35888ms) +✔ engine: timeout sends abort and fails only that turn; the process stays (103.261162ms) +✔ engine: tool events from a run that outlived its timeout never land in the next prompt's record (231.288342ms) +✔ engine: a prompt after a turn that timed out before its agent_start waits for pi to settle instead of being refused (126.827973ms) +✔ engine: when pi has not started a timed-out turn by the end of the abort grace, the engine stops pi and fails held prompts (212.661556ms) +✔ engine: a timed-out turn pi starts only after the grace never answers a later prompt (615.487598ms) +✔ engine: late events of a run past its grace, before pi exits, answer nothing and nothing more is sent (early prompt response) (1.370293ms) +✔ engine: late events of a run past its grace, before pi exits, answer nothing and nothing more is sent (late prompt response) (0.537854ms) +✔ engine: a timed-out run pi did start outlives the grace; the next prompt goes out when it ends (427.933175ms) +✔ engine: a malformed JSONL line fails the turn, not the process (22.736136ms) +✔ engine: a turn that ends in error rejects with the error code; process exit fails pending turns (46.413276ms) +✔ gateway: hello -> identify with intents, ready, heartbeat with jitter, ack (2.711402ms) +✔ gateway: missed ack closes the socket and resumes with the last sequence (1.939565ms) +✔ gateway: op 7 reconnect resumes; op 9 non-resumable re-identifies (0.591266ms) +✔ gateway: op 9 resumable resumes (0.3611ms) +✔ gateway: close 4014 is fatal, reports the missing intent, never reconnects (0.954906ms) +✔ gateway: 4004 and 4013 are fatal too; 1006 reconnects with identify when no session (0.572683ms) +✔ gateway: close() is final and unparseable frames are ignored (0.49881ms) +✔ git: config validation is strict, needs write: true, a work tree and a private token file (68.576099ms) +✔ git: the child environment drops every host git config, names one helper, and carries the token path only for origin (45.56167ms) +✔ git: status reports the branch, ahead/behind and changed paths, and refuses off the named branch or mid-merge (73.765148ms) +✔ git: parseStatus reads porcelain v2 including renames and conflicts (0.28583ms) +✔ git: a commit stages exactly the named files, carries the seat author and the requester trailer, and pushes at once (73.301209ms) +✔ git: commit refusals: message, paths, requester, nothing to commit, and an index that already holds other work (87.53822ms) +✔ git: a commit whose push fails is still a commit, says so, and the next commit's push carries both (D6) (82.429664ms) +✔ git: pull is fast-forward only; a diverged origin or dirty local files refuse with nothing merged (187.748855ms) +✔ git: push pushes the named branch only and reports up to date (68.54912ms) +✔ git: no token value or token path ever reaches a git argument list; outputs are masked and capped (77.62595ms) +✔ git: the credential helper answers get over https from a private file and nothing else (192.45159ms) +✔ git: the vault protocol validates before a commit, honours another owner's lock, reserves ids, and locks around writes (350.996448ms) +✔ lock: the claim is exclusive; a second start against a live owner refuses (4.442589ms) +✔ lock: a stale lock (dead owner, reused pid, or record without start) refuses run and is never signaled; only unlock clears it (80.14209ms) +✔ lock: an incomplete claim (directory without owner record) is busy and refuses run; unlock clears it (0.879317ms) +✔ lock: an owner record that exists but cannot be read is invalid: never signaled, never removed, never claimed over (1.878001ms) +✔ lock: legacy upgrade; a live connector holding a {pid, start} record is unknown, unlock refuses and nothing changes; after it exits, unlock clears it (51.730431ms) +✔ lock: a live pid whose record carries a malformed or noncanonical start or boot string is unknown, not a mismatch; nothing signals, removes, or claims over it (305.241917ms) +✔ lock: identity syntax; only canonical unsigned decimal start ticks and lowercase boot uuids are identities (0.436451ms) +✔ lock: a process whose start marker or boot id cannot be read refuses to claim (22.13892ms) +✔ lock: a live pid whose identity cannot be read right now is unknown: never signaled, never removed, never claimed over (0.941645ms) +✔ lock: four processes racing for the same binding; exactly one claims it and the others refuse (40.69254ms) +✔ lock: stale handoff; concurrent starts over a stale lock all refuse, nothing reclaims, one unlock then exactly one live owner (131.741059ms) +✔ lock: four-party schedule; claims landing inside an unlock's gap never survive, one unlock leaves no owner and no residue (80.649113ms) +✔ notices: a kind is recorded per UTC day and found again (0.40637ms) +✔ notify: the DM channel opens once, every send carries the nonce, and only the message id comes back (5.113329ms) +✔ notify: refusals and unknowns surface as RestOutcome without ids; a refused send reopens the channel next time (2.061449ms) +✔ notify: no dmRecipient, a non-0600 binding or token, or a missing binding refuse before any network use (1.419553ms) +✔ check --offline validates local fixture without REST or gateway calls (164.936804ms) +✔ check --offline refuses token mode and missing context under the selected repo (115.255403ms) +✔ run --offline is a usage refusal before reading config or networking (64.658492ms) +✔ recover: nothing to do is clean; a lock whose owner is gone or that has no record is cleared and STOP ends up absent (50.07082ms) +✔ recover: an operator STOP refuses with exit 3 and is never removed, whatever the lock says (36.622472ms) +✔ recover: a brake written during the unlock wins; STOP stays with both lines and the start is refused (31.735013ms) +✔ recover: a held binding refuses with exit 3 and writes no STOP: live owner, alive pid without verifiable identity, unreadable record (68.023788ms) +✔ cli: recover exits 0 when ready, 3 behind a brake or a held binding, and run's own STOP refusal is 3 (615.329128ms) +✔ rest: createMessage sends nonce, enforce_nonce, empty allowed_mentions and a soft reply reference (2.266712ms) +✔ rest: 429 waits retry_after and retries; 4xx is refused; 5xx and socket errors are unknown (3.491416ms) +✔ rest: content and nonce limits are enforced locally; typing never throws (0.631621ms) +✔ rest: react PUTs the encoded emoji on the inbound message for @me; 2xx is true, anything else is false and never throws (0.842643ms) +✔ rest: createDm posts the recipient and resolves the channel id; 4xx refused, 5xx unknown, bad id never sent (0.817126ms) +✔ setspark config: a bare https or loopback origin, a private key file, a principal (4.827514ms) +✔ setspark config: reaches the tools config and the binding as a fixed key (2.052688ms) +✔ setspark config: the binding's key survives resolveToolRoots and the engine's JSON hand-off to the extension (1.176934ms) +✔ setspark config: approvers come from the binding's users, never from the binding's setspark key (1.479781ms) +✔ setspark verbs: required_approvers go out as discord ids from names and come back as names (23.175566ms) +✔ setspark verbs: no Discord user id reaches tool text, whatever shape the service returns it in (9.630839ms) +✔ setspark contract: a decision made with names opens a request the connector accepts; names stored by an old record still refuse (7.136501ms) +✔ setspark keys: read per call, one printable token per file, rotation without a restart (3.791747ms) +✔ setspark idempotency keys: principal, turn id, call index; connector keys name a step (0.668929ms) +✔ setspark http core: json in and out, bearer header, idempotency header, fixed user agent, no key anywhere else (3.01183ms) +✔ setspark http core: error bodies become fixed refusals with code and the 409 fields; server text is data, cut (1008.960502ms) +✔ setspark verbs: a setspark key enables the eight verbs and no counters (0.476089ms) +✔ setspark verbs: writes carry the turn's key and the asserted requester, reads carry no key, and the api key never appears in text or details (6.187784ms) +✔ setspark verbs: no turn refuses every write before any request; bad arguments refuse before any request; reads still work (1.233657ms) +✔ setspark verbs: renderRecord caps long output and hides the accepted snapshot (0.199212ms) +✔ setspark api: bind, add_approval (button and reply) and get use integer request ids and the connector's keys (2.273972ms) +✔ tools: config refuses a missing, symlinked, dotted, non-directory or duplicate root and bad limits (3.935152ms) +✔ tools: every escape is refused with a fixed reason and nothing outside the root is read (3.904793ms) +✔ tools: happy paths list, read a window, and search case-insensitively; dotfiles and symlinks never appear (5.228771ms) +✔ tools: the tool set renders text for the model, records details for the journal, and enforces the per-run budget (3.559234ms) +✔ tools: listing and search caps hold (7.52236ms) +✔ tools: credential shapes are caught; ordinary prose and ids are not (0.58763ms) +✔ tools: the read uses the checked file itself; a symlink, a swapped file, a FIFO, a grown file or a hard link at read time is refused (3.978095ms) +✔ tools: an unreadable file under the root is skipped by search and refused by read (0.943191ms) +✔ tools: config accepts write: true only as a boolean, and enables the write tools only then (0.875055ms) +✔ tools: every write outside the fence is refused before any byte lands, and no temp file remains (4.810605ms) +✔ tools: write_file leaves the exact bytes, edit_file replaces one exact match, and the set renders the change as uncommitted (2.382867ms) +✔ tools: a target that changed between the check and the rename is refused and the temp file is removed (1.31175ms) +✔ web: config takes an https or loopback-http SearXNG base url and a bounded fetch cap (3.186139ms) +✔ web: address rules refuse every private, loopback, link-local, mapped and multicast form (1.989368ms) +✔ web: web_fetch refuses bad urls, private hosts, rebinding names, non-https redirects, too many hops, error status, non-text bodies, and times out (1022.146076ms) +✔ web: web_fetch returns html as text with the title, follows an https redirect, keeps plain text and json, and cuts at the cap (4.200609ms) +✔ web: html to text drops scripts, styles and comments, decodes entities and keeps block breaks (0.223248ms) +✔ web: web_search asks the instance for json, returns at most ten clean results, and refuses a bad query, a down instance or an unusable answer (2.564412ms) +✔ web: the tool set enables the web tools only with a web key, counts them in the budget, and records url, status and hits (2.333835ms) +ℹ tests 183 +ℹ suites 0 +ℹ pass 183 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 2631.617248 diff --git a/agents/rocko/work/queue-114/r1/out/full/test-auth.txt b/agents/rocko/work/queue-114/r1/out/full/test-auth.txt new file mode 100644 index 000000000..ac2287606 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-auth.txt @@ -0,0 +1,17 @@ +OK status with missing harness credential exits 3 and still lists accounts +OK status reports harness credential (read-only) + mosaic accounts +OK api key material never reaches output +OK oauth token material never reaches output +OK unparseable credential file exits 2 +OK symlinked credential file exits 4 +OK env-side credential names reported +OK env var values never reach output +OK accounts without an accounts dir reports none and creates nothing +OK accounts lists files and marks the active one +OK loose account perms flagged in listing +OK agent --auth with missing account file refuses (exit 4) +OK agent --auth with non-0600 account file refuses +OK agent --auth with invalid account name refuses +OK auth.sh without valid config refuses + +selftest: 15 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-conductor.txt b/agents/rocko/work/queue-114/r1/out/full/test-conductor.txt new file mode 100644 index 000000000..62afc513c --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-conductor.txt @@ -0,0 +1,23 @@ +On branch refactor +Your branch is up to date with 'origin/refactor'. + +nothing to commit, working tree clean +OK dry-run: allowed change, exit 0, nothing committed (exit 0) +OK dry-run committed nothing +OK apply: allowed change exits 0 (exit 0) +OK apply: attribution in commit subject +OK apply: target tree clean after commit +OK disallowed path refused (exit 1) +OK disallowed path: target untouched +OK syntax gate refused broken .mjs (exit 1) +OK syntax gate: target untouched +OK suite failure refused (exit 1) +OK suite failure: target reverted to clean +OK disabled policy refused (exit 2) +OK disabled policy: target untouched +OK failed run refused (exit 1) +OK failed run: target untouched +OK missing run exits 4 (exit 4) +OK invalid policy exits 2 (exit 2) + +selftest: 17 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-config.txt b/agents/rocko/work/queue-114/r1/out/full/test-config.txt new file mode 100644 index 000000000..76c05ef74 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-config.txt @@ -0,0 +1,26 @@ +OK absent adapter defaults to pi +OK adapter mock validates (exit 0) +OK unsupported adapter exits 2 (exit 2) +OK env exports adapter +OK bootstrap creates default when absent (exit 0) +OK bootstrap wrote config file +OK bootstrap is idempotent on existing config (exit 0) +OK bootstrap did not rewrite existing config +OK validate missing config exits 3 (exit 3) +OK malformed JSON exits 2 (exit 2) +OK unsupported configVersion exits 2 (exit 2) +OK unknown top-level key exits 2 (exit 2) +OK unknown execution key exits 2 (exit 2) +OK unsupported backend exits 2 (exit 2) +OK unsupported environment exits 2 (exit 2) +OK relative dataRoot exits 2 (exit 2) +OK non-canonical dataRoot exits 2 (exit 2) +OK filesystem root dataRoot exits 2 (exit 2) +OK home directory dataRoot exits 2 (exit 2) +OK dataRoot containing config dir exits 2 (exit 2) +OK control character in provider exits 2 (exit 2) +OK symlinked config file exits 2 (exit 2) +OK env exports resolve correctly +OK failed validation modified nothing + +selftest: 24 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-discord.txt b/agents/rocko/work/queue-114/r1/out/full/test-discord.txt new file mode 100644 index 000000000..051dfcc57 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-discord.txt @@ -0,0 +1,82 @@ +toolchain: node v26.8.1 + +OK syntax: packages/discord/src/approvals.mjs +OK syntax: packages/discord/src/authorize.mjs +OK syntax: packages/discord/src/binding.mjs +OK syntax: packages/discord/src/cli.mjs +OK syntax: packages/discord/src/connector.mjs +OK syntax: packages/discord/src/context.mjs +OK syntax: packages/discord/src/engine-pi.mjs +OK syntax: packages/discord/src/errors.mjs +OK syntax: packages/discord/src/gateway.mjs +OK syntax: packages/discord/src/git.mjs +OK syntax: packages/discord/src/journal.mjs +OK syntax: packages/discord/src/notify.mjs +OK syntax: packages/discord/src/rest.mjs +OK syntax: packages/discord/src/setspark.mjs +OK syntax: packages/discord/src/tools.mjs +OK syntax: packages/discord/src/web.mjs +OK syntax: packages/discord/bin/git-credential.mjs +OK syntax: packages/discord/extension/tools.mjs +OK syntax: packages/discord/tests/approvals.test.mjs +OK syntax: packages/discord/tests/authorize.test.mjs +OK syntax: packages/discord/tests/binding.test.mjs +OK syntax: packages/discord/tests/connector.test.mjs +OK syntax: packages/discord/tests/context.test.mjs +OK syntax: packages/discord/tests/copy-service.test.mjs +OK syntax: packages/discord/tests/engine.test.mjs +OK syntax: packages/discord/tests/fake-pi.mjs +OK syntax: packages/discord/tests/gateway.test.mjs +OK syntax: packages/discord/tests/git.test.mjs +OK syntax: packages/discord/tests/helpers.mjs +OK syntax: packages/discord/tests/journal.test.mjs +OK syntax: packages/discord/tests/notify.test.mjs +OK syntax: packages/discord/tests/offline-check.test.mjs +OK syntax: packages/discord/tests/recover.test.mjs +OK syntax: packages/discord/tests/rest.test.mjs +OK syntax: packages/discord/tests/setspark.test.mjs +OK syntax: packages/discord/tests/tools.test.mjs +OK syntax: packages/discord/tests/web.test.mjs +OK syntax: packages/discord/fixtures/claim-worker.mjs +OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs +OK syntax: scripts/discord.sh +OK syntax: scripts/discord-service.sh +OK packages/discord declares no dependencies +OK no bot-token-shaped string in packages/discord +OK fixture binding uses placeholder ids only +OK fixture binding validates +OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool +OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start +OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root +OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token +OK real pi with protocol vault adds reserve_id to the git verbs +OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key +OK real pi refuses a git key on a read-only root (fail closed) +OK real pi with the pilot flags (--no-tools) exposes no tool at all +OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed) +OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT +OK node --test packages/discord/tests/ (ℹ pass 183) +OK scripts/discord.sh --help exits 0 +OK scripts/discord.sh check without a binding exits 4 +OK scripts/discord.sh recover without a binding exits 4 +OK scripts/discord.sh reload without a binding exits 4 +OK scripts/discord-service.sh without a command exits 4 +OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP +OK service install writes the rendered unit (0644) and leaves no temp file +OK service install a second time reports unchanged +OK systemd-analyze verify accepts the rendered unit +OK service uninstall removes the unit file +OK service install with an unknown flag exits 4 +OK service install with USER unset finishes and names the account for lingering +OK pinned render runs copy CLI with copy cwd/repo and no checkout executable +OK pinned install writes the rendered unit in a temporary unit directory +OK pinned install refuses short prerequisite and writes no unit +OK pinned install refuses missing prerequisite and writes no unit +OK pinned install refuses cli prerequisite and writes no unit +OK pinned install refuses pi prerequisite and writes no unit +OK status names the copy from fake systemctl effective cwd +OK checkout install explicitly recommends --copy +OK wrapper check --offline passes local fixture and makes no network call +OK wrapper run --offline refuses usage + +discord suite: 78 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-extension-package.txt b/agents/rocko/work/queue-114/r1/out/full/test-extension-package.txt new file mode 100644 index 000000000..d9e8aab6f --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-extension-package.txt @@ -0,0 +1,21 @@ +OK initial ordinary-file install +OK installed tree matches canonical source +OK installed tree has no symlinks +OK check detects installation drift +OK sync refuses to overwrite installation drift +OK check detects an extra destination file +OK check detects an extra destination directory +OK check rejects a destination symlink +OK sync accepts a canonical source update +OK updated installation matches canonical source +/mnt/storage/src/mosaic-stack-rocko-114/scripts/test-extension-package.sh: line 14: 1903040 Killed "$@" > /dev/null 2>&1 +OK forced interruption kills the replacing process +OK next invocation recovers old consistent installation +OK interrupted replacement rolled back +OK sync succeeds after interruption recovery +OK unlocked stale lock file does not block +OK active lock refuses a concurrent sync +OK source symlink fails closed +OK nested second entrypoint fails closed + +extension package selftest: 18 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-foundation.txt b/agents/rocko/work/queue-114/r1/out/full/test-foundation.txt new file mode 100644 index 000000000..6338e1e6d --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-foundation.txt @@ -0,0 +1,53 @@ +toolchain: node v26.8.1, python 3.12.8, jsonschema 4.26.0 + +OK syntax: scripts/foundation-inspect.mjs +OK syntax: scripts/foundation/strict-json.mjs +OK syntax: scripts/foundation/canonical.mjs +OK syntax: scripts/foundation/resolve.mjs +OK syntax: scripts/foundation/validate-record.mjs +OK syntax: scripts/foundation/fixtures/build-fixtures.mjs +OK syntax: scripts/foundation/canonical.test.mjs +OK syntax: scripts/foundation/cli.test.mjs +OK syntax: scripts/foundation/fixtures.test.mjs +OK syntax: scripts/foundation/resolve.test.mjs +OK syntax: scripts/foundation/strict-json.test.mjs +OK syntax: scripts/foundation/verify-schema.py (ast only; no bytecode written) +OK fixture generator runs +OK checked-in fixtures/bundles equal a fresh generation +OK checked-in fixtures/raw equal a fresh generation +OK checked-in fixtures/index.json equal a fresh generation +OK checked-in demo bundles equal a fresh generation +OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT +OK node --test scripts/foundation/ (ℹ pass 80) +OK differential schema oracle: PASS: differential schema oracle (finite corpus; compatibility evidence, not equivalence proof) + platform witness: strftime('%Y') for year 999 -> '999' (pinned checker refuses years 0001..0999) + node v26.8.1; corpus 1568 records (38 pinned fixtures, 478 unique bundle records, 1052 typeCase/mutation/lexical cases) + schema column: agree-valid 540, agree-invalid 991, DISAGREEMENTS 0; strict-only (parser-bound) cases: 27; unsupported-kind records not schema-assessed by the inspector: 10 + profile column (schema-valid records only): profile-valid 510, profile-invalid 30 + profile refusals asserted: 30 schema-agreed-valid records refused only by the strict typed-string profile (rule profile-pattern-mismatch), 12 declared by name; 73 named probes verified against declared schema/profile columns +OK oracle: zero schema-column disagreements with the pinned checker +OK oracle: strict-only profile refusals are counted and asserted +OK demo: permitted read preview exits 0 (exit 0) +OK demo: permitted file.change preview exits 0 (exit 0) +OK demo: assignment.change proposal is unresolved (exit 3) (exit 3) +OK demo: revoked registration is refused (exit 3) (exit 3) +OK demo: message is not authority (exit 3) (exit 3) +OK usage: no arguments exits 2 (exit 2) +OK io: missing file exits 4 (exit 4) +OK io: directory exits 4 (exit 4) +OK io: symlink exits 4 (O_NOFOLLOW) (exit 4) +OK bound: oversize fixture exits 2 (exit 2) +OK profile: one final LF in a typed selection id is refused before admission (exit 2) (exit 2) +OK profile: two final LFs fail the schema pattern itself (exit 2) (exit 2) +OK profile: escaped newlines in free-form text stay allowed (exit 0) (exit 0) +OK profile refusal is invalid-request/profile-pattern-mismatch with selection and operation withheld, value not echoed +OK text output starts with the disclaimer +OK json output is valid JSON with result allowed and exactly the charter §7 fields +OK json golden matches byte-for-byte +OK sandboxed bundle run (env -i, PATH=/nonexistent) produced the unresolved proposal +OK sandbox inventory (path/type/size/mode/uid/gid/inode/mtime/sha256) unchanged by runs +OK canary never printed (bundle run and credential-file run) +OK a non-bundle JSON file is refused at the shape gate, not read into output +OK no field of the non-bundle file is echoed + +selftest: 44 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-land-work.txt b/agents/rocko/work/queue-114/r1/out/full/test-land-work.txt new file mode 100644 index 000000000..decdd8fbd --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-land-work.txt @@ -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 diff --git a/agents/rocko/work/queue-114/r1/out/full/test-queue.txt b/agents/rocko/work/queue-114/r1/out/full/test-queue.txt new file mode 100644 index 000000000..cc44019fa --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-queue.txt @@ -0,0 +1,36 @@ +toolchain: node v26.8.1, git version 2.55.0 + +OK syntax: packages/queue/src/cli.mjs +OK syntax: packages/queue/src/errors.mjs +OK syntax: packages/queue/src/io.mjs +OK syntax: packages/queue/src/lock.mjs +OK syntax: packages/queue/src/queue.mjs +OK syntax: packages/queue/src/review.mjs +OK syntax: packages/queue/src/store.mjs +OK syntax: packages/queue/tests/commit.test.mjs +OK syntax: packages/queue/tests/data.test.mjs +OK syntax: packages/queue/tests/dispatch.test.mjs +OK syntax: packages/queue/tests/gate-owner.test.mjs +OK syntax: packages/queue/tests/helpers.mjs +OK syntax: packages/queue/tests/lock.test.mjs +OK syntax: packages/queue/tests/migration.test.mjs +OK syntax: packages/queue/tests/review.test.mjs +OK syntax: packages/queue/tests/store.test.mjs +OK syntax: packages/queue/tests/write.test.mjs +OK syntax: packages/queue/tests/fixtures/fake-gitea.mjs +OK syntax: packages/queue/tests/fixtures/kill-at.mjs +OK syntax: packages/queue/tests/fixtures/lock-child.mjs +OK syntax: packages/queue/tests/fixtures/mosaic-pre-a2.sh +OK syntax: scripts/queue-commit.sh +OK syntax: scripts/git-hooks/pre-commit +OK syntax: scripts/mosaic +OK queue-commit.sh, the guard and scripts/mosaic are executable +OK packages/queue declares no dependencies +ℹ tests 156 +ℹ pass 156 +ℹ fail 0 +OK node --test packages/queue/tests/ +OK scripts/mosaic queue help +skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-114) is not the queue's canonical root (/mnt/storage/src/mosaic-stack) + +queue suite: 28 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-release.txt b/agents/rocko/work/queue-114/r1/out/full/test-release.txt new file mode 100644 index 000000000..1d6ed0503 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-release.txt @@ -0,0 +1,7 @@ +OK valid RELEASE resolves (exit 0) +OK invalid RELEASE exits 1 (exit 1) +OK missing RELEASE exits 1 (exit 1) +OK valid RELEASE leaves image tag consistent with version +skip state-machine cases (docker daemon unavailable) + +selftest: 4 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/full/test-task.txt b/agents/rocko/work/queue-114/r1/out/full/test-task.txt new file mode 100644 index 000000000..cd89fe9b2 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/full/test-task.txt @@ -0,0 +1,32 @@ +OK valid task validates (exit 0) +OK unknown task key exits 2 (exit 2) +OK unsupported taskVersion exits 2 (exit 2) +OK invalid task id exits 2 (exit 2) +OK empty prompt exits 2 (exit 2) +OK NUL in expectExact exits 2 (exit 2) +OK out-of-range timeout exits 2 (exit 2) +OK missing mission file exits 4 (exit 4) +OK task with valid mission validates (exit 0) +OK invalid mission exits 2 (exit 2) +OK validate missing task exits 4 (exit 4) +OK validation does not modify the task file +OK prune dry-run exits 0 (exit 0) +OK dry-run deleted nothing +OK prune --keep=2 --yes removes oldest (exit 0) +OK kept exactly 2 newest runs +OK newest run kept, oldest pruned +OK append-only receipt written (3 entries) +OK sessions/workspaces untouched by prune +OK prune with invalid keep exits 4 (exit 4) +skip adapter seam cases (docker daemon unavailable) +skip workspace/capability cases (docker daemon unavailable) +skip live task cases (docker unavailable) +OK onboard without name exits 4 (non-interactive) (exit 4) +OK onboard --name renders profile (exit 0) +OK profile written +OK canon structure: required filled, optional placeholdered +OK canon sections present +skip live recall pair: user recall run, recalled user name (docker daemon unavailable) +OK no agent identity on headless run + +selftest: 26 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/out/green-final.txt b/agents/rocko/work/queue-114/r1/out/green-final.txt new file mode 100644 index 000000000..9628da8c2 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/green-final.txt @@ -0,0 +1,13 @@ +✔ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (35.745472ms) +✔ Discord status reports effective WorkingDirectory from a fake user manager (28.458045ms) +✔ check --offline validates local fixture without REST or gateway calls (107.822599ms) +✔ check --offline refuses token mode and missing context under the selected repo (104.910772ms) +✔ run --offline is a usage refusal before reading config or networking (51.506878ms) +ℹ tests 5 +ℹ suites 0 +ℹ pass 5 +ℹ fail 0 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 335.898598 diff --git a/agents/rocko/work/queue-114/r1/out/green.txt b/agents/rocko/work/queue-114/r1/out/green.txt new file mode 100644 index 000000000..fe16c32ca --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/green.txt @@ -0,0 +1,35 @@ +✔ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (33.955405ms) +✔ Discord status reports effective WorkingDirectory from a fake user manager (28.150537ms) +✖ check --offline validates local fixture without REST or gateway calls (55.152759ms) +✔ check --offline refuses token mode and missing context under the selected repo (107.793918ms) +✔ run --offline is a usage refusal before reading config or networking (53.575105ms) +ℹ tests 5 +ℹ suites 0 +ℹ pass 4 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 286.142494 + +✖ failing tests: + +test at packages/discord/tests/offline-check.test.mjs:15:1 +✖ check --offline validates local fixture without REST or gateway calls (55.152759ms) + AssertionError [ERR_ASSERTION]: discord: token file does not hold a bot token: /mnt/storage/scratch/tmp/mosaic-discord-VWXFQT/secrets/bot.token + + + 2 !== 0 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/offline-check.test.mjs:16:56) + 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: 2, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/mutants/checkout-execstart.txt b/agents/rocko/work/queue-114/r1/out/mutants/checkout-execstart.txt new file mode 100644 index 000000000..8b0e159b9 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/mutants/checkout-execstart.txt @@ -0,0 +1,30 @@ +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (11.395833ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 0 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 75.471822 + +✖ failing tests: + +test at packages/discord/tests/copy-service.test.mjs:11:1 +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (11.395833ms) + AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: + + assert.ok(r.stdout.includes(`ExecStart=${process.execPath} ${s.copy}/packages/discord/src/cli.mjs run %i --supervised --repo ${s.copy}\n`)) + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/copy-service.test.mjs:13:70) + 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: false, + expected: true, + operator: '==', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/mutants/missing-pi-accepted.txt b/agents/rocko/work/queue-114/r1/out/mutants/missing-pi-accepted.txt new file mode 100644 index 000000000..5aa399baf --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/mutants/missing-pi-accepted.txt @@ -0,0 +1,30 @@ +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (43.477288ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 0 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 109.274458 + +✖ failing tests: + +test at packages/discord/tests/copy-service.test.mjs:11:1 +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (43.477288ms) + AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: + + 0 !== 1 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/copy-service.test.mjs:22:333) + 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: 0, + expected: 1, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/mutants/offline-calls-getMe.txt b/agents/rocko/work/queue-114/r1/out/mutants/offline-calls-getMe.txt new file mode 100644 index 000000000..b56f1312c --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/mutants/offline-calls-getMe.txt @@ -0,0 +1,31 @@ +✖ check --offline validates local fixture without REST or gateway calls (54.337228ms) +ℹ tests 1 +ℹ suites 0 +ℹ pass 0 +ℹ fail 1 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 120.395496 + +✖ failing tests: + +test at packages/discord/tests/offline-check.test.mjs:15:1 +✖ check --offline validates local fixture without REST or gateway calls (54.337228ms) + AssertionError [ERR_ASSERTION]: discord: GET /users/@me: fixture refuses network + + + 1 !== 0 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/offline-check.test.mjs:16:56) + 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: 1, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/mutants/summary.json b/agents/rocko/work/queue-114/r1/out/mutants/summary.json new file mode 100644 index 000000000..b36c05b3d --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/mutants/summary.json @@ -0,0 +1,17 @@ +[ + { + "name": "checkout-execstart", + "exit": 1, + "status": "killed" + }, + { + "name": "missing-pi-accepted", + "exit": 1, + "status": "killed" + }, + { + "name": "offline-calls-getMe", + "exit": 1, + "status": "killed" + } +] diff --git a/agents/rocko/work/queue-114/r1/out/network-clear.txt b/agents/rocko/work/queue-114/r1/out/network-clear.txt new file mode 100644 index 000000000..f8d1555c4 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/network-clear.txt @@ -0,0 +1 @@ +Named network absent or Docker unavailable; dead-socket gate created none. diff --git a/agents/rocko/work/queue-114/r1/out/network-inspect.txt b/agents/rocko/work/queue-114/r1/out/network-inspect.txt new file mode 100644 index 000000000..3b75cd62f --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/network-inspect.txt @@ -0,0 +1,2 @@ +[] +Error response from daemon: network mosaic-stack-rocko-114_default not found diff --git a/agents/rocko/work/queue-114/r1/out/process-clear.txt b/agents/rocko/work/queue-114/r1/out/process-clear.txt new file mode 100644 index 000000000..4825ae693 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/process-clear.txt @@ -0,0 +1 @@ +busy: [] diff --git a/agents/rocko/work/queue-114/r1/out/queue-in-review.txt b/agents/rocko/work/queue-114/r1/out/queue-in-review.txt new file mode 100644 index 000000000..df60fb5ff --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/queue-in-review.txt @@ -0,0 +1,3 @@ +request rocko-114-review-1 not sent: MOSAIC_GITEA_CREDENTIAL_FILE is not set; a request posts only with rocko's own token file +ok rocko-114-review-1 rev 1186 row 114 in-progress→in-review round 1 on #1608; request rocko-114-review-1 requesting +ok rocko-114-review-1.outcome rev 1187 row 114 round 1 request rocko-114-review-1 failed diff --git a/agents/rocko/work/queue-114/r1/out/red-offline.txt b/agents/rocko/work/queue-114/r1/out/red-offline.txt new file mode 100644 index 000000000..10f75aefb --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/red-offline.txt @@ -0,0 +1,67 @@ +✖ check --offline validates local fixture without REST or gateway calls (53.152825ms) +✖ check --offline refuses token mode and missing context under the selected repo (50.950038ms) +✔ run --offline is a usage refusal before reading config or networking (49.833721ms) +ℹ tests 3 +ℹ suites 0 +ℹ pass 1 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 224.637027 + +✖ failing tests: + +test at packages/discord/tests/offline-check.test.mjs:15:1 +✖ check --offline validates local fixture without REST or gateway calls (53.152825ms) + AssertionError [ERR_ASSERTION]: discord: unknown argument: --offline + usage: mosaic-discord check [--config PATH] [--repo PATH] + mosaic-discord run [--config PATH] [--repo PATH] [--supervised] + mosaic-discord stop [--config PATH] + mosaic-discord unlock [--config PATH] + mosaic-discord recover [--config PATH] + mosaic-discord reload [--config PATH] + + + 4 !== 0 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/offline-check.test.mjs:16:56) + 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: 4, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } + +test at packages/discord/tests/offline-check.test.mjs:20:1 +✖ check --offline refuses token mode and missing context under the selected repo (50.950038ms) + AssertionError [ERR_ASSERTION]: discord: unknown argument: --offline + usage: mosaic-discord check [--config PATH] [--repo PATH] + mosaic-discord run [--config PATH] [--repo PATH] [--supervised] + mosaic-discord stop [--config PATH] + mosaic-discord unlock [--config PATH] + mosaic-discord recover [--config PATH] + mosaic-discord reload [--config PATH] + + + 4 !== 2 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/offline-check.test.mjs:21:95) + 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: 4, + expected: 2, + operator: 'strictEqual', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/red-service.txt b/agents/rocko/work/queue-114/r1/out/red-service.txt new file mode 100644 index 000000000..ce0b22116 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/red-service.txt @@ -0,0 +1,53 @@ +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (5.455806ms) +✖ Discord status reports effective WorkingDirectory from a fake user manager (30.187919ms) +ℹ tests 2 +ℹ suites 0 +ℹ pass 0 +ℹ fail 2 +ℹ cancelled 0 +ℹ skipped 0 +ℹ todo 0 +ℹ duration_ms 100.729282 + +✖ failing tests: + +test at packages/discord/tests/copy-service.test.mjs:11:1 +✖ pinned Discord render/install and missing prerequisites; checkout bytes unchanged (5.455806ms) + AssertionError [ERR_ASSERTION]: usage: scripts/discord-service.sh render | install [--dir DIR] [--no-reload] | uninstall [--dir DIR] [--no-reload] | status + + + 4 !== 0 + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/copy-service.test.mjs:12:94) + 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: 4, + expected: 0, + operator: 'strictEqual', + diff: 'simple' + } + +test at packages/discord/tests/copy-service.test.mjs:23:1 +✖ Discord status reports effective WorkingDirectory from a fake user manager (30.187919ms) + AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: + + assert.ok(r.stdout.includes(`copy: ${s.id}`)) + + at TestContext. (file:///mnt/storage/src/mosaic-stack-rocko-114/packages/discord/tests/copy-service.test.mjs:24:337) + 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: false, + expected: true, + operator: '==', + diff: 'simple' + } diff --git a/agents/rocko/work/queue-114/r1/out/suite-counts.json b/agents/rocko/work/queue-114/r1/out/suite-counts.json new file mode 100644 index 000000000..71a547547 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/suite-counts.json @@ -0,0 +1,126 @@ +[ + { + "suite": "node-discord", + "exit": 0, + "began": "2026-10-14T20:30:20.823230+00:00", + "ended": "2026-10-14T20:30:23.493776+00:00", + "summaries": [ + "\u2714 turn: a failed engine turn posts the fixed line, never model output, and writes a failed record (3.649376ms)", + "\u2714 receipt: an admitted message gets one eyes reaction on the inbound message; drops and refusals get none; a failed reaction is recorded and does not fail the turn (2.66673ms)", + "\u2139 tests 183", + "\u2139 pass 183", + "\u2139 fail 0", + "\u2139 cancelled 0", + "\u2139 skipped 0" + ] + }, + { + "suite": "test-auth", + "exit": 0, + "began": "2026-10-14T20:30:23.494015+00:00", + "ended": "2026-10-14T20:30:24.109265+00:00", + "summaries": [ + "selftest: 15 passed, 0 failed" + ] + }, + { + "suite": "test-conductor", + "exit": 0, + "began": "2026-10-14T20:30:24.109530+00:00", + "ended": "2026-10-14T20:30:30.287430+00:00", + "summaries": [ + "OK failed run refused (exit 1)", + "OK failed run: target untouched", + "selftest: 17 passed, 0 failed" + ] + }, + { + "suite": "test-config", + "exit": 0, + "began": "2026-10-14T20:30:30.287694+00:00", + "ended": "2026-10-14T20:30:31.955466+00:00", + "summaries": [ + "OK failed validation modified nothing", + "selftest: 24 passed, 0 failed" + ] + }, + { + "suite": "test-discord", + "exit": 0, + "began": "2026-10-14T20:30:31.955716+00:00", + "ended": "2026-10-14T20:30:38.736178+00:00", + "summaries": [ + "OK node --test packages/discord/tests/ (\u2139 pass 183)", + "discord suite: 78 passed, 0 failed" + ] + }, + { + "suite": "test-extension-package", + "exit": 0, + "began": "2026-10-14T20:30:38.736435+00:00", + "ended": "2026-10-14T20:30:40.052900+00:00", + "summaries": [ + "extension package selftest: 18 passed, 0 failed" + ] + }, + { + "suite": "test-foundation", + "exit": 0, + "began": "2026-10-14T20:30:40.053145+00:00", + "ended": "2026-10-14T20:31:17.005136+00:00", + "summaries": [ + "OK node --test scripts/foundation/ (\u2139 pass 80)", + "selftest: 44 passed, 0 failed" + ] + }, + { + "suite": "test-land-work", + "exit": 0, + "began": "2026-10-14T20:31:17.005438+00:00", + "ended": "2026-10-14T20:31:25.637399+00:00", + "summaries": [ + "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 failed gate moves no ref", + "land-work selftests: 84 passed, 0 failed" + ] + }, + { + "suite": "test-queue", + "exit": 0, + "began": "2026-10-14T20:31:25.637691+00:00", + "ended": "2026-10-14T20:31:45.992880+00:00", + "summaries": [ + "\u2139 tests 156", + "\u2139 pass 156", + "\u2139 fail 0", + "skip queue verify and render --check: this checkout (/mnt/storage/src/mosaic-stack-rocko-114) is not the queue's canonical root (/mnt/storage/src/mosaic-stack)", + "queue suite: 28 passed, 0 failed" + ] + }, + { + "suite": "test-release", + "exit": 0, + "began": "2026-10-14T20:31:45.993134+00:00", + "ended": "2026-10-14T20:31:46.157295+00:00", + "summaries": [ + "skip state-machine cases (docker daemon unavailable)", + "selftest: 4 passed, 0 failed" + ] + }, + { + "suite": "test-task", + "exit": 0, + "began": "2026-10-14T20:31:46.157584+00:00", + "ended": "2026-10-14T20:31:48.126073+00:00", + "summaries": [ + "skip adapter seam cases (docker daemon unavailable)", + "skip workspace/capability cases (docker daemon unavailable)", + "skip live task cases (docker unavailable)", + "skip live recall pair: user recall run, recalled user name (docker daemon unavailable)", + "selftest: 26 passed, 0 failed" + ] + } +] diff --git a/agents/rocko/work/queue-114/r1/out/test-discord-first.txt b/agents/rocko/work/queue-114/r1/out/test-discord-first.txt new file mode 100644 index 000000000..051dfcc57 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/out/test-discord-first.txt @@ -0,0 +1,82 @@ +toolchain: node v26.8.1 + +OK syntax: packages/discord/src/approvals.mjs +OK syntax: packages/discord/src/authorize.mjs +OK syntax: packages/discord/src/binding.mjs +OK syntax: packages/discord/src/cli.mjs +OK syntax: packages/discord/src/connector.mjs +OK syntax: packages/discord/src/context.mjs +OK syntax: packages/discord/src/engine-pi.mjs +OK syntax: packages/discord/src/errors.mjs +OK syntax: packages/discord/src/gateway.mjs +OK syntax: packages/discord/src/git.mjs +OK syntax: packages/discord/src/journal.mjs +OK syntax: packages/discord/src/notify.mjs +OK syntax: packages/discord/src/rest.mjs +OK syntax: packages/discord/src/setspark.mjs +OK syntax: packages/discord/src/tools.mjs +OK syntax: packages/discord/src/web.mjs +OK syntax: packages/discord/bin/git-credential.mjs +OK syntax: packages/discord/extension/tools.mjs +OK syntax: packages/discord/tests/approvals.test.mjs +OK syntax: packages/discord/tests/authorize.test.mjs +OK syntax: packages/discord/tests/binding.test.mjs +OK syntax: packages/discord/tests/connector.test.mjs +OK syntax: packages/discord/tests/context.test.mjs +OK syntax: packages/discord/tests/copy-service.test.mjs +OK syntax: packages/discord/tests/engine.test.mjs +OK syntax: packages/discord/tests/fake-pi.mjs +OK syntax: packages/discord/tests/gateway.test.mjs +OK syntax: packages/discord/tests/git.test.mjs +OK syntax: packages/discord/tests/helpers.mjs +OK syntax: packages/discord/tests/journal.test.mjs +OK syntax: packages/discord/tests/notify.test.mjs +OK syntax: packages/discord/tests/offline-check.test.mjs +OK syntax: packages/discord/tests/recover.test.mjs +OK syntax: packages/discord/tests/rest.test.mjs +OK syntax: packages/discord/tests/setspark.test.mjs +OK syntax: packages/discord/tests/tools.test.mjs +OK syntax: packages/discord/tests/web.test.mjs +OK syntax: packages/discord/fixtures/claim-worker.mjs +OK syntax: packages/discord/fixtures/legacy-owner-worker.mjs +OK syntax: scripts/discord.sh +OK syntax: scripts/discord-service.sh +OK packages/discord declares no dependencies +OK no bot-token-shaped string in packages/discord +OK fixture binding uses placeholder ids only +OK fixture binding validates +OK real pi with the extension exposes exactly list_dir, read_file, search and no built-in tool +OK real pi with a writable root exposes exactly the three reads plus write_file and edit_file, and writes nothing at start +OK real pi with a web key exposes the three reads plus web_fetch and web_search, and no write tool without a writable root +OK real pi with a git root exposes the reads, writes and the four git verbs, commits nothing at start, and never shows the token +OK real pi with protocol vault adds reserve_id to the git verbs +OK real pi with a setspark key exposes the reads and the eight record verbs, no counters, and never shows the key +OK real pi refuses a git key on a read-only root (fail closed) +OK real pi with the pilot flags (--no-tools) exposes no tool at all +OK real pi exits non-zero without MOSAIC_DISCORD_TOOLS: no session, no tools (fail closed) +OK a failing nested test fails the run under a parent runner's NODE_TEST_CONTEXT +OK node --test packages/discord/tests/ (ℹ pass 183) +OK scripts/discord.sh --help exits 0 +OK scripts/discord.sh check without a binding exits 4 +OK scripts/discord.sh recover without a binding exits 4 +OK scripts/discord.sh reload without a binding exits 4 +OK scripts/discord-service.sh without a command exits 4 +OK service unit renders with the repository path, a supervised run as the main process, exit 3 never retried, and reload as SIGHUP +OK service install writes the rendered unit (0644) and leaves no temp file +OK service install a second time reports unchanged +OK systemd-analyze verify accepts the rendered unit +OK service uninstall removes the unit file +OK service install with an unknown flag exits 4 +OK service install with USER unset finishes and names the account for lingering +OK pinned render runs copy CLI with copy cwd/repo and no checkout executable +OK pinned install writes the rendered unit in a temporary unit directory +OK pinned install refuses short prerequisite and writes no unit +OK pinned install refuses missing prerequisite and writes no unit +OK pinned install refuses cli prerequisite and writes no unit +OK pinned install refuses pi prerequisite and writes no unit +OK status names the copy from fake systemctl effective cwd +OK checkout install explicitly recommends --copy +OK wrapper check --offline passes local fixture and makes no network call +OK wrapper run --offline refuses usage + +discord suite: 78 passed, 0 failed diff --git a/agents/rocko/work/queue-114/r1/packet-manifest.sha256 b/agents/rocko/work/queue-114/r1/packet-manifest.sha256 new file mode 100644 index 000000000..4b0e807a8 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/packet-manifest.sha256 @@ -0,0 +1,38 @@ +850f50e1672e1667b501e2f293f352b0fbf69d6124f7059f2d11e03735d7648a BUILD.md +8c897b19b571ad5b0ea8ee3a28b0d9d339bb98126dd3ce5f3193e7e89a655f8f base.txt +07d20b63826e25d5273175c298e00402810272e8d03d43748bf15b40de008dd2 build.patch +68c60a79914692f3f6d4923f7bcff41de109ccca33bf6fba687fb88efa24bcac candidate-manifest.sha256 +80e206246f3e8b496f6c4b9744f50ccdb78a978178f12f3a60b70ca91a989064 files.txt +8ad99be6e5418fbb45f3d2de9bc55dbda878f75fbddeec19b9a41557543b18af gate.py +987ecd603283b2bed71f6703b6be4a4f6672e30b96b764602c3f13f945986b90 mutants.py +088e0684151cd1d0b9d50577d1c481a805739e7084b58a61a241ab5c430be503 out/checkout-render-after.txt +088e0684151cd1d0b9d50577d1c481a805739e7084b58a61a241ab5c430be503 out/checkout-render-before.txt +8793c861ff5ca1ff86e7250d20a5e5406c579d106573421bd0a9509a5a00e502 out/final-verification.txt +2ddefa97647c42b7fff1e9e1cfc0323e45a2994f4f505832b215b0ef8d1955dc out/full/gate-results.json +666aaa26657e42f419872f00aa6232664a264ee681f207e25d05d4ab682db347 out/full/node-discord.txt +f91fc95a173339137f981e24fbf630acfde957e32c3cd71e28304532083c6a77 out/full/test-auth.txt +e1206366f07f3d9029530dcdcb55c0282d3f052adc60fc7fd51642d5d4ec3600 out/full/test-conductor.txt +52d211444489ea729dafc3c9745d4474d9dfd50f41055cbad792424197f04073 out/full/test-config.txt +87d2e24ce0be7586e31ea1f2c9ce5618b3127515b3c3cd3893f2a0ed899d5822 out/full/test-discord.txt +7f08b2b9deb0549a13bd205f00284e3c42838ff7ede6c07d503b3466447152d6 out/full/test-extension-package.txt +83dfaa21c4e4ad941088efab3f69e87ebd2f6bd3cc72ede938e21dc06da8a34f out/full/test-foundation.txt +8e2254aa3e1bb9b205ab72c68273d447c0328c9f156ccba2a46f3a0476468b58 out/full/test-land-work.txt +3faa89e75a914ce8d41980c71c54bdbe78ef1af764108088d3cae90a907e3730 out/full/test-queue.txt +6183e6b9b05edb497e92ffd09a19bba49c6f656c750ecb2acc283021113d1a98 out/full/test-release.txt +5dc16a91c36d6ff437e5fbb66764ece758e412f32f74b5a6d0c9cb9cad332f59 out/full/test-task.txt +e6403893a1796778506f4979ae52349c183e846bd9e8ea89049dcd8a1997c862 out/green-final.txt +d36abefd090b0e48ff62f4b12f32255367372cf1d59fcb1d6b26dcc72faf354e out/green.txt +c5c3085c3cb096d3c8499907e780e818352387507869718c05e8e8466075cf0b out/mutants/checkout-execstart.txt +8e8bb9e2af5da4a7905e5dc29bd299d546ef806039662ef8c662283d254dec98 out/mutants/missing-pi-accepted.txt +d92b1ba65404e7fd0b0e59980ca6f4f2deb3e348cdf96276494b078467e83651 out/mutants/offline-calls-getMe.txt +bee2f510b309a3af98d43f63e34384968065d7bdea5a786670bf3605a72eba47 out/mutants/summary.json +48dbb5dcccd5415a1e1b39326081598f543198471420cb3f174ab9d19bb8b0b5 out/network-clear.txt +0c50414f09a179e749639c37f45c13f746432213c0c8052660eda09158094303 out/network-inspect.txt +7b1c894bf5ac4017fc38d5d07b725f71fa4f0edd11ff68028ed53b8e6a2263a9 out/process-clear.txt +44267c81ad178dfd389b4d6deb3dc80176ad9fe828e7b6cce82c37e441beb52d out/queue-in-review.txt +5f17c71b2638de539f996a7d00290516d39fe5a24734ae08b55ddad01bfd02d8 out/red-offline.txt +b45024c5f50fc490553c1784c8975964cd2a240f5aa7e53f57a2924d80b12785 out/red-service.txt +fcfbc35c0c256e7da6019994bdb4ee319f4379dcb5a27b6a2e8e68d818ba45a7 out/suite-counts.json +87d2e24ce0be7586e31ea1f2c9ce5618b3127515b3c3cd3893f2a0ed899d5822 out/test-discord-first.txt +b3dd66ba58d6a2c78156c2a766ab51b37a8b378847de76311a715d104e076865 process-sweep.py +b0b8a95469e77280442d4733be76e0ed84ffd52f32b11c59780b968205685b06 verify.sh diff --git a/agents/rocko/work/queue-114/r1/process-sweep.py b/agents/rocko/work/queue-114/r1/process-sweep.py new file mode 100644 index 000000000..42f118979 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/process-sweep.py @@ -0,0 +1,13 @@ +"""Inspect only processes under this row's worktree; no unrelated argv/env.""" +from pathlib import Path +import os,sys +root='/mnt/storage/src/mosaic-stack-rocko-114';busy=[] +for p in Path('/proc').iterdir(): + if not p.name.isdigit():continue + try: + cwd=os.readlink(p/'cwd') + if cwd==root or cwd.startswith(root+'/'): + busy.append((int(p.name),(p/'comm').read_text().strip(),cwd)) + except OSError:pass +print('busy:',busy) +sys.exit(bool(busy)) diff --git a/agents/rocko/work/queue-114/r1/verify.sh b/agents/rocko/work/queue-114/r1/verify.sh new file mode 100755 index 000000000..083a8cf55 --- /dev/null +++ b/agents/rocko/work/queue-114/r1/verify.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail +packet=/mnt/storage/src/mosaic-stack/agents/rocko/work/queue-114/r1 +[ -z "$(git branch --show-current)" ] || { echo 'detached worktree required' >&2;exit 2; } +export DOCKER_HOST=unix:///nonexistent.sock +sha256sum -c "$packet/candidate-manifest.sha256" +git diff --check +python "$packet/gate.py" "${1:?pass absolute gate output directory}" +python "$packet/mutants.py" "${2:?pass separate absolute mutant output directory}" +sha256sum -c "$packet/candidate-manifest.sha256"