# Row 149 (#1643) mutants: one per new check. Each edits one file in the worktree, the test files # that cover row 149 run per package, and the file is restored afterwards. import subprocess, os W = os.path.expanduser('~/dewey-scratch/r149') OUT = os.path.expanduser('~/dewey-scratch/r149-mut') os.makedirs(OUT, exist_ok=True) TOOLS = 'packages/harness/src/tools.mjs' SR, MG = 'roles/security-reviewer.json', 'roles/merge-gate.json' PROACTIVE = 'Within your grants, act on what you see without waiting to be asked, and\nraise a decision or send a message for anything outside them.\n\n' ROUTING = ("Where a raise goes (PRD 1.5 REQ-DEC-2): a cross-role raise, or a gated\nraise that cites the project's current spec commit, goes to the\n" "business's arbiter for its domain. Pass `domain` to `raise_decision`,\n`technical` or `delivery`; leaving it out means `delivery`. An uncited\n" "gated raise, and every hard wait, goes to the human through the inbox.\n") SR_MSG = ',\n "messaging": {\n "sendTo": ["human", "chief-of-staff", "pm", "cto", "coder"],\n "receiveFrom": ["human", "chief-of-staff", "pm", "cto", "coder"]\n }' MG_MSG = ',\n "messaging": {\n "sendTo": ["human", "chief-of-staff", "pm", "cto"],\n "receiveFrom": ["human", "chief-of-staff", "pm", "cto"]\n }' M = { 'T1-domain-param': (TOOLS, ' domain: str("The arbiter domain for a routed raise: technical or delivery. Leaving it out means delivery", { enum: ["technical", "delivery"] }),\n', ''), 'T2-domain-enum': (TOOLS, '{ enum: ["technical", "delivery"] }', '{ enum: ["technical", "delivery", "human"] }'), 'T3-domain-desc': (TOOLS, 'Leaving it out means delivery"', 'Optional"'), 'T4-raise-desc': (TOOLS, "A cross-role raise, or a gated raise citing the project's current spec commit, goes to the business's arbiter for its domain; an uncited gated raise or a hard wait goes to the human. ", ''), 'S1-sr-bash': (SR, '"tools": ["read", "grep", "find", "ls"]', '"tools": ["read", "grep", "find", "ls", "bash"]'), 'S2-sr-send': (SR, '"withinRole": ["review.verdict"]', '"withinRole": ["review.verdict", "message.send"]'), 'S3-sr-messaging': (SR, SR_MSG, ''), 'G1-mg-within': (MG, '"withinRole": [],\n "crossRole": ["git.merge.protected"]', '"withinRole": ["git.merge.protected"],\n "crossRole": []'), 'G2-mg-extra-cross': (MG, '"crossRole": ["git.merge.protected"]', '"crossRole": ["git.merge.protected", "task.reassign"]'), 'G3-mg-edit': (MG, '"tools": ["read", "grep", "find", "ls"]', '"tools": ["read", "grep", "find", "ls", "edit"]'), 'G4-mg-no-cto': (MG, '"receiveFrom": ["human", "chief-of-staff", "pm", "cto"]', '"receiveFrom": ["human", "chief-of-staff", "pm"]'), 'G5-mg-messaging': (MG, MG_MSG, ''), 'G6-mg-send': (MG, '"withinRole": []', '"withinRole": ["message.send"]'), 'H1-header': ('roles/merge-gate.md', '# Role contract: merge-gate\n', '# Merge gate\n'), 'P1-proactive-gone': ('roles/reviewer.md', PROACTIVE, ''), 'P2-proactive-outside': ('roles/coder.md', PROACTIVE, '## Elsewhere\n\n' + PROACTIVE), 'R1-routing-gone': ('roles/chief-of-staff.md', ROUTING, ''), 'R2-hard-wait': ('roles/pm.md', '`deploy`', '`git.merge.protected`'), 'R3-old-text': ('roles/pm.md', 'raise a decision and wait for', 'raise a decision for the human and wait for'), } FILES = [ ('packages/business', ['tests/workflow-roles.test.mjs', 'tests/role.test.mjs', 'tests/assistant.test.mjs', 'tests/record-grants.test.mjs']), ('packages/bus', ['tests/workflow-roles.test.mjs', 'tests/csuite-messaging.test.mjs']), ('packages/harness', ['tests/raise-domain.test.mjs', 'tests/tools.test.mjs', 'tests/spec-tools.test.mjs']), ] env = dict(os.environ, TMPDIR=os.path.expanduser('~/dewey-scratch/tmp')) origs = {f: open(os.path.join(W, f)).read() for f in {v[0] for v in M.values()}} try: for name, (f, a, b) in M.items(): assert origs[f].count(a) == 1, name for name, (f, a, b) in M.items(): open(os.path.join(W, f), 'w').write(origs[f].replace(a, b)) killed, log = [], '' for pkg, tests in FILES: r = subprocess.run(['node', '--test', *tests], cwd=os.path.join(W, pkg), env=env, capture_output=True, text=True, timeout=300, start_new_session=True) log += f'== {pkg} rc={r.returncode}\n' + r.stdout + r.stderr fails = sorted({l[2:].split(' (')[0] for l in r.stdout.splitlines() if l.startswith('✖ ') and 'failing tests' not in l}) if r.returncode != 0: killed.append(f'{pkg.split("/")[1]}: ' + '; '.join(fails)) open(os.path.join(W, f), 'w').write(origs[f]) open(os.path.join(OUT, f'{name}.log'), 'w').write(log) print(name, 'KILLED' if killed else 'SURVIVED', '|', ' | '.join(killed)[:700], flush=True) finally: for f, s in origs.items(): open(os.path.join(W, f), 'w').write(s) print('restored', all(open(os.path.join(W, f)).read() == s for f, s in origs.items()))