row 217: correct new runtime fixture and record first-run evidence
This commit is contained in:
1 parent
6558c7bf53
commit
2d274a5b6c
4 files changed
+96
-15
No files matched your search
@@ -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
|
||||||
@@ -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)
|
||||||
@@ -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' } });
|
||||||
|
|||||||
Reference in new issue
Block a user