row 217: correct new runtime fixture and record first-run evidence

This commit is contained in:
jason.woltje committed 2026-10-24 05:06:00 -05:00
1 parent 6558c7bf53
commit 2d274a5b6c
4 files changed
+96 -15

No files matched your search

+31
View File
@@ -225,3 +225,34 @@ an edit. Full green gate, mutants and Webby verdict remain outstanding.
Range-diff receipt rendering trims trailing whitespace on diff separator lines; no substantive range-diff content changed. This removes whitespace warnings caused by embedding raw diff output in a tracked text file. Range-diff receipt rendering trims trailing whitespace on diff separator lines; no substantive range-diff content changed. This removes whitespace warnings caused by embedding raw diff output in a tracked text file.
Final base-to-candidate whitespace check found a trailing blank line inherited from Launchpad in limits.mjs; removed it without behavior changes. manifest.r5.sha256 supersedes r4 for the exact candidate file hashes. Final base-to-candidate whitespace check found a trailing blank line inherited from Launchpad in limits.mjs; removed it without behavior changes. manifest.r5.sha256 supersedes r4 for the exact candidate file hashes.
## CLEAR sage-4042/4043 — execution started 2026-10-24
Queue beakley-217-start initially refused Lena's review-outcome lock twice;
same-op retry succeeded at rev3894 (briefed→in-progress). No queue bypass.
Short TMPDIR /mnt/storage/scratch/tmp/tNoueZ. Worktree-local npm ci at root
(128 packages) and packages/webui (2) completed; neither path was a symlink.
No npm/rm command ran in canonical. All test commands use timeout -k 10.
E4 current file: 3 pass/0 fail/0 skip. M5 isolated pre-fix stand-in: 1 pass,
2 expected assertion failures (citation-invalid instead of citation-unavailable),
exit1. Restored product bytes and checkout product hashes, then E4 restored
control 3/3. Receipts under run-r2/m5-red. M1 six-space anchors both match
exactly once on the eight-space lines.
Touched test files first run: 56 pass/1 fail, zero skip/cancel. The sole first-red
was NEW citation-runtime.test.mjs invalid-authority at Broker.checkBusiness:
validator output has unresolved roles and is not the host's broker projection.
Adjusted that new fixture only, following limits-runtime.test.mjs: minimal
empty-authority coder, validated real project mappings, real organization adapter
and systemFor(root). Single rerun 1/1, then all touched files 57/57. No base test
failure or edit. First log retained as run-r2/touched-first.log and reported to
Sage in beakley-0014. No production change was required.
The isolated mutant driver now wraps each node run in timeout -k 10, refuses a
symlinked root node_modules, restores mutated files in finally, verifies original
checkout product hashes after every mutant and reruns the restored control.
Optional name filters allow the E4 M5 RED before the full mutant pass. No
canonical dependency link is used; isolated copies link only this worktree's
own dependency install.
@@ -0,0 +1,23 @@
eeca81ab965f9e94f930ee5f51d16f019af6368bc6c3994895e204f7a54ec8d2 packages/bus/src/broker.mjs
ad3c686a089f67f3c89610937c6fc9b32367cea5d9735125d89bef042082d4e8 packages/bus/src/client.mjs
36b05dd3119e5929211aa1cc5d45c5043f5a1c34567ddc7cac8f002835d44abe packages/bus/src/runtime.mjs
66b26d131a19f4f411686427274936850c1ff0aed11e9b281ae4aadcf4b289fc packages/bus/src/server.mjs
cdd0304ec25ef1ad3e31c52502fa46f2c80bd77c8d3c2e13f8ed4b5328f342c9 packages/bus/tests/citation-availability.test.mjs
2e05074cd9d15d810103658af3858161cee2af78b0a2e1ba910222fab3e84401 packages/bus/tests/citation-guard.test.mjs
2c7a2102e2e0244876e41b664f4f706baefe3375100b956655551db1230f5da3 packages/bus/tests/citation-helpers.mjs
9768b6dc5ae078c5cc4f76473097287b74c5bc5853d39e1f57f153e646f861af packages/bus/tests/citation-runtime.test.mjs
abaeac64f2c3bf8ba83c9a4488edd9105c4707a6564560c5333d5421445653af packages/business/src/business.mjs
3a6044de5d1ca2cc35c5285b460c3e402b4274837e5d88b97f489797f6004903 packages/business/src/organization.mjs
4d2eb11beaa80175e524af1b95c81e7164990fba1d3e1754f5ba06eee390a14f packages/business/tests/reply-limits.test.mjs
a2bb98734bcc2556f8b2168f0faf8a89f7064c3f0aa49feb7d1975d596192f09 packages/cli/README.md
2f291a71f490f2741edada7a3e3788500f8976a08eb8ab1411f6c5982f778260 packages/cli/src/limits.mjs
f38af2d46d5f5f6388f599912507b94b87a0bf9dcc2104bb2187c38ee35118d5 packages/cli/tests/reply-limits.test.mjs
6ad72b4245e0a66e32725941900c1ece64c2e5de2fb73d65c8e042b4f3a691a6 packages/harness/src/runner.mjs
a5ef1b65230239a7baf6d0e8f2b8a51c0516348c7c4339a55b3f0a1a6ff531ba packages/harness/tests/citation-runner.test.mjs
330bc71bf6c7e64d3ddb70440903d2d9acf7878d44a49d7e30c2352ee4c807ec packages/harness/tests/fixtures/citation-adapter.mjs
f710d9600a17f6e2989a289cfe84e58f161d86c7306605946ce05fa71b364eb2 packages/library/src/guard.mjs
c0d630798914e300e461c247340533328e97119e54909c6a9406340e61fed8b7 packages/library/src/index.mjs
98ef45ed61144aaea44d8aea1ac43082b6d340297e46846d01772da38728e530 packages/library/src/limits.mjs
7b46f47b5e9d6b554b5d39bce2cd95c4610f5f35b8ab8fdc5a2864b3214be809 packages/library/src/reply-protocol.mjs
406146ebbce3710f308243b684a1c17e7626c1b65a4468489364317e31537a48 packages/library/tests/guard.test.mjs
39c8e6c8250a13fa43015fb2c407195e30ee642f729a9f6a644c38b4ea758a72 packages/seat/src/sandbox.mjs
+34 -12
View File
@@ -6,6 +6,7 @@ Usage: python3 agents/beakley/work/queue-217/mutants.py OUTPUT_DIRECTORY
""" """
from pathlib import Path from pathlib import Path
import io import io
import hashlib
import os import os
import subprocess import subprocess
import sys import sys
@@ -40,29 +41,50 @@ MUTANTS = [
archive = subprocess.check_output(["git", "archive", "HEAD", "packages", "roles", "scripts", "tools", "docs", "package.json", "RELEASE"], cwd=ROOT) archive = subprocess.check_output(["git", "archive", "HEAD", "packages", "roles", "scripts", "tools", "docs", "package.json", "RELEASE"], cwd=ROOT)
summary = [] summary = []
selected = set(sys.argv[2:])
product_files = [line.split(' ', 1)[1] for line in (ROOT / 'agents/beakley/work/queue-217/manifest.r5.sha256').read_text().splitlines()]
def hashes(base, files):
return {file: hashlib.sha256((base / file).read_bytes()).hexdigest() for file in files}
original_products = hashes(ROOT, product_files)
for name, changes, tests in MUTANTS: for name, changes, tests in MUTANTS:
if selected and name not in selected:
continue
with tempfile.TemporaryDirectory(prefix="row217-mutant-") as directory: with tempfile.TemporaryDirectory(prefix="row217-mutant-") as directory:
work = Path(directory) work = Path(directory)
with tarfile.open(fileobj=io.BytesIO(archive)) as source: with tarfile.open(fileobj=io.BytesIO(archive)) as source:
source.extractall(work, filter="data") source.extractall(work, filter="data")
modules = ROOT / "node_modules" modules = ROOT / "node_modules"
if modules.is_symlink():
raise SystemExit('root node_modules must be a local install, never a canonical link')
if modules.exists(): if modules.exists():
os.symlink(modules.resolve(), work / "node_modules", target_is_directory=True) os.symlink(modules.resolve(), work / "node_modules", target_is_directory=True)
cmd = ["node", "--test", *tests] cmd = ["timeout", "-k", "10", "120", "node", "--test", *tests]
with (OUT / f"{name}-control.log").open("w") as log: with (OUT / f"{name}-control.log").open("w") as log:
control = subprocess.run(cmd, cwd=work, stdout=log, stderr=subprocess.STDOUT, timeout=120) control = subprocess.run(cmd, cwd=work, stdout=log, stderr=subprocess.STDOUT, timeout=120)
if control.returncode: if control.returncode:
raise SystemExit(f"{name}: control RED, no mutant result claimed") raise SystemExit(f"{name}: control RED, no mutant result claimed")
for file, before, after in changes: originals = {file: (work / file).read_bytes() for file, _, _ in changes}
path = work / file try:
text = path.read_text() for file, before, after in changes:
if text.count(before) != 1: path = work / file
raise SystemExit(f"{name}: expected exactly one mutation anchor in {file}") text = path.read_text()
path.write_text(text.replace(before, after)) if text.count(before) != 1:
with (OUT / f"{name}.log").open("w") as log: raise SystemExit(f"{name}: expected exactly one mutation anchor in {file}")
mutant = subprocess.run(cmd, cwd=work, stdout=log, stderr=subprocess.STDOUT, timeout=120) path.write_text(text.replace(before, after))
if mutant.returncode == 0: with (OUT / f"{name}.log").open("w") as log:
raise SystemExit(f"{name}: SURVIVED") mutant = subprocess.run(cmd, cwd=work, stdout=log, stderr=subprocess.STDOUT, timeout=140)
summary.append(f"{name}: killed (control green, mutant exit {mutant.returncode})") if mutant.returncode != 1:
raise SystemExit(f"{name}: expected assertion failure exit 1, got {mutant.returncode}")
finally:
for file, content in originals.items():
(work / file).write_bytes(content)
assert all((work / file).read_bytes() == content for file, content in originals.items())
assert hashes(ROOT, product_files) == original_products, 'checkout product hashes changed'
(OUT / f"{name}-restored.sha256").write_text(''.join(f'{digest} {file}\n' for file, digest in sorted(original_products.items())))
with (OUT / f"{name}-restored-green.log").open("w") as log:
restored = subprocess.run(cmd, cwd=work, stdout=log, stderr=subprocess.STDOUT, timeout=140)
if restored.returncode:
raise SystemExit(f"{name}: restored control RED")
summary.append(f"{name}: killed (control green, mutant exit {mutant.returncode}, hashes restored, restored green)")
(OUT / "summary.txt").write_text("\n".join(summary) + "\n") (OUT / "summary.txt").write_text("\n".join(summary) + "\n")
print(summary[-1], flush=True) print(summary[-1], flush=True)
+8 -3
View File
@@ -6,7 +6,7 @@ import { tmpdir } from 'node:os';
import { join } from 'node:path'; import { join } from 'node:path';
import { startBroker } from '../src/runtime.mjs'; import { startBroker } from '../src/runtime.mjs';
import { validateBusinessDocument } from '../../business/src/business.mjs'; import { validateBusinessDocument } from '../../business/src/business.mjs';
import { businessDoc, rolesCopy, writeJson } from '../../business/tests/helpers.mjs'; import { businessDoc, rolesCopy, systemFor, writeJson } from '../../business/tests/helpers.mjs';
import { mappingEntry } from '../../library/tests/helpers.mjs'; import { mappingEntry } from '../../library/tests/helpers.mjs';
test('C2-06 runtime reads changed and unreadable reply limits without restarting', async t => { test('C2-06 runtime reads changed and unreadable reply limits without restarting', async t => {
@@ -14,8 +14,13 @@ test('C2-06 runtime reads changed and unreadable reply limits without restarting
const doc = businessDoc(root), rolesDir = rolesCopy(root), dir = join(root, 'config'), dataRoot = join(root, 'data'); const doc = businessDoc(root), rolesDir = rolesCopy(root), dir = join(root, 'config'), dataRoot = join(root, 'data');
doc.projects.books = mappingEntry(); doc.replyLimits = { requireCitation: false, citationsPerReply: 3 }; doc.projects.books = mappingEntry(); doc.replyLimits = { requireCitation: false, citationsPerReply: 3 };
const file = writeJson(join(dir, 'businesses/acme.json'), doc); const file = writeJson(join(dir, 'businesses/acme.json'), doc);
const business = validateBusinessDocument(doc, file, { rolesDir }); mkdirSync(dataRoot, { mode: 0o700 }); const checked = validateBusinessDocument(doc, file, { rolesDir }); mkdirSync(dataRoot, { mode: 0o700 });
const runtime = await startBroker({ dataRoot, businesses: { acme: business }, organization: { dir, rolesDir } }); // Runtime takes the host's broker projection, not the business validator's unresolved role entries.
// No agent action is needed here: use the same empty-authority shape as limits-runtime.test.mjs.
const business = { id: 'acme', human: 'jason', projects: checked.projects,
arbiters: { technical: 'coder', delivery: 'coder' },
roles: { coder: { definition: 'coder', authority: { withinRole: [], crossRole: [] } } } };
const runtime = await startBroker({ dataRoot, businesses: { acme: business }, organization: { dir, rolesDir, system: systemFor(root) } });
t.after(() => runtime.close()); t.after(() => runtime.close());
const human = runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true }); const human = runtime.broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
const status = () => runtime.broker.request(human, { verb: 'library.status', args: { project: 'books' } }); const status = () => runtime.broker.request(human, { verb: 'library.status', args: { project: 'books' } });