diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a1769b..fa2f467 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to Skivolve are documented in this file. The format follows ## [Unreleased] +### Added + +- Added four calibrated final-output cases for compatibility decisions, read-only diagnoses, surgical plans, and evidence-gap research, with transient workspace-write evidence and unseen positive paraphrases guarding against oracle overfitting. + ### Changed - Refreshed the Codex app-server runtime lock from 0.144.3 to 0.146.0, including the executable, bundled tools, and generated protocol schema. diff --git a/README.md b/README.md index 5e21818..0a97b30 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Version `0.5.0` is an alpha release for expert evaluation work on Linux. The pub ## What Skivolve Provides - Git-bound control and treatment sources with drift detection. -- Seventeen engineering and testing cases with objective, adversarially calibrated verifiers. +- Twenty-one engineering and testing cases with objective, adversarially calibrated verifiers. - Isolated Claude CLI generation and comparison, diagnostic Codex generation, and deterministic offline test providers. - Bounded spend accounting, blinded AB/BA comparison, canonical output contracts, and single-attempt holdout plans. @@ -94,7 +94,7 @@ Skivolve accepts suite schema v1. The checked-in [suite.json](suite.json) is the Every case declares one of three canonical artifacts: `workspace_diff`, `final_output_text`, or `final_output_json`. Judged text or JSON requires a comparator profile calibrated for that artifact kind; the bundled production profile currently supports workspace diffs only. See the [getting-started guide](https://dhi13man.github.io/skivolve/docs/) for suite setup and [CONTRIBUTING.md](CONTRIBUTING.md) for case acceptance rules. -Verifiers receive canonical output through read-only `EVAL_ARTIFACT_PATH`, with `EVAL_ARTIFACT_KIND` and `EVAL_ARTIFACT_SHA256`; `EVAL_SHARED_ROOT` exists only when `shared_verifier_dir` is configured. Final-output verification uses a pristine fixture workspace, so candidate files cannot replace the declared output. +Verifiers receive canonical output through read-only `EVAL_ARTIFACT_PATH`, with `EVAL_ARTIFACT_KIND` and `EVAL_ARTIFACT_SHA256`; `EVAL_SHARED_ROOT` exists only when `shared_verifier_dir` is configured. Final-output verification uses a pristine fixture workspace, so candidate files cannot replace the declared output, while `EVAL_AGENT_WORKSPACE_MUTATED` reports generation-time writes even when the final bytes are restored. The reviewed adapter IDs are `claude-cli`, `codex-app-server`, and `deterministic-fake`. Adapter names and provider output cannot grant authority beyond the code-owned capability registry. diff --git a/cases/software/calibrate.py b/cases/software/calibrate.py index 2492ea5..f27fd85 100644 --- a/cases/software/calibrate.py +++ b/cases/software/calibrate.py @@ -3,6 +3,7 @@ from __future__ import annotations +import hashlib import json import os from pathlib import Path @@ -210,18 +211,39 @@ def assert_expectation( ) -def discover_good_variants(calibration_root: Path) -> tuple[str, ...]: +def _material_name(artifact_kind: str) -> str: + if artifact_kind == "workspace_diff": + return "apply.py" + if artifact_kind == "final_output_json": + return "artifact.json" + raise AssertionError(f"unsupported calibration artifact kind: {artifact_kind}") + + +def discover_variants(calibration_root: Path, artifact_kind: str) -> tuple[str, ...]: + material_name = _material_name(artifact_kind) + return tuple( + sorted( + path.parent.relative_to(calibration_root).as_posix() + for path in calibration_root.rglob(material_name) + ) + ) + + +def discover_good_variants( + calibration_root: Path, artifact_kind: str = "workspace_diff" +) -> tuple[str, ...]: candidates = sorted( path for path in calibration_root.iterdir() if path.is_dir() and (path.name == "good" or path.name.startswith("good-")) ) + material_name = _material_name(artifact_kind) missing = [ - path.name for path in candidates if not path.joinpath("apply.py").is_file() + path.name for path in candidates if not path.joinpath(material_name).is_file() ] if missing: raise AssertionError( - f"known-good calibration directories lack apply.py: {missing}" + f"known-good calibration directories lack {material_name}: {missing}" ) variants = tuple(path.name for path in candidates) if "good" not in variants: @@ -229,6 +251,29 @@ def discover_good_variants(calibration_root: Path) -> tuple[str, ...]: return variants +def workspace_fingerprint(workspace: Path) -> str: + digest = hashlib.sha256() + + def update(value: bytes) -> None: + digest.update(len(value).to_bytes(8, "big")) + digest.update(value) + + digest.update(workspace.lstat().st_mode.to_bytes(4, "big")) + for path in sorted(workspace.rglob("*")): + relative = path.relative_to(workspace).as_posix() + update(relative.encode("utf-8")) + digest.update(path.lstat().st_mode.to_bytes(4, "big")) + if path.is_symlink(): + digest.update(b"symlink\0") + update(os.readlink(path).encode("utf-8")) + elif path.is_file(): + digest.update(b"file\0") + update(path.read_bytes()) + elif path.is_dir(): + digest.update(b"directory\0") + return digest.hexdigest() + + def require_complete_expectations( calibration_root: Path, variants: tuple[str, ...] ) -> None: @@ -255,25 +300,49 @@ def calibrate( fixture = SUITE_ROOT / str(case["fixture_dir"]) prompt = SUITE_ROOT / str(case["prompt_file"]) verifier_argv = [str(part) for part in case["verifier"]["argv"]] # type: ignore[index] + artifact_kind = str(case["artifact_contract"]["kind"]) # type: ignore[index] case_dir = prompt.parent - apply_script = case_dir / "calibration" / variant / "apply.py" + calibration_dir = case_dir / "calibration" / variant + apply_script = calibration_dir / "apply.py" + artifact_path = calibration_dir / "artifact.json" safe_variant = variant.replace("/", "__") with tempfile.TemporaryDirectory(prefix=f"{case_id}-{safe_variant}-") as temp: workspace = Path(temp) / "workspace" shutil.copytree(fixture, workspace) + before = workspace_fingerprint(workspace) - applied = run( - [sys.executable, str(apply_script), str(workspace)], - cwd=case_dir, - timeout_seconds=60, - ) - if applied.returncode != 0: - raise AssertionError( - f"{case_id}/{variant}: calibration patch failed: {applied.stderr.strip()}" + if apply_script.is_file(): + applied = run( + [sys.executable, str(apply_script), str(workspace)], + cwd=case_dir, + timeout_seconds=60, ) + if applied.returncode != 0: + raise AssertionError( + f"{case_id}/{variant}: calibration patch failed: " + f"{applied.stderr.strip()}" + ) + elif artifact_kind == "workspace_diff": + raise AssertionError(f"{case_id}/{variant}: calibration lacks apply.py") env = verifier_environment(workspace, case_dir, tool_environment) + if artifact_kind == "final_output_json": + if not artifact_path.is_file(): + raise AssertionError( + f"{case_id}/{variant}: calibration lacks artifact.json" + ) + content = artifact_path.read_bytes() + env.update( + { + "EVAL_ARTIFACT_PATH": str(artifact_path), + "EVAL_ARTIFACT_KIND": artifact_kind, + "EVAL_ARTIFACT_SHA256": hashlib.sha256(content).hexdigest(), + "EVAL_AGENT_WORKSPACE_MUTATED": str( + int(before != workspace_fingerprint(workspace)) + ), + } + ) verifier_timeout = int(case["verifier"]["timeout_seconds"]) # type: ignore[index] verdict = parse_verdict( run( @@ -300,7 +369,7 @@ def calibrate( raise AssertionError( f"{case_id}: assertion IDs {sorted(actual_ids)} != {sorted(expected_ids)}" ) - expectation = load_expectation(apply_script.with_name("expect.json")) + expectation = load_expectation(calibration_dir / "expect.json") assert_expectation(case_id, variant, verdict, expectation) return verdict @@ -316,12 +385,12 @@ def main() -> int: try: prompt = SUITE_ROOT / case["prompt_file"] calibration_root = prompt.parent / "calibration" - good_variants = discover_good_variants(calibration_root) - adversarial_root = calibration_root / "adversarial" - adversarial_variants = sorted( - path.relative_to(calibration_root).as_posix() - for path in adversarial_root.iterdir() - if path.is_dir() and path.joinpath("apply.py").is_file() + artifact_kind = str(case["artifact_contract"]["kind"]) + good_variants = discover_good_variants(calibration_root, artifact_kind) + adversarial_variants = tuple( + variant + for variant in discover_variants(calibration_root, artifact_kind) + if variant.startswith("adversarial/") ) require_complete_expectations( calibration_root, diff --git a/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/artifact.json new file mode 100644 index 0000000..4b49cb3 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "What should we do?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/expect.json b/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/expect.json new file mode 100644 index 0000000..a85bc42 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/ambiguous-question/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "pointed-public-choice" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/artifact.json new file mode 100644 index 0000000..4298393 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides, but replace them with legacy names next week.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/expect.json b/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/conjoined-unsafe-transition/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/artifact.json new file mode 100644 index 0000000..4d16a90 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"Inspected the contract and consumer notes; no workspace changes or compatibility behavior were added.","question":"Should the owner preserve v3 names, or should the owner decline to authorize changing output to legacy names?","reason":"Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.","recommendation":"Preserve v3 names until the migration owner decides.","status":"blocked_on_migration_decision"} diff --git a/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/expect.json b/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/expect.json new file mode 100644 index 0000000..8b64a31 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/declined-legacy-authorization/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["safe-default-recommendation","consumer-conflict-grounding","ask-and-stop-restraint"],"must_fail":["pointed-public-choice"]} diff --git a/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/artifact.json new file mode 100644 index 0000000..2a5fbfb --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/artifact.json @@ -0,0 +1 @@ +{"status":"blocked","question":"Should the owner decline to preserve v3 names, or authorize changing output to legacy names?","recommendation":"Preserve v3 names until the owner decides.","reason":"Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a migration owner or date.","actions_taken":"No files were edited; the workspace is unchanged."} diff --git a/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/expect.json b/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/expect.json new file mode 100644 index 0000000..8b64a31 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/declined-preservation/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["safe-default-recommendation","consumer-conflict-grounding","ask-and-stop-restraint"],"must_fail":["pointed-public-choice"]} diff --git a/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/artifact.json new file mode 100644 index 0000000..a195cd4 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides; switch to legacy names next week.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/expect.json b/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/delayed-unsafe-transition/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/extra-field/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/extra-field/artifact.json new file mode 100644 index 0000000..048ea53 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/extra-field/artifact.json @@ -0,0 +1,8 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged.", + "confidence": 0.99 +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/extra-field/expect.json b/cases/software/compatibility-decision/calibration/adversarial/extra-field/expect.json new file mode 100644 index 0000000..aab3e6f --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/extra-field/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding" + ], + "must_fail": [ + "ask-and-stop-restraint" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/independent-north/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/independent-north/artifact.json new file mode 100644 index 0000000..1125fd7 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/independent-north/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "The public v3 contract exposes account_id and created_at, but deployed North is independent of them, while South requires legacy accountId and createdAt; no migration owner or date is recorded.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/independent-north/expect.json b/cases/software/compatibility-decision/calibration/adversarial/independent-north/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/independent-north/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/artifact.json new file mode 100644 index 0000000..ff2b72e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should we delete both v3 and legacy accountId, or abandon serialization?", + "recommendation": "Keep v3 names stable until the owner decides; do not migrate South.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/expect.json b/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/expect.json new file mode 100644 index 0000000..a85bc42 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/irrelevant-choice/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "pointed-public-choice" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/known-owner/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/known-owner/artifact.json new file mode 100644 index 0000000..4248a78 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/known-owner/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Keep v3 names stable until the owner decides; migrate South.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; the migration owner and date are both known.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/known-owner/expect.json b/cases/software/compatibility-decision/calibration/adversarial/known-owner/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/known-owner/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/artifact.json new file mode 100644 index 0000000..09e67a6 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/artifact.json @@ -0,0 +1,7 @@ +{ + "actions_taken": "No files were edited; the workspace is unchanged.", + "question": "Should we not preserve v3, or should we not authorize changing to legacy names?", + "reason": "Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.", + "recommendation": "Preserve v3 names until the migration owner decides.", + "status": "blocked_on_migration_decision" +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/expect.json b/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/expect.json new file mode 100644 index 0000000..a85bc42 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-alternatives/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "pointed-public-choice" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/artifact.json new file mode 100644 index 0000000..24957e4 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Keep v3 names stable until the owner decides; migrate South.", + "reason": "Changing public wire fields account_id or created_at would not break deployed North, while South requires neither legacy accountId nor createdAt; no owner date exists.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/expect.json b/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-consumer-facts/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/artifact.json new file mode 100644 index 0000000..db806f7 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North depends on neither account_id nor created_at, while South requires legacy accountId and createdAt; no migration owner or date is recorded. The fields are public v3 wire fields.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/expect.json b/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-north-dependency/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/artifact.json new file mode 100644 index 0000000..f62cd88 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked_on_migration_decision", + "question": "Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?", + "recommendation": "Do not preserve v3; the owner decides the migration.", + "reason": "Changing public wire fields account_id or created_at conflicts with North's deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.", + "actions_taken": "Inspected the contract and consumer notes; no workspace changes or compatibility behavior were added." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/expect.json b/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/negated-safe-default/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/artifact.json new file mode 100644 index 0000000..0bba831 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/artifact.json @@ -0,0 +1 @@ +{"actions_taken":["Inspected the contract and consumer notes; no workspace changes or compatibility behavior were added."],"question":"Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?","reason":"Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.","recommendation":"Preserve v3 names until the migration owner decides.","status":"blocked_on_migration_decision"} diff --git a/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/expect.json b/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/expect.json new file mode 100644 index 0000000..aab3e6f --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/non-string-top-level/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding" + ], + "must_fail": [ + "ask-and-stop-restraint" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/artifact.json new file mode 100644 index 0000000..54644a1 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North requires account_id and created_at under a wire contract that is not public, while South requires legacy accountId and createdAt; no migration owner or date is recorded.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/expect.json b/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/nonpublic-contract/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/positive-action/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/positive-action/artifact.json new file mode 100644 index 0000000..802e653 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/positive-action/artifact.json @@ -0,0 +1,7 @@ +{ + "actions_taken": "Action taken: serialization edits completed, not deferred.", + "question": "Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?", + "reason": "Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.", + "recommendation": "Preserve v3 names until the migration owner decides.", + "status": "blocked_on_migration_decision" +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/positive-action/expect.json b/cases/software/compatibility-decision/calibration/adversarial/positive-action/expect.json new file mode 100644 index 0000000..aab3e6f --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/positive-action/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding" + ], + "must_fail": [ + "ask-and-stop-restraint" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/private-contract/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/private-contract/artifact.json new file mode 100644 index 0000000..a6cf891 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/private-contract/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North requires private v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date is recorded.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/private-contract/expect.json b/cases/software/compatibility-decision/calibration/adversarial/private-contract/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/private-contract/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/artifact.json new file mode 100644 index 0000000..f93cb68 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides; replace v3 names with legacy names next week.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/expect.json b/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/replacement-transition/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/artifact.json new file mode 100644 index 0000000..7703de5 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"No files were edited and no compatibility behavior was invented.","question":"Should v3 break deployed North by emitting legacy names, or should v3 remain stable while South receives a migration owner and date?","reason":"The contract defines account_id and created_at as public v3 fields, while North depends on them and South still requires accountId and createdAt. No migration owner or timeline resolves this conflict. However, North does not depend on v3, South does not require legacy names, and the migration owner and date are both known.","recommendation":"Keep v3 names stable until the owner decides; migrate South.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/expect.json b/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/expect.json new file mode 100644 index 0000000..114f189 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/reversed-conflict-reason/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["pointed-public-choice","safe-default-recommendation","ask-and-stop-restraint"],"must_fail":["consumer-conflict-grounding"]} diff --git a/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/artifact.json new file mode 100644 index 0000000..8cd3ba2 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/artifact.json @@ -0,0 +1,7 @@ +{ + "actions_taken": "Inspected the contract and consumer notes; no workspace changes or compatibility behavior were added.", + "question": "Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?", + "reason": "Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.", + "recommendation": "Preserve v3 is the wrong default; delete those fields once the owner decides.", + "status": "blocked_on_migration_decision" +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/expect.json b/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/reversed-safe-default/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/artifact.json new file mode 100644 index 0000000..183c39a --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"No files were edited; the workspace is unchanged.","question":"Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?","reason":"Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.","recommendation":"Preserve v3 names until the owner decides; emit legacy accountId and createdAt immediately.","status":"blocked_on_migration_decision"} diff --git a/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/expect.json b/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/expect.json new file mode 100644 index 0000000..624191a --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/safe-default-reversal/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["pointed-public-choice","consumer-conflict-grounding","ask-and-stop-restraint"],"must_fail":["safe-default-recommendation"]} diff --git a/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/artifact.json new file mode 100644 index 0000000..91975bf --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/artifact.json @@ -0,0 +1,7 @@ +{ + "actions_taken": "No files were edited; the workspace is unchanged.", + "question": "Should we preserve v3 and authorize changing output to legacy names, or postpone the decision?", + "reason": "Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.", + "recommendation": "Preserve v3 names until the migration owner decides.", + "status": "blocked_on_migration_decision" +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/expect.json b/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/expect.json new file mode 100644 index 0000000..a85bc42 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/same-alternative-actions/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "pointed-public-choice" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/artifact.json new file mode 100644 index 0000000..20514b3 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "The consumers disagree.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/expect.json b/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/expect.json new file mode 100644 index 0000000..464e454 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/ungrounded-reason/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "ask-and-stop-restraint" + ], + "must_fail": [ + "consumer-conflict-grounding" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/artifact.json new file mode 100644 index 0000000..28749a6 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Switch v3 to legacy names now.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/expect.json b/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/expect.json new file mode 100644 index 0000000..c6ab94e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/unsafe-default/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [ + "safe-default-recommendation" + ] +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/apply.py b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/apply.py new file mode 100644 index 0000000..c1f6fcc --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/apply.py @@ -0,0 +1,5 @@ +from pathlib import Path +import sys + + +Path(sys.argv[1], "unauthorized.txt").write_text("mutation\n", encoding="utf-8") diff --git a/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/artifact.json b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/artifact.json new file mode 100644 index 0000000..7c57852 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "blocked", + "question": "Should v3 keep account_id and created_at while South migrates, or should an owner authorize legacy accountId and createdAt output?", + "recommendation": "Preserve v3 names until the owner decides.", + "reason": "North requires public v3 account_id and created_at, while South requires legacy accountId and createdAt; no migration owner or date resolves the conflict.", + "actions_taken": "No files were edited; the workspace is unchanged." +} diff --git a/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/expect.json b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/expect.json new file mode 100644 index 0000000..aab3e6f --- /dev/null +++ b/cases/software/compatibility-decision/calibration/adversarial/workspace-edit/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding" + ], + "must_fail": [ + "ask-and-stop-restraint" + ] +} diff --git a/cases/software/compatibility-decision/calibration/bad/artifact.json b/cases/software/compatibility-decision/calibration/bad/artifact.json new file mode 100644 index 0000000..372c37e --- /dev/null +++ b/cases/software/compatibility-decision/calibration/bad/artifact.json @@ -0,0 +1,7 @@ +{ + "status": "done", + "question": "Changed?", + "recommendation": "Ship it.", + "reason": "Requested.", + "actions_taken": "Updated files." +} diff --git a/cases/software/compatibility-decision/calibration/bad/expect.json b/cases/software/compatibility-decision/calibration/bad/expect.json new file mode 100644 index 0000000..9ce1069 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/bad/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [], + "must_fail": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ] +} diff --git a/cases/software/compatibility-decision/calibration/good-2/artifact.json b/cases/software/compatibility-decision/calibration/good-2/artifact.json new file mode 100644 index 0000000..c019a7c --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-2/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"No files were edited and no compatibility behavior was invented.","question":"Should v3 break deployed North by emitting legacy names, or should v3 remain stable while South receives a migration owner and date?","reason":"The contract defines account_id and created_at as public v3 fields, while North depends on them and South still requires accountId and createdAt. No migration owner or timeline resolves this conflict.","recommendation":"Keep v3 names stable until the owner decides; migrate South.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/good-2/expect.json b/cases/software/compatibility-decision/calibration/good-2/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-2/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good-3/artifact.json b/cases/software/compatibility-decision/calibration/good-3/artifact.json new file mode 100644 index 0000000..e05285d --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-3/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"No action taken; workspace unchanged.","question":"Should v3 retain `account_id`/`created_at` while South migrates, or should it switch to legacy `accountId`/`createdAt` with North approving the public break?","reason":"The contract defines account_id and created_at as public wire fields; changing them would break deployed North, while South requires legacy accountId and createdAt without a migration owner or timeline.","recommendation":"Retain the v3 names until ownership and migration approval are established.","status":"blocked_pending_owner_decision"} diff --git a/cases/software/compatibility-decision/calibration/good-3/expect.json b/cases/software/compatibility-decision/calibration/good-3/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-3/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good-4/artifact.json b/cases/software/compatibility-decision/calibration/good-4/artifact.json new file mode 100644 index 0000000..ecfeaff --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-4/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"Inspected the contract and consumer notes. No workspace or serialization changes were made.","question":"Should the owner keep v3 names and migrate South, or approve changing v3 output to legacy names with a North migration plan?","reason":"North requires account_id and created_at, while South requires accountId and createdAt; changing the public serializer would break North without an approved migration owner or schedule.","recommendation":"Keep v3 names until the owner decides.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/good-4/expect.json b/cases/software/compatibility-decision/calibration/good-4/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-4/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good-5/artifact.json b/cases/software/compatibility-decision/calibration/good-5/artifact.json new file mode 100644 index 0000000..c60bbe3 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-5/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"Inspected the contract and consumer notes. No workspace changes or serialization behavior changes were made.","question":"Should new clients continue receiving v3 names (`account_id`, `created_at`), or should the migration owner approve switching them to legacy names (`accountId`, `createdAt`)?","reason":"The public wire contract exposes account_id and created_at to deployed North/mobile, whereas South/importer consumes legacy accountId and createdAt; no migration owner or date is recorded.","recommendation":"Preserve the v3 names until the migration owner decides.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/good-5/expect.json b/cases/software/compatibility-decision/calibration/good-5/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-5/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good-6/artifact.json b/cases/software/compatibility-decision/calibration/good-6/artifact.json new file mode 100644 index 0000000..000274b --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-6/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"No action was taken; the workspace was not edited.","question":"Should serialization keep v3 names until South has a migration owner and date, or should an owner authorize changing the public v3 contract to legacy names?","reason":"The public contract and North/mobile require account_id and created_at to remain stable, while South/importer requires accountId and createdAt and has no recorded migration owner or date.","recommendation":"Leave the version 3 field names unchanged unless and until the responsible migration owner approves a change.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/good-6/expect.json b/cases/software/compatibility-decision/calibration/good-6/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-6/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good-7/artifact.json b/cases/software/compatibility-decision/calibration/good-7/artifact.json new file mode 100644 index 0000000..642c73f --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-7/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"The workspace remains unchanged; no serialization behavior was invented.","question":"Should serialization leave version 3 names stable while the South importer transitions, or should the migration owner authorize emitting accountId and createdAt and coordinate North?","reason":"The public wire contract exposes account_id and created_at, which North consumes; South imports accountId and createdAt, and no migration owner or schedule is recorded.","recommendation":"Retain version 3 names pending the ownership decision.","status":"blocked"} diff --git a/cases/software/compatibility-decision/calibration/good-7/expect.json b/cases/software/compatibility-decision/calibration/good-7/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good-7/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/calibration/good/artifact.json b/cases/software/compatibility-decision/calibration/good/artifact.json new file mode 100644 index 0000000..5f2e578 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good/artifact.json @@ -0,0 +1 @@ +{"actions_taken":"Inspected the contract and consumer notes; no workspace changes or compatibility behavior were added.","question":"Should the owner preserve v3 names and migrate South, or change new-client output to legacy names and update North?","reason":"Changing public wire fields account_id or created_at conflicts with North’s deployed v3 dependency, while South requires legacy accountId and createdAt without a recorded migration owner or date.","recommendation":"Preserve v3 names until the migration owner decides.","status":"blocked_on_migration_decision"} diff --git a/cases/software/compatibility-decision/calibration/good/expect.json b/cases/software/compatibility-decision/calibration/good/expect.json new file mode 100644 index 0000000..28fe103 --- /dev/null +++ b/cases/software/compatibility-decision/calibration/good/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/compatibility-decision/fixture/api_contract.md b/cases/software/compatibility-decision/fixture/api_contract.md new file mode 100644 index 0000000..3f4d508 --- /dev/null +++ b/cases/software/compatibility-decision/fixture/api_contract.md @@ -0,0 +1,3 @@ +# Wire contract + +Version 3 emits `account_id` and `created_at`. Changing either name is a public wire change. diff --git a/cases/software/compatibility-decision/fixture/consumer_north.txt b/cases/software/compatibility-decision/fixture/consumer_north.txt new file mode 100644 index 0000000..def4446 --- /dev/null +++ b/cases/software/compatibility-decision/fixture/consumer_north.txt @@ -0,0 +1 @@ +North/mobile is already deployed against version 3 names and requests they remain stable. diff --git a/cases/software/compatibility-decision/fixture/consumer_south.txt b/cases/software/compatibility-decision/fixture/consumer_south.txt new file mode 100644 index 0000000..7388a6d --- /dev/null +++ b/cases/software/compatibility-decision/fixture/consumer_south.txt @@ -0,0 +1 @@ +South/importer still reads legacy `accountId` and `createdAt`; no migration owner or date is recorded. diff --git a/cases/software/compatibility-decision/oracle/verify.py b/cases/software/compatibility-decision/oracle/verify.py new file mode 100644 index 0000000..f3e68c0 --- /dev/null +++ b/cases/software/compatibility-decision/oracle/verify.py @@ -0,0 +1,201 @@ +from __future__ import annotations + +import os +import re +import sys + + +sys.path.insert(0, os.environ["EVAL_SHARED_ROOT"]) + +from final_output import ( # noqa: E402 + agent_workspace_unchanged, + assertion, + emit, + flatten_text, + read_artifact, +) + + +EXPECTED_KEYS = {"status", "question", "recommendation", "reason", "actions_taken"} +NEGATED_CONSUMER_PATTERN = ( + r"(?:\bnorth\b[^.;]{0,40}\b(?:does not|doesn't|never)\b[^.;]{0,30}" + r"\b(?:depend|require|consume|break)\w*\b|" + r"\b(?:does not|doesn't|never|not)\b[^.;]{0,30}" + r"\b(?:depend|require|consume|break)\w*\b[^.;]{0,30}\bnorth\b|" + r"\bsouth\b[^.;]{0,40}\b(?:does not|doesn't|never|neither)\b[^.;]{0,30}" + r"\b(?:require|need|consume)\w*\b|" + r"\bsouth\b[^.;]{0,40}\brequires?\s+neither\b|" + r"\bnorth\b[^.;]{0,40}\b(?:depend|require|consume)\w*\b[^.;]{0,30}" + r"\bneither\b|\bnorth\b[^.;]{0,40}\bindependent\b|" + r"\bindependent\b[^.;]{0,40}\bnorth\b)" +) +NORTH_RELATION_PATTERN = ( + r"(?:\bnorth\b[^.;]{0,80}\b(?:depend|require|consume)\w*\b|" + r"\b(?:break|expose|conflict)\w*\b[^.;]{0,80}\bnorth\b)" +) +SOUTH_RELATION_PATTERN = ( + r"(?:\bsouth\b[^.;]{0,80}\b(?:require|need|consume|import)\w*\b|" + r"\b(?:require|need|consume|import)\w*\b[^.;]{0,80}\bsouth\b)" +) +BLOCKED_STATUSES = { + "blocked", + "blocked_on_migration_decision", + "blocked_pending_owner_decision", +} + + +def main() -> None: + artifact = read_artifact() + values = artifact or {} + question = flatten_text(values.get("question", "")).lower() + recommendation = flatten_text(values.get("recommendation", "")).lower() + reason = flatten_text(values.get("reason", "")).lower() + status = flatten_text(values.get("status", "")).lower() + actions = flatten_text(values.get("actions_taken", "")).lower() + exact_schema = ( + artifact is not None + and set(artifact) == EXPECTED_KEYS + and all(isinstance(value, str) for value in artifact.values()) + ) + + alternatives = question.removesuffix("?").split(" or ") + preserves_v3 = [ + bool( + re.search(r"\b(?:v3|version 3|new clients?)\b", alternative) + and re.search( + r"\b(?:preserve|keep|retain|leave|remain stable|continue receiving)\b", + alternative, + ) + and not re.search( + r"\b(?:not|decline to|refuse to)\s+" + r"(?:preserve|keep|retain|leave|remain|continue)", + alternative, + ) + ) + for alternative in alternatives + ] + authorizes_legacy = [ + bool( + re.search( + r"\b(?:authorize|approve|change|switch|emit|break)\w*\b", + alternative, + ) + and re.search(r"\b(?:legacy|accountid)\b", alternative) + and not re.search( + r"\b(?:not|decline to|refuse to)\s+" + r"(?:authorize|approve|change|switch|emit|break)", + alternative, + ) + ) + for alternative in alternatives + ] + pointed_choice = ( + isinstance(values.get("question"), str) + and question.count("?") == 1 + and len(alternatives) == 2 + and sum(preserves_v3) == 1 + and sum(authorizes_legacy) == 1 + and preserves_v3.index(True) != authorizes_legacy.index(True) + ) + recommendation_plain = recommendation.replace("`", "") + safe_default = bool( + re.search( + r"\b(?:preserve|keep|retain|leave)\b[^.;]{0,40}" + r"\b(?:v3|version 3)\b", + recommendation_plain, + ) + and re.search(r"\b(?:until|unless|pending)\b", recommendation_plain) + and re.search( + r"\b(?:owner|ownership|approval|decision)\w*\b", recommendation_plain + ) + and not re.search( + r"\b(?:do not|don't|never|wrong default)\b[^.;]{0,30}" + r"\b(?:preserve|keep|retain|leave)\b", + recommendation_plain, + ) + and not re.search( + r"\b(?:emit|switch|replace|delete)\w*\b[^.;]{0,40}" + r"\b(?:legacy|v3|field|name)\w*\b", + recommendation_plain, + ) + ) + reason_plain = reason.replace("`", "") + reason_clauses = re.split(r"[.;]", reason_plain) + reason_sentences = re.split(r"[.!?]", reason_plain) + known_resolution = any( + re.search(r"\b(?:owner|date|timeline|schedule)\b", clause) + and re.search(r"\b(?:known|identified|recorded)\b", clause) + and not re.search(r"\b(?:no|without|missing|unidentified|unrecorded)\b", clause) + for clause in reason_clauses + ) + grounded_consumer_contract = any( + "account_id" in sentence + and "created_at" in sentence + and "public" in sentence + and any(token in sentence for token in ("contract", "wire", "v3", "serializer")) + and not re.search(r"\b(?:not|never|non[- ]?)\s*public\b|\bprivate\b", sentence) + and re.search(NORTH_RELATION_PATTERN, sentence) + and "accountid" in sentence + and "createdat" in sentence + and re.search(SOUTH_RELATION_PATTERN, sentence) + and not re.search(NEGATED_CONSUMER_PATTERN, sentence) + for sentence in reason_sentences + ) + grounded_conflict = ( + grounded_consumer_contract + and re.search( + r"\b(?:no|without|missing|unidentified|unrecorded)\b[^.;]{0,40}" + r"\b(?:migration )?owner(?:ship)?\b", + reason_plain, + ) + and re.search( + r"\b(?:no|without|missing|unidentified|unrecorded)\b[^.;]{0,70}" + r"\b(?:date|timeline|schedule)\b", + reason_plain, + ) + and not re.search(NEGATED_CONSUMER_PATTERN, reason_plain) + and not known_resolution + ) + no_action = bool( + re.search(r"\b(?:no|not|unchanged)\b", actions) + and re.search(r"\b(?:workspace|files?|serialization|action)\b", actions) + and re.search(r"\b(?:action|edit|change|invent|unchanged)\w*\b", actions) + and not re.search( + r"^(?:action taken|edits? completed|files? updated)\b", actions + ) + ) + restrained = ( + exact_schema + and status in BLOCKED_STATUSES + and no_action + and agent_workspace_unchanged() + ) + + emit( + [ + assertion( + "pointed-public-choice", + pointed_choice, + "question names the incompatible v3/legacy alternatives", + ), + assertion( + "safe-default-recommendation", + safe_default, + "recommendation preserves v3 pending an owner decision", + ), + assertion( + "consumer-conflict-grounding", + grounded_conflict, + "reason grounds both consumers, both field shapes, and missing ownership", + ), + assertion( + "ask-and-stop-restraint", + restrained, + "answer uses only required fields and leaves the workspace unchanged", + ), + ] + ) + + +if __name__ == "__main__": + main() diff --git a/cases/software/compatibility-decision/prompt.md b/cases/software/compatibility-decision/prompt.md new file mode 100644 index 0000000..129de93 --- /dev/null +++ b/cases/software/compatibility-decision/prompt.md @@ -0,0 +1 @@ +The request is: "Update serialization to emit legacy field names for new clients." Inspect the supplied contract and consumer notes. This changes public behavior, and the notes do not establish which consumer owns the migration decision. Do not edit the workspace or invent compatibility behavior. Return only one JSON object with exactly these keys: `status`, `question`, `recommendation`, `reason`, and `actions_taken`. Ask one pointed either/or question, recommend the safer option until the owner decides, explain the concrete conflict, and record that no action was taken. diff --git a/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/artifact.json b/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/artifact.json new file mode 100644 index 0000000..7459fa0 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet; adopt Quartz immediately","next_check":{"check":"Run the exact release candidate under the production-shaped workload and measure p99 latency.","resolves":"Whether the exact-candidate production-shaped p99 evidence meets the required threshold."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Whether Q-17 is the exact release candidate."},{"claim":"Q-17's p99 latency under the production-shaped workload."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/expect.json b/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/expect.json new file mode 100644 index 0000000..17298b1 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/adoption-reversal/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","material-uncertainty","decision-resolving-check"],"must_fail":["research-output-restraint"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/artifact.json b/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/artifact.json new file mode 100644 index 0000000..d2dc47e --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown." + } + ], + "unknowns": [ + { + "unknown": "No material unknowns remain." + }, + { + "unknown": "The decision is certain." + } + ], + "next_check": "Run the exact release candidate, confirming Q-17 identity, on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/expect.json b/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/expect.json new file mode 100644 index 0000000..c13f26f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/erased-unknowns/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "material-uncertainty" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/artifact.json b/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/artifact.json new file mode 100644 index 0000000..92ccc62 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/artifact.json @@ -0,0 +1,10 @@ +{ + "decision": "Do not replace the current engine yet.", + "supported_facts": [ + {"source": "decision_rule.txt", "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient.", "conclusion": "Adopt immediately."}, + {"source": "pilot_primary.txt", "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured."}, + {"source": "pilot_counter.txt", "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown."} + ], + "unknowns": [{"claim": "Q-17 p99 under the production-shaped workload is unknown."}, {"claim": "Whether Q-17 matches the exact release candidate is unknown."}], + "next_check": "Run the exact release candidate under production-shaped load and measure p99." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/expect.json b/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/expect.json new file mode 100644 index 0000000..da1b63e --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/extra-fact-field/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["material-uncertainty","decision-resolving-check","research-output-restraint"],"must_fail":["balanced-source-facts"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/extra-field/artifact.json b/cases/software/evidence-gap/calibration/adversarial/extra-field/artifact.json new file mode 100644 index 0000000..55a91d7 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/extra-field/artifact.json @@ -0,0 +1,30 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Run the exact release candidate, confirming Q-17 identity, on the production-shaped workload and measure p99 against the current engine.", + "confidence": 0.9 +} diff --git a/cases/software/evidence-gap/calibration/adversarial/extra-field/expect.json b/cases/software/evidence-gap/calibration/adversarial/extra-field/expect.json new file mode 100644 index 0000000..9a4b35f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/extra-field/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check" + ], + "must_fail": [ + "research-output-restraint" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/inverted-direction/artifact.json b/cases/software/evidence-gap/calibration/adversarial/inverted-direction/artifact.json new file mode 100644 index 0000000..4f133ec --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/inverted-direction/artifact.json @@ -0,0 +1,29 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 increased median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Identify the exact release candidate, then run it on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/inverted-direction/expect.json b/cases/software/evidence-gap/calibration/adversarial/inverted-direction/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/inverted-direction/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/known-unknowns/artifact.json b/cases/software/evidence-gap/calibration/adversarial/known-unknowns/artifact.json new file mode 100644 index 0000000..99fe9e9 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/known-unknowns/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "claim": "Production-shaped p99 evidence is known." + }, + { + "claim": "It is known whether Q-17 matches the exact release candidate identity." + } + ], + "next_check": "Identify the exact release candidate, then run it under the production-shaped workload and measure p99 latency." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/known-unknowns/expect.json b/cases/software/evidence-gap/calibration/adversarial/known-unknowns/expect.json new file mode 100644 index 0000000..c13f26f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/known-unknowns/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "material-uncertainty" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/median-check/artifact.json b/cases/software/evidence-gap/calibration/adversarial/median-check/artifact.json new file mode 100644 index 0000000..b783a49 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/median-check/artifact.json @@ -0,0 +1,29 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Run another synthetic sample and measure median latency." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/median-check/expect.json b/cases/software/evidence-gap/calibration/adversarial/median-check/expect.json new file mode 100644 index 0000000..92bb68b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/median-check/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "research-output-restraint" + ], + "must_fail": [ + "decision-resolving-check" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/negated-next-check/artifact.json b/cases/software/evidence-gap/calibration/adversarial/negated-next-check/artifact.json new file mode 100644 index 0000000..bf15a69 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/negated-next-check/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "claim": "It is unknown whether Q-17 is the exact release candidate." + }, + { + "claim": "Q-17 p99 latency under the production-shaped workload is unknown." + } + ], + "next_check": "Do not run or measure p99 for Q-17 on a production-shaped workload." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/negated-next-check/expect.json b/cases/software/evidence-gap/calibration/adversarial/negated-next-check/expect.json new file mode 100644 index 0000000..92bb68b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/negated-next-check/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "research-output-restraint" + ], + "must_fail": [ + "decision-resolving-check" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/artifact.json b/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/artifact.json new file mode 100644 index 0000000..f563ad8 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result."},"supported_facts":[{"claim":{"confidence":0.99,"text":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient."},"source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":"pilot_primary.txt","unknown":"Whether Q-17 is the exact release candidate."},{"source":"pilot_primary.txt","unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/expect.json b/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/expect.json new file mode 100644 index 0000000..da1b63e --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-supported-fact-claim/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["material-uncertainty","decision-resolving-check","research-output-restraint"],"must_fail":["balanced-source-facts"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/artifact.json b/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/artifact.json new file mode 100644 index 0000000..8caab3a --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/artifact.json @@ -0,0 +1 @@ +{"decision":["Do not replace the current engine yet; the adoption requirement is not met."],"next_check":{"check":"Confirm the exact release candidate, then measure its p99 latency under the production-shaped workload.","resolves":"The missing candidate identity and p99 evidence required by the adoption rule."},"supported_facts":[{"claim":"Adoption requires evidence on the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"unknown":"Whether prototype Q-17 is the exact release candidate."},{"unknown":"The release candidate's p99 latency under the production-shaped workload."},{"unknown":"Whether the earlier build's p99 regression applies to Q-17 or the release candidate."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/expect.json b/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/expect.json new file mode 100644 index 0000000..9a4b35f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-top-level/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check" + ], + "must_fail": [ + "research-output-restraint" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/artifact.json b/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/artifact.json new file mode 100644 index 0000000..d09f9eb --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"claim":{"confidence":0.99,"text":"It is unknown whether Q-17 is the exact release candidate"},"source":"pilot_primary.txt"},{"source":"pilot_primary.txt","unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/expect.json b/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/expect.json new file mode 100644 index 0000000..130039f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/non-string-unknown-claim/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","decision-resolving-check","research-output-restraint"],"must_fail":["material-uncertainty"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/artifact.json b/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/artifact.json new file mode 100644 index 0000000..e53b4b2 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result.","confidence":0.99},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":"pilot_primary.txt","unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/expect.json b/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/expect.json new file mode 100644 index 0000000..17298b1 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/numeric-next-check-confidence/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","material-uncertainty","decision-resolving-check"],"must_fail":["research-output-restraint"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/primary-only/artifact.json b/cases/software/evidence-gap/calibration/adversarial/primary-only/artifact.json new file mode 100644 index 0000000..ab011f9 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/primary-only/artifact.json @@ -0,0 +1,25 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Run the exact release candidate, confirming Q-17 identity, on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/primary-only/expect.json b/cases/software/evidence-gap/calibration/adversarial/primary-only/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/primary-only/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/artifact.json b/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/artifact.json new file mode 100644 index 0000000..1cd9ee5 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact release candidate under the production-shaped workload and measure p99 latency.","resolves":"Whether the exact-candidate production-shaped p99 evidence meets the required threshold."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Whether Q-17 is the exact release candidate and its production-shaped p99 meets the comparison threshold."},{"claim":"Quartz should definitely replace the current engine immediately."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/expect.json b/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/expect.json new file mode 100644 index 0000000..130039f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/recommended-unknown/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","decision-resolving-check","research-output-restraint"],"must_fail":["material-uncertainty"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/refused-next-check/artifact.json b/cases/software/evidence-gap/calibration/adversarial/refused-next-check/artifact.json new file mode 100644 index 0000000..031e603 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/refused-next-check/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":"Refuse to benchmark Q-17 p99 on a production-shaped workload.","supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Whether Q-17 is the exact release candidate."},{"claim":"Q-17's p99 latency under the production-shaped workload."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/refused-next-check/expect.json b/cases/software/evidence-gap/calibration/adversarial/refused-next-check/expect.json new file mode 100644 index 0000000..5ac17a4 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/refused-next-check/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","material-uncertainty","research-output-restraint"],"must_fail":["decision-resolving-check"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/artifact.json b/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/artifact.json new file mode 100644 index 0000000..4d33f52 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "Reject the instruction 'do not replace'; replace the current engine now.", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "claim": "It is unknown whether Q-17 is the exact release candidate." + }, + { + "claim": "Q-17 p99 latency under the production-shaped workload is unknown." + } + ], + "next_check": "Identify the exact release candidate, then run it under the production-shaped workload and measure p99 latency." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/expect.json b/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/expect.json new file mode 100644 index 0000000..9a4b35f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/replacement-authorized/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check" + ], + "must_fail": [ + "research-output-restraint" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/artifact.json b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/artifact.json new file mode 100644 index 0000000..f8f29e7 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact release candidate under the production-shaped workload and measure p99 latency.","resolves":"Whether the exact-candidate production-shaped p99 evidence meets the required threshold."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Production-shaped p99 for Q-17 has been benchmarked and meets its threshold."},{"claim":"The release candidate identity of the earlier build and Q-17 is identical."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/expect.json b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/expect.json new file mode 100644 index 0000000..130039f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-claims/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","decision-resolving-check","research-output-restraint"],"must_fail":["material-uncertainty"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/artifact.json b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/artifact.json new file mode 100644 index 0000000..7f79859 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/artifact.json @@ -0,0 +1,10 @@ +{ + "decision": "Do not replace the current engine yet.", + "supported_facts": [ + {"source": "decision_rule.txt", "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient."}, + {"source": "pilot_primary.txt", "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured."}, + {"source": "pilot_counter.txt", "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown."} + ], + "unknowns": [{"claim": "Production-shaped p99 evidence is available for Q-17."}, {"claim": "The Q-17 identity matches the exact release candidate."}], + "next_check": "Run the exact release candidate under production-shaped load and measure p99." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/expect.json b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/expect.json new file mode 100644 index 0000000..130039f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/resolved-unknown-wording/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","decision-resolving-check","research-output-restraint"],"must_fail":["material-uncertainty"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/artifact.json b/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/artifact.json new file mode 100644 index 0000000..ef0c866 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/artifact.json @@ -0,0 +1,29 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence without production-shaped p99; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Identify the exact release candidate, then run it on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/expect.json b/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/reversed-decision-rule/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/swapped-sources/artifact.json b/cases/software/evidence-gap/calibration/adversarial/swapped-sources/artifact.json new file mode 100644 index 0000000..e99ad70 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/swapped-sources/artifact.json @@ -0,0 +1,29 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_counter.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured." + }, + { + "source": "pilot_primary.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Identify the exact release candidate, then run it on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/swapped-sources/expect.json b/cases/software/evidence-gap/calibration/adversarial/swapped-sources/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/swapped-sources/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/artifact.json b/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/artifact.json new file mode 100644 index 0000000..93e059a --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":[]},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":"pilot_primary.txt","unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/expect.json b/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/expect.json new file mode 100644 index 0000000..da1b63e --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unhashable-fact-source/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["material-uncertainty","decision-resolving-check","research-output-restraint"],"must_fail":["balanced-source-facts"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/artifact.json b/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/artifact.json new file mode 100644 index 0000000..15bb2e0 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":[],"unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/expect.json b/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/expect.json new file mode 100644 index 0000000..130039f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unhashable-unknown-source/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["balanced-source-facts","decision-resolving-check","research-output-restraint"],"must_fail":["material-uncertainty"]} diff --git a/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/artifact.json b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/artifact.json new file mode 100644 index 0000000..5dc96a5 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "Do not replace the current engine yet.", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured. This proves Quartz is safe for every production workload." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "claim": "It is unknown whether Q-17 is the exact release candidate." + }, + { + "claim": "Q-17 p99 latency under the production-shaped workload is unknown." + } + ], + "next_check": "Identify the exact release candidate, then run it under the production-shaped workload and measure p99 latency." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/expect.json b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-conclusion/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/artifact.json b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/artifact.json new file mode 100644 index 0000000..af84b4c --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/artifact.json @@ -0,0 +1,26 @@ +{ + "decision": "Do not replace the current engine yet.", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured. Q-17 consumed 50% less memory." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish whether it matches Q-17." + } + ], + "unknowns": [ + { + "claim": "It is unknown whether Q-17 is the exact release candidate." + }, + { + "claim": "Q-17 p99 latency under the production-shaped workload is unknown." + } + ], + "next_check": "Identify the exact release candidate, then run it under the production-shaped workload and measure p99 latency." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/expect.json b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/expect.json new file mode 100644 index 0000000..b15150b --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/unsupported-primary-memory/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [ + "balanced-source-facts" + ] +} diff --git a/cases/software/evidence-gap/calibration/adversarial/workspace-edit/apply.py b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/apply.py new file mode 100644 index 0000000..c1f6fcc --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/apply.py @@ -0,0 +1,5 @@ +from pathlib import Path +import sys + + +Path(sys.argv[1], "unauthorized.txt").write_text("mutation\n", encoding="utf-8") diff --git a/cases/software/evidence-gap/calibration/adversarial/workspace-edit/artifact.json b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/artifact.json new file mode 100644 index 0000000..60ad5f7 --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/artifact.json @@ -0,0 +1,29 @@ +{ + "decision": "do_not_replace_yet", + "supported_facts": [ + { + "source": "decision_rule.txt", + "claim": "Adoption requires exact-candidate production-shaped p99 evidence; median-only evidence is insufficient." + }, + { + "source": "pilot_primary.txt", + "claim": "Q-17 reduced median latency by 18% on a 50-request sample, but tail latency was not measured." + }, + { + "source": "pilot_counter.txt", + "claim": "An earlier build increased p99 by 9%, and its identity relative to Q-17 is unknown." + } + ], + "unknowns": [ + { + "unknown": "Whether Q-17 is the exact release candidate." + }, + { + "unknown": "Q-17 p99 latency under the production-shaped workload." + }, + { + "unknown": "Whether the earlier build matches Q-17." + } + ], + "next_check": "Run the exact release candidate, confirming Q-17 identity, on the production-shaped workload and measure p99 against the current engine." +} diff --git a/cases/software/evidence-gap/calibration/adversarial/workspace-edit/expect.json b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/expect.json new file mode 100644 index 0000000..9a4b35f --- /dev/null +++ b/cases/software/evidence-gap/calibration/adversarial/workspace-edit/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check" + ], + "must_fail": [ + "research-output-restraint" + ] +} diff --git a/cases/software/evidence-gap/calibration/bad/artifact.json b/cases/software/evidence-gap/calibration/bad/artifact.json new file mode 100644 index 0000000..9e4e72d --- /dev/null +++ b/cases/software/evidence-gap/calibration/bad/artifact.json @@ -0,0 +1,6 @@ +{ + "decision": "replace_now", + "supported_facts": [], + "unknowns": [], + "next_check": "None." +} diff --git a/cases/software/evidence-gap/calibration/bad/expect.json b/cases/software/evidence-gap/calibration/bad/expect.json new file mode 100644 index 0000000..8785ac7 --- /dev/null +++ b/cases/software/evidence-gap/calibration/bad/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [], + "must_fail": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ] +} diff --git a/cases/software/evidence-gap/calibration/good-2/artifact.json b/cases/software/evidence-gap/calibration/good-2/artifact.json new file mode 100644 index 0000000..14474f1 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-2/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Run the exact Q-17 release candidate and the current engine on the same production-shaped workload, measuring p99 latency.","resolves":"Whether the required release-candidate, production-shaped, p99 evidence exists; the supplied rule does not define the qualifying p99 result."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"},{"claim":"The evidence does not establish whether that earlier build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":"pilot_primary.txt","unknown":"Q-17's p99 latency under the required production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's p99 regression applies to Q-17."},{"source":"decision_rule.txt","unknown":"No acceptable p99 threshold or required improvement relative to the current engine is specified."}]} diff --git a/cases/software/evidence-gap/calibration/good-2/expect.json b/cases/software/evidence-gap/calibration/good-2/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-2/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good-3/artifact.json b/cases/software/evidence-gap/calibration/good-3/artifact.json new file mode 100644 index 0000000..1967d14 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-3/artifact.json @@ -0,0 +1 @@ +{"decision":"Do not replace the current engine yet; the adoption requirement is not met.","next_check":{"check":"Confirm the exact release candidate, then measure its p99 latency under the production-shaped workload.","resolves":"The missing candidate identity and p99 evidence required by the adoption rule."},"supported_facts":[{"claim":"Adoption requires evidence on the exact release candidate under a production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"unknown":"Whether prototype Q-17 is the exact release candidate."},{"unknown":"The release candidate's p99 latency under the production-shaped workload."},{"unknown":"Whether the earlier build's p99 regression applies to Q-17 or the release candidate."}]} diff --git a/cases/software/evidence-gap/calibration/good-3/expect.json b/cases/software/evidence-gap/calibration/good-3/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-3/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good-4/artifact.json b/cases/software/evidence-gap/calibration/good-4/artifact.json new file mode 100644 index 0000000..2862074 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-4/artifact.json @@ -0,0 +1 @@ +{"decision":"Do not replace the current engine yet; the adoption requirement is unmet.","next_check":"Run the exact release candidate, confirming whether it is Q-17, under the production-shaped workload and record p99 latency.","supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload, but the source does not establish that it matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Whether Q-17 is the exact release candidate is unknown.","source":"pilot_primary.txt"},{"claim":"Q-17's p99 latency under the production-shaped workload is unknown.","source":"pilot_primary.txt"},{"claim":"The acceptable p99 result or comparison threshold is unspecified.","source":"decision_rule.txt"}]} diff --git a/cases/software/evidence-gap/calibration/good-4/expect.json b/cases/software/evidence-gap/calibration/good-4/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-4/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good-5/artifact.json b/cases/software/evidence-gap/calibration/good-5/artifact.json new file mode 100644 index 0000000..c8c88a7 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-5/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Verify the exact release-candidate identity, then measure its p99 latency under the production-shaped workload and compare it with the current engine.","resolves":"The missing evidence required by the adoption rule."},"supported_facts":[{"claim":"Adoption requires evidence on the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload; the note does not establish that it matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Whether Q-17 is the exact release candidate."},{"claim":"Q-17's p99 latency under the production-shaped workload."},{"claim":"The pass threshold or required comparison against the current engine."}]} diff --git a/cases/software/evidence-gap/calibration/good-5/expect.json b/cases/software/evidence-gap/calibration/good-5/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-5/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good-6/artifact.json b/cases/software/evidence-gap/calibration/good-6/artifact.json new file mode 100644 index 0000000..c79ed15 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-6/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":"Identify the exact release candidate, then compare it with the current engine on the same production-shaped workload while measuring p99 latency.","supported_facts":[{"claim":"Adoption requires evidence on the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample, but tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload; the source does not establish that this build matches Q-17.","source":"pilot_counter.txt"}],"unknowns":[{"source":"pilot_primary.txt","unknown":"Whether Q-17 is the exact release candidate."},{"source":"pilot_primary.txt","unknown":"The release candidate's p99 latency under a production-shaped workload."},{"source":"pilot_counter.txt","unknown":"Whether the earlier build's 9% p99 increase applies to the release candidate."}]} diff --git a/cases/software/evidence-gap/calibration/good-6/expect.json b/cases/software/evidence-gap/calibration/good-6/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-6/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good-7/artifact.json b/cases/software/evidence-gap/calibration/good-7/artifact.json new file mode 100644 index 0000000..2533a21 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-7/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Confirm which build is the exact release candidate, execute it on a production-shaped workload, and record tail latency at p99.","resolves":"The missing candidate identity and production-shaped p99 result required by the decision rule."},"supported_facts":[{"claim":"The decision rule requires exact-candidate p99 data from a production-shaped workload and says median evidence alone is insufficient for adoption.","source":"decision_rule.txt"},{"claim":"On a 50-request synthetic sample, Q-17 reduced median latency by 18%; its tail latency was not measured.","source":"pilot_primary.txt"},{"claim":"The note says an earlier Quartz build increased p99 by 9% under a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"Exact release candidate identity for Q-17 remains unknown."},{"claim":"The production-shaped workload has no Q-17 p99 result."},{"claim":"The qualifying comparison threshold is unspecified."}]} diff --git a/cases/software/evidence-gap/calibration/good-7/expect.json b/cases/software/evidence-gap/calibration/good-7/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good-7/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/calibration/good/artifact.json b/cases/software/evidence-gap/calibration/good/artifact.json new file mode 100644 index 0000000..ea629f9 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good/artifact.json @@ -0,0 +1 @@ +{"decision":"do_not_replace_yet","next_check":{"check":"Identify the exact release candidate, then run it under the production-shaped workload and measure p99 latency.","resolves":"Whether the required release-candidate, production-shaped, tail-latency evidence exists; the supplied evidence still lacks an acceptance threshold for interpreting the measured p99."},"supported_facts":[{"claim":"Adoption requires evidence for the exact release candidate under the production-shaped workload, including p99 latency; median-only evidence is insufficient.","source":"decision_rule.txt"},{"claim":"Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample.","source":"pilot_primary.txt"},{"claim":"Tail latency was not measured for Q-17.","source":"pilot_primary.txt"},{"claim":"An earlier Quartz build increased p99 latency by 9% on a bursty workload.","source":"pilot_counter.txt"}],"unknowns":[{"claim":"It is unknown whether Q-17 is the exact release candidate.","source":"pilot_primary.txt"},{"claim":"Q-17's p99 latency under the production-shaped workload is unknown.","source":"pilot_primary.txt"},{"claim":"No p99 acceptance threshold beyond requiring its measurement is supplied.","source":"decision_rule.txt"}]} diff --git a/cases/software/evidence-gap/calibration/good/expect.json b/cases/software/evidence-gap/calibration/good/expect.json new file mode 100644 index 0000000..4071f78 --- /dev/null +++ b/cases/software/evidence-gap/calibration/good/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/evidence-gap/fixture/decision_rule.txt b/cases/software/evidence-gap/fixture/decision_rule.txt new file mode 100644 index 0000000..95bfca3 --- /dev/null +++ b/cases/software/evidence-gap/fixture/decision_rule.txt @@ -0,0 +1 @@ +Adoption requires evidence on the exact release candidate under the production-shaped workload, including p99 latency. Median-only evidence is insufficient. diff --git a/cases/software/evidence-gap/fixture/pilot_counter.txt b/cases/software/evidence-gap/fixture/pilot_counter.txt new file mode 100644 index 0000000..081c7de --- /dev/null +++ b/cases/software/evidence-gap/fixture/pilot_counter.txt @@ -0,0 +1 @@ +An earlier Quartz build increased p99 latency by 9% on a bursty workload. The note does not establish whether that build matches release candidate Q-17. diff --git a/cases/software/evidence-gap/fixture/pilot_primary.txt b/cases/software/evidence-gap/fixture/pilot_primary.txt new file mode 100644 index 0000000..d037df9 --- /dev/null +++ b/cases/software/evidence-gap/fixture/pilot_primary.txt @@ -0,0 +1 @@ +Quartz prototype Q-17 reduced median latency by 18% on a 50-request synthetic sample. Tail latency was not measured. diff --git a/cases/software/evidence-gap/oracle/verify.py b/cases/software/evidence-gap/oracle/verify.py new file mode 100644 index 0000000..f88a6a1 --- /dev/null +++ b/cases/software/evidence-gap/oracle/verify.py @@ -0,0 +1,233 @@ +from __future__ import annotations + +import os +import re +import sys + + +sys.path.insert(0, os.environ["EVAL_SHARED_ROOT"]) + +from final_output import ( # noqa: E402 + agent_workspace_unchanged, + assertion, + emit, + flatten_text, + read_artifact, +) + + +EXPECTED_KEYS = {"decision", "supported_facts", "unknowns", "next_check"} +ALLOWED_SOURCES = {"decision_rule.txt", "pilot_primary.txt", "pilot_counter.txt"} +DECISION_PATTERN = ( + r"(?:do_not_replace_yet|do not replace the current engine yet(?:; the adoption " + r"requirement is (?:not met|unmet))?)" +) + + +def grounded_fact(source: str, claim: str) -> bool: + if source == "decision_rule.txt": + return bool( + re.search(r"\badoption\b", claim) + and re.search(r"\brequires?\b", claim) + and re.search(r"\bexact(?:-| )candidate|exact release candidate\b", claim) + and "production-shaped" in claim + and "p99" in claim + and "median" in claim + and "insufficient" in claim + and "without production-shaped p99" not in claim + ) + if source == "pilot_primary.txt": + unsupported = re.search( + r"\b(?:increased median|proves?|safe for|every production|memory)\b", claim + ) + median_result = all( + token in claim + for token in ("q-17", "reduced", "median", "18%", "50-request") + ) + tail_gap = ( + "q-17" in claim + and "tail latency" in claim + and re.search(r"\bnot measured\b", claim) + ) + return unsupported is None and bool(median_result or tail_gap) + if source == "pilot_counter.txt": + regression = all( + token in claim for token in ("earlier", "build", "increased", "p99", "9%") + ) + identity_gap = bool( + "earlier build" in claim + and "q-17" in claim + and re.search(r"\b(?:unknown|does not establish|not establish)\b", claim) + ) + return regression or identity_gap + return False + + +def material_unknown(claim: str) -> bool: + if re.search( + r"\b(?:known|benchmarked|available|identical|definitely|should replace|meets)\b|" + r"\bidentity matches\b", + claim, + ): + return False + candidate_identity = ( + "q-17" in claim + and "release candidate" in claim + and re.search(r"\b(?:whether|identity|matches|exact)\b", claim) + ) + production_p99 = "p99" in claim and "production-shaped" in claim + earlier_applicability = ( + "earlier build" in claim + and re.search(r"\b(?:q-17|release candidate)\b", claim) + and re.search(r"\b(?:applies|matches|identity)\b", claim) + ) + threshold_gap = "threshold" in claim or "required comparison" in claim + return bool( + candidate_identity or production_p99 or earlier_applicability or threshold_gap + ) + + +def main() -> None: + artifact = read_artifact() + values = artifact or {} + decision = flatten_text(values.get("decision", "")).lower() + facts = values.get("supported_facts") + unknowns = values.get("unknowns") + unknowns_text = flatten_text(unknowns).lower() + next_check_value = values.get("next_check", "") + next_check = flatten_text(next_check_value).lower() + next_check_schema = isinstance(next_check_value, str) or ( + isinstance(next_check_value, dict) + and set(next_check_value) == {"check", "resolves"} + and all(isinstance(value, str) for value in next_check_value.values()) + ) + + fact_objects = ( + facts + if isinstance(facts, list) + and 2 <= len(facts) <= 6 + and all( + isinstance(item, dict) + and set(item) == {"source", "claim"} + and isinstance(item.get("claim"), str) + for item in facts + ) + else [] + ) + fact_claims = [ + ( + item.get("source"), + flatten_text(item.get("claim", "")).lower(), + ) + for item in fact_objects + ] + sources = {source for source, _claim in fact_claims if isinstance(source, str)} + source_text = { + source: " ".join( + claim for claim_source, claim in fact_claims if claim_source == source + ) + for source in ALLOWED_SOURCES + } + attributed_facts = all( + claim + and isinstance(source, str) + and source in ALLOWED_SOURCES + and grounded_fact(source, claim.rstrip(". ")) + for source, claim in fact_claims + ) + balanced_facts = ( + bool(fact_objects) + and attributed_facts + and sources == ALLOWED_SOURCES + and all( + token in source_text["decision_rule.txt"] + for token in ("production", "p99", "median") + ) + and all( + token in source_text["pilot_primary.txt"] + for token in ("18%", "median", "tail") + ) + and all(token in source_text["pilot_counter.txt"] for token in ("9%", "p99")) + ) + material_unknowns = ( + isinstance(unknowns, list) + and 2 <= len(unknowns) <= 4 + and all( + isinstance(item, dict) + and set(item) + in ( + {"claim"}, + {"unknown"}, + {"claim", "source"}, + {"unknown", "source"}, + ) + and ( + "source" not in item + or ( + isinstance(item["source"], str) + and item["source"] in ALLOWED_SOURCES + ) + ) + and isinstance(item.get("claim", item.get("unknown")), str) + and material_unknown( + flatten_text(item.get("claim", item.get("unknown", ""))) + .lower() + .rstrip(". ") + ) + for item in unknowns + ) + and "p99" in unknowns_text + and "production" in unknowns_text + and any(token in unknowns_text for token in ("q-17", "release candidate")) + and any(word in unknowns_text for word in ("whether", "identity", "matches")) + ) + resolving_check = bool( + re.search( + r"\b(?:run|identify|confirm|verify|measure|record|compare)\b", next_check + ) + and re.search( + r"\b(?:exact(?:-| )release(?:-| )candidate|exact(?:-| )candidate|q-17)\b", + next_check, + ) + and "production-shaped" in next_check + and re.search(r"\b(?:p99|tail latency)\b", next_check) + and not re.search(r"\b(?:do not|refuse|median-only)\b", next_check) + ) + restrained = ( + artifact is not None + and set(artifact) == EXPECTED_KEYS + and isinstance(values.get("decision"), str) + and re.fullmatch(DECISION_PATTERN, decision.rstrip(". ")) is not None + and sources <= ALLOWED_SOURCES + and next_check_schema + and agent_workspace_unchanged() + ) + + emit( + [ + assertion( + "balanced-source-facts", + balanced_facts, + "facts cover the primary median result and p99 counter-evidence", + ), + assertion( + "material-uncertainty", + material_unknowns, + "unknowns preserve production p99 and release identity gaps", + ), + assertion( + "decision-resolving-check", + resolving_check, + "next check measures exact-candidate p99 on production-shaped load", + ), + assertion( + "research-output-restraint", + restrained, + "decision is evidence-bounded, exact-schema, and read-only", + ), + ] + ) + + +if __name__ == "__main__": + main() diff --git a/cases/software/evidence-gap/prompt.md b/cases/software/evidence-gap/prompt.md new file mode 100644 index 0000000..4f3fa10 --- /dev/null +++ b/cases/software/evidence-gap/prompt.md @@ -0,0 +1 @@ +Using only the supplied evidence, decide whether Engine Quartz should replace the current engine. Do not guess, import outside facts, or turn uncertainty into a confidence score. Return only one JSON object with exactly `decision`, `supported_facts`, `unknowns`, and `next_check`. Represent each supported fact as a source-and-claim object, include material counter-evidence, distinguish what the sources establish from what remains unknown, and propose the narrowest check that could resolve the decision rule. diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/artifact.json new file mode 100644 index 0000000..dd42cd0 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`." + ], + "root_cause": "The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0); expect ok, but the actual result is retry." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/contradictory-verification-result/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/artifact.json new file mode 100644 index 0000000..4c64c8d --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/artifact.json @@ -0,0 +1 @@ +{"verdict":"failed","root_cause":"The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.","evidence":["failure.log:2","worker.py:2-3"],"verification":"Run outcome(0) in the supplied worker module; expect `ok`.","unverified":"The broader test suite is not missing, and all behavior is verified."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/expect.json new file mode 100644 index 0000000..d5f77fd --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/denied-gap/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["concrete-root-cause","minimal-line-evidence","diagnostic-report-restraint"],"must_fail":["reproducible-verification-check"]} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/artifact.json new file mode 100644 index 0000000..8e6fd60 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Executed no check; outcome(0) was not observed = unknown.", + "unverified": "No actual verification was performed." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/empty-execution/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/artifact.json new file mode 100644 index 0000000..6848ce8 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`." + ], + "root_cause": "The >= 0 condition excludes zero; outcome(0) returns ok.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0); expect ok." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/excluded-zero/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/artifact.json new file mode 100644 index 0000000..44d0164 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/artifact.json @@ -0,0 +1,11 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Run outcome(0) in the supplied worker module; expect `ok`.", + "unverified": "No broader behavior specification or test suite was supplied.", + "remediation": "Rewrite the retry system." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/expect.json new file mode 100644 index 0000000..37200d5 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/extra-field/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check" + ], + "must_fail": [ + "diagnostic-report-restraint" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/artifact.json new file mode 100644 index 0000000..9b4cc51 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`." + ], + "root_cause": "The >= 0 comparison is false, so attempts=0 returns ok.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0); expect ok." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/false-bound-relation/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/artifact.json new file mode 100644 index 0000000..8cb0c18 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "I did not directly inspect the files or perform any check.", + "unverified": "No broader behavior specification or test suite was supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/intervening-negation/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/artifact.json new file mode 100644 index 0000000..3037d9e --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log", + "worker.py:2-3" + ], + "verification": "Run outcome(0) in the supplied worker module; expect `ok`.", + "unverified": "No broader behavior specification or test suite was supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/expect.json new file mode 100644 index 0000000..ab241b9 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/missing-line/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "minimal-line-evidence" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/artifact.json new file mode 100644 index 0000000..61a57fd --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 is irrelevant.", + "worker.py:2 does not contain the causal line." + ], + "root_cause": "The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0) in the supplied worker module; expect `ok`." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/expect.json new file mode 100644 index 0000000..ab241b9 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-evidence-claims/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "minimal-line-evidence" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/artifact.json new file mode 100644 index 0000000..9270cd2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`." + ], + "root_cause": "The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0); expect definitely not ok." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-expected-result/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/artifact.json new file mode 100644 index 0000000..a7ef7bb --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`." + ], + "root_cause": "The >= 0 condition does not include zero; outcome(0) returns ok.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed", + "verification": "Run outcome(0); expect ok." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-inclusive-relation/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/artifact.json new file mode 100644 index 0000000..9b4d6a4 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2-3"],"root_cause":"The condition attempts >= 0 includes zero, but attempts=0 never returns ok; it returns retry.","unverified":"The original check command and broader test suite were not supplied.","verdict":"failed","verification":"Run outcome(0) in the supplied worker module; expect `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/expect.json new file mode 100644 index 0000000..b14f6b6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-observed-branch/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["minimal-line-evidence","reproducible-verification-check","diagnostic-report-restraint"],"must_fail":["concrete-root-cause"]} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/artifact.json new file mode 100644 index 0000000..68e9da6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2 reports expected `retry` and observed `ok` for attempts=0.","worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`."],"root_cause":"The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.","unverified":"The original check command and broader test suite were not supplied.","verdict":"not failed; there is no bug at zero","verification":"Run outcome(0) in the supplied worker module; expect `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/expect.json new file mode 100644 index 0000000..b14f6b6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verdict/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["minimal-line-evidence","reproducible-verification-check","diagnostic-report-restraint"],"must_fail":["concrete-root-cause"]} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/artifact.json new file mode 100644 index 0000000..9eb83b8 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2-3"],"root_cause":"The condition attempts >= 0 includes zero, so outcome(0) returns ok instead of the expected retry.","unverified":"The original check command and broader test suite were not supplied.","verdict":"failed","verification":"Executed a check showing the statement outcome(0)=ok is false."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/expect.json new file mode 100644 index 0000000..d5f77fd --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification-result/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["concrete-root-cause","minimal-line-evidence","diagnostic-report-restraint"],"must_fail":["reproducible-verification-check"]} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/artifact.json new file mode 100644 index 0000000..178b3c0 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Not executed or reproduced; no check was performed.", + "unverified": "No broader behavior specification or test suite was supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/negated-verification/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/artifact.json new file mode 100644 index 0000000..7b3ba17 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/artifact.json @@ -0,0 +1,11 @@ +{ + "evidence": [ + "failure.log:2 reports expected `retry` and observed `ok` for attempts=0.", + "worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`.", + "Direct evaluation produced `outcome(0)=ok`; boundary values were `(-1, retry), (0, ok), (1, ok)`." + ], + "root_cause": "The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.", + "unverified": "No remaining gap; everything is fully verified.", + "verdict": "failed", + "verification": "Run outcome(0) in the supplied worker module; expect `ok`." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/no-verification-gap/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/artifact.json new file mode 100644 index 0000000..dde17bb --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2-3"],"root_cause":"The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.","unverified":"No independent test suite or broader behavior specification was supplied for other attempt values.","verdict":["failed"],"verification":"Run `python3 -c 'from worker import outcome; print(outcome(0))'`; expect output `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/expect.json new file mode 100644 index 0000000..37200d5 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/non-string-top-level/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check" + ], + "must_fail": [ + "diagnostic-report-restraint" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/artifact.json new file mode 100644 index 0000000..ca325bc --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The condition attempts >= 0 includes zero, so outcome(0) returns retry instead of the expected ok.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Run outcome(0) in the supplied worker module; expect `ok`.", + "unverified": "No production traces were supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-root-cause/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/artifact.json new file mode 100644 index 0000000..865535d --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The condition attempts >= 0 includes zero, so outcome(0) returns ok instead of the expected retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Executed outcome(0); observed retry instead of ok.", + "unverified": "No production traces were supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/reversed-verification-result/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/artifact.json new file mode 100644 index 0000000..1de7cfa --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Looks correct.", + "unverified": "Everything else is known." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/expect.json new file mode 100644 index 0000000..e343054 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/unlabeled-check/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "diagnostic-report-restraint" + ], + "must_fail": [ + "reproducible-verification-check" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/artifact.json new file mode 100644 index 0000000..0cc7bf6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2-3","This proves the system is safe for production and should be deployed immediately."],"root_cause":"The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.","unverified":"The original check command and broader test suite were not supplied.","verdict":"failed","verification":"Run outcome(0) in the supplied worker module; expect `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/expect.json new file mode 100644 index 0000000..535b261 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/unsupported-third-evidence/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["concrete-root-cause","reproducible-verification-check","diagnostic-report-restraint"],"must_fail":["minimal-line-evidence"]} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/artifact.json new file mode 100644 index 0000000..22a1df0 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/artifact.json @@ -0,0 +1,10 @@ +{ + "evidence": [ + "failure.log:2 reports expected retry and observed ok for attempts=0.", + "worker.py:2-3 routes every attempts >= 0, including 0, to ok." + ], + "root_cause": "attempts >= 0 includes zero, but outcome(0) returns retry and the condition is correct.", + "unverified": "The original check command and its broader environment were not supplied.", + "verdict": "failed because outcome(0) returns ok", + "verification": "Run outcome(0) in the supplied worker module; expect `ok`." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/verdict-masks-reversed-cause/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/apply.py b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/apply.py new file mode 100644 index 0000000..c1f6fcc --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/apply.py @@ -0,0 +1,5 @@ +from pathlib import Path +import sys + + +Path(sys.argv[1], "unauthorized.txt").write_text("mutation\n", encoding="utf-8") diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/artifact.json new file mode 100644 index 0000000..c166ca1 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "The >= 0 condition includes zero, so outcome(0) returns ok instead of retry.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Run outcome(0) in the supplied worker module; expect `ok`.", + "unverified": "No broader behavior specification or test suite was supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/expect.json new file mode 100644 index 0000000..37200d5 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/workspace-edit/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check" + ], + "must_fail": [ + "diagnostic-report-restraint" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/artifact.json b/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/artifact.json new file mode 100644 index 0000000..154ddd4 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/artifact.json @@ -0,0 +1,10 @@ +{ + "verdict": "failed", + "root_cause": "A stale cache caused the failure.", + "evidence": [ + "failure.log:2", + "worker.py:2-3" + ], + "verification": "Run outcome(0) in the supplied worker module; expect `ok`.", + "unverified": "No broader behavior specification or test suite was supplied." +} diff --git a/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/expect.json b/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/expect.json new file mode 100644 index 0000000..81d3cae --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/adversarial/wrong-cause/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [ + "concrete-root-cause" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/bad/artifact.json b/cases/software/root-cause-diagnosis/calibration/bad/artifact.json new file mode 100644 index 0000000..b1238a6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/bad/artifact.json @@ -0,0 +1,7 @@ +{ + "verdict": "unknown", + "root_cause": "Unknown.", + "evidence": [], + "verification": "Not checked.", + "unverified": "" +} diff --git a/cases/software/root-cause-diagnosis/calibration/bad/expect.json b/cases/software/root-cause-diagnosis/calibration/bad/expect.json new file mode 100644 index 0000000..675e5e1 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/bad/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [], + "must_fail": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-2/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-2/artifact.json new file mode 100644 index 0000000..d0f9717 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-2/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2-3"],"root_cause":"The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.","unverified":"No independent test suite or broader behavior specification was supplied for other attempt values.","verdict":"failed","verification":"Run `python3 -c 'from worker import outcome; print(outcome(0))'`; expect output `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-2/expect.json b/cases/software/root-cause-diagnosis/calibration/good-2/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-2/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-3/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-3/artifact.json new file mode 100644 index 0000000..cbb7e5b --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-3/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2 records expected retry but observed ok for attempts=0.","worker.py:2-3 routes every attempts >= 0, including 0, to ok."],"root_cause":"The nonnegative guard treats the initial attempt (0) as successful.","unverified":"The executable check source is not supplied; only its recorded expectation is available.","verdict":"failed","verification":"Evaluate outcome(0) in a local Python process; expect `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-3/expect.json b/cases/software/root-cause-diagnosis/calibration/good-3/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-3/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-4/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-4/artifact.json new file mode 100644 index 0000000..c008416 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-4/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2","worker.py:2"],"root_cause":"The condition treats attempts=0 as successful because >= 0 is true.","unverified":"The original check command and any broader test suite were not supplied.","verdict":"failed","verification":"Call outcome(0) from worker.py; expect the return value `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-4/expect.json b/cases/software/root-cause-diagnosis/calibration/good-4/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-4/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-5/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-5/artifact.json new file mode 100644 index 0000000..bb2e814 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-5/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2 expects retry for attempts=0 but observes ok.","worker.py:2-4 returns ok when attempts >= 0 and retry only otherwise."],"root_cause":"worker.py:2 uses an inclusive nonnegative condition, so the initial attempt enters the ok branch.","unverified":"No separate specification or test file establishes the intended behavior beyond failure.log:2.","verdict":"The check fails because attempts=0 is classified as ok.","verification":"Probe outcome(0) without editing the fixture; expect `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-5/expect.json b/cases/software/root-cause-diagnosis/calibration/good-5/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-5/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-6/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-6/artifact.json new file mode 100644 index 0000000..8a976b3 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-6/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2 reports attempts=0, expected=retry, observed=ok.","worker.py:2-3 classify nonnegative attempts as \"ok\"."],"root_cause":"Because zero satisfies attempts >= 0, the function takes the ok branch for the initial attempt rather than returning retry.","unverified":"No broader retry-boundary specification or test suite is supplied.","verdict":"The check fails because zero attempts are classified as successful.","verification":"Invoke outcome(0) in the supplied worker module; expect `ok` rather than `retry`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-6/expect.json b/cases/software/root-cause-diagnosis/calibration/good-6/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-6/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good-7/artifact.json b/cases/software/root-cause-diagnosis/calibration/good-7/artifact.json new file mode 100644 index 0000000..3cf4633 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-7/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2: attempts=0 expects retry yet records ok.","worker.py:2-3: the nonnegative guard sends attempts to ok."],"root_cause":"Zero satisfies the inclusive nonnegative guard, causing outcome(0) to take the ok branch rather than retry.","unverified":"A broader retry specification and the originating test command remain unavailable.","verdict":"failed","verification":"Invoke outcome(0) in an isolated local process; expect the return value ok."} diff --git a/cases/software/root-cause-diagnosis/calibration/good-7/expect.json b/cases/software/root-cause-diagnosis/calibration/good-7/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good-7/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/calibration/good/artifact.json b/cases/software/root-cause-diagnosis/calibration/good/artifact.json new file mode 100644 index 0000000..c1f464e --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good/artifact.json @@ -0,0 +1 @@ +{"evidence":["failure.log:2 reports expected `retry` and observed `ok` for attempts=0.","worker.py:2-3 routes all nonnegative attempts, including 0, to `\"ok\"`.","Direct evaluation produced `outcome(0)=ok`; boundary values were `(-1, retry), (0, ok), (1, ok)`."],"root_cause":"The condition `attempts >= 0` includes zero, so `outcome(0)` returns `\"ok\"` instead of the expected `\"retry\"`.","unverified":"The original check command and its broader environment were not supplied, so only the reported failure and local function behavior were verified.","verdict":"failed","verification":"Run a local assertion for outcome(0); expect the observed value `ok`."} diff --git a/cases/software/root-cause-diagnosis/calibration/good/expect.json b/cases/software/root-cause-diagnosis/calibration/good/expect.json new file mode 100644 index 0000000..a80cfb2 --- /dev/null +++ b/cases/software/root-cause-diagnosis/calibration/good/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/root-cause-diagnosis/fixture/failure.log b/cases/software/root-cause-diagnosis/fixture/failure.log new file mode 100644 index 0000000..dd818e6 --- /dev/null +++ b/cases/software/root-cause-diagnosis/fixture/failure.log @@ -0,0 +1,2 @@ +case=initial_attempt +input.attempts=0 expected=retry observed=ok diff --git a/cases/software/root-cause-diagnosis/fixture/worker.py b/cases/software/root-cause-diagnosis/fixture/worker.py new file mode 100644 index 0000000..000ba15 --- /dev/null +++ b/cases/software/root-cause-diagnosis/fixture/worker.py @@ -0,0 +1,4 @@ +def outcome(attempts): + if attempts >= 0: + return "ok" + return "retry" diff --git a/cases/software/root-cause-diagnosis/oracle/verify.py b/cases/software/root-cause-diagnosis/oracle/verify.py new file mode 100644 index 0000000..b3d4413 --- /dev/null +++ b/cases/software/root-cause-diagnosis/oracle/verify.py @@ -0,0 +1,240 @@ +from __future__ import annotations + +import os +from pathlib import Path +import re +import sys + + +sys.path.insert(0, os.environ["EVAL_SHARED_ROOT"]) + +from final_output import ( # noqa: E402 + agent_workspace_unchanged, + assertion, + emit, + flatten_text, + read_artifact, +) + + +EXPECTED_KEYS = {"verdict", "root_cause", "evidence", "verification", "unverified"} +ZERO_PATTERN = r"(?:zero|attempts?\s*=\s*0|outcome\(0\)|initial attempt(?:\s*\(?0\)?)?)" +BOUND_PATTERN = r"(?:>=\s*0|nonnegative|inclusive nonnegative)" +INCLUSIVE_RELATION_PATTERNS = ( + rf"{BOUND_PATTERN}[^.;]{{0,50}}\b(?:includes?|captures?|covers?|treats?|" + rf"classifies?)\b[^.;]{{0,40}}{ZERO_PATTERN}", + rf"{ZERO_PATTERN}[^.;]{{0,50}}\b(?:satisfies?|meets?)\b[^.;]{{0,40}}" + rf"{BOUND_PATTERN}", + rf"{BOUND_PATTERN}(?:\s+(?:condition|guard))?[, ]+\b(?:so|therefore)\b" + rf"[^.;]{{0,40}}{ZERO_PATTERN}", + rf"{ZERO_PATTERN}[^.;]{{0,50}}\bbecause\b[^.;]{{0,40}}{BOUND_PATTERN}", +) +WRONG_BRANCH_PATTERNS = ( + rf"{ZERO_PATTERN}[^.;]{{0,80}}\breturns?\s+[\"']?ok\b", + rf"{ZERO_PATTERN}[^.;]{{0,80}}\b(?:enters?|takes?)\s+(?:the\s+)?ok branch\b", + rf"\btakes?\s+(?:the\s+)?ok branch\b[^.;]{{0,80}}{ZERO_PATTERN}", + rf"{ZERO_PATTERN}[^.;]{{0,80}}\breaches?\b[^.;]{{0,40}}" + r"\breturns?\s+[\"']?ok\b", + rf"\b(?:treats?|classifies?)\b[^.;]{{0,50}}{ZERO_PATTERN}[^.;]{{0,30}}" + r"\b(?:as\s+)?(?:ok|successful)\b", +) +NEGATED_WRONG_BRANCH_PATTERN = ( + r"\b(?:never|not|doesn't|does not|isn't|is not)\b[^.;]{0,30}" + r"\b(?:return|enter|reach|take|treat|classif)\w*\b[^.;]{0,30}" + r"\b(?:ok|success\w*)\b" +) +VERDICT_PATTERNS = ( + r"failed", + r"the check fails because attempts=0 is classified as ok", + r"the check fails because zero attempts are classified as successful", +) + + +def main() -> None: + artifact = read_artifact() + values = artifact or {} + verdict = flatten_text(values.get("verdict", "")).lower() + cause = flatten_text(values.get("root_cause", "")).lower() + evidence = values.get("evidence") + evidence_items = ( + [ + flatten_text(item) + .lower() + .replace("`", "") + .replace('"', "") + .replace("'", "") + for item in evidence + ] + if isinstance(evidence, list) + else [] + ) + verification = flatten_text(values.get("verification", "")).lower() + unverified = flatten_text(values.get("unverified", "")).lower() + cause_plain = cause.replace("`", "").replace('"', "").replace("'", "") + verification_plain = verification.replace("`", "").replace('"', "").replace("'", "") + exact_schema = ( + artifact is not None + and set(artifact) == EXPECTED_KEYS + and all( + isinstance(artifact.get(field), str) + for field in ("verdict", "root_cause", "verification", "unverified") + ) + and isinstance(evidence, list) + and 2 <= len(evidence) <= 3 + and all(isinstance(item, str) for item in evidence) + ) + + inclusive_matches = [ + match + for pattern in INCLUSIVE_RELATION_PATTERNS + if (match := re.search(pattern, cause_plain)) + ] + bounded_zero = any( + not re.search(r"\b(?:no|not|never)\b", match.group()) + for match in inclusive_matches + ) + wrong_branch = any( + re.search(pattern, cause_plain) for pattern in WRONG_BRANCH_PATTERNS + ) and not re.search(NEGATED_WRONG_BRANCH_PATTERN, cause_plain) + concrete_cause = ( + any(re.fullmatch(pattern, verdict.rstrip(". ")) for pattern in VERDICT_PATTERNS) + and bounded_zero + and wrong_branch + ) + bounded_evidence = ( + isinstance(evidence, list) + and 2 <= len(evidence) <= 3 + and all(isinstance(item, str) for item in evidence) + ) + failure_matches = [] + worker_matches = [] + direct_matches = [] + for item in evidence_items: + stripped = item.strip(". ") + failure_detail = stripped.removeprefix("failure.log:2").strip(" ,;:-") + failure_matches.append( + stripped.startswith("failure.log:2") + and not re.search(r"\b(?:irrelevant|does not|not causal)\b", stripped) + and ( + not failure_detail + or ( + re.search(ZERO_PATTERN, failure_detail) + and re.search(r"\bexpect\w*\b", failure_detail) + and "retry" in failure_detail + and re.search( + r"\b(?:observed|observes|reports|records)\b", failure_detail + ) + and re.search(r"\bok\b", failure_detail) + ) + ) + ) + worker_detail = re.sub(r"^worker\.py:2(?:-[34])?", "", stripped).strip(" ,;:-") + worker_matches.append( + re.match(r"^worker\.py:2(?:-[34])?\b", stripped) is not None + and not re.search(r"\b(?:does not|not causal|irrelevant)\b", stripped) + and ( + not worker_detail + or ( + re.search(r"(?:>=\s*0|nonnegative)", worker_detail) + and re.search(r"\bok\b", worker_detail) + ) + ) + ) + direct_matches.append( + stripped.startswith("direct evaluation") + and "outcome(0)=ok" in stripped + and all( + boundary in stripped + for boundary in ("(-1, retry)", "(0, ok)", "(1, ok)") + ) + ) + line_evidence = ( + bounded_evidence + and any(failure_matches) + and any(worker_matches) + and all( + failure or worker or direct + for failure, worker, direct in zip( + failure_matches, worker_matches, direct_matches, strict=True + ) + ) + ) + verification_words = re.sub(r"[^a-z0-9()>=_-]+", " ", verification_plain) + checked = ( + re.search(r"\b(?:run|evaluate|call|invoke|probe)\b", verification_words) + and re.search(r"\boutcome\s*\(\s*0\s*\)", verification_words) + and re.search( + r"\bexpect(?:ed)?\s+(?:(?:the\s+)?" + r"(?:output|return value|observed value)\s+)?ok" + r"(?:\s+(?:rather than|not)\s+retry)?\s*$", + verification_words, + ) + and not re.search( + r"\b(?:did not|do not|never|no check|unknown|false|retry instead)\b", + verification_plain, + ) + ) + workspace = Path(os.environ["EVAL_WORKSPACE"]) + try: + worker_lines = ( + workspace.joinpath("worker.py").read_text(encoding="utf-8").splitlines() + ) + failure_lines = ( + workspace.joinpath("failure.log").read_text(encoding="utf-8").splitlines() + ) + except (OSError, UnicodeError): + fixture_grounded = False + else: + fixture_grounded = ( + len(worker_lines) >= 4 + and worker_lines[1].strip() == "if attempts >= 0:" + and worker_lines[2].strip() == 'return "ok"' + and len(failure_lines) >= 2 + and failure_lines[1].strip() + == "input.attempts=0 expected=retry observed=ok" + ) + honest_gap = bool( + re.search(r"\b(?:no|not|missing|unavailable|unknown)\b", unverified) + and re.search( + r"\b(?:broader|original|independent|separate|production|executable)\b", + unverified, + ) + and re.search( + r"\b(?:specification|suite|check|command|environment|traces?|source)\b", + unverified, + ) + and not re.search( + r"\b(?:not missing|no remaining gap|everything|all behavior)\b", + unverified, + ) + ) + restrained = exact_schema and bounded_evidence and agent_workspace_unchanged() + + emit( + [ + assertion( + "concrete-root-cause", + concrete_cause, + "diagnosis identifies the inclusive zero boundary and wrong branch", + ), + assertion( + "minimal-line-evidence", + line_evidence, + "evidence cites only the failing log line and causal code line", + ), + assertion( + "reproducible-verification-check", + bool(checked) and fixture_grounded and honest_gap, + "answer gives a reproducible check grounded by the supplied fixture", + ), + assertion( + "diagnostic-report-restraint", + restrained, + "answer is bounded to the required schema and leaves files unchanged", + ), + ] + ) + + +if __name__ == "__main__": + main() diff --git a/cases/software/root-cause-diagnosis/prompt.md b/cases/software/root-cause-diagnosis/prompt.md new file mode 100644 index 0000000..57f2e2d --- /dev/null +++ b/cases/software/root-cause-diagnosis/prompt.md @@ -0,0 +1 @@ +Diagnose the supplied failed check. This is a read-only diagnosis: do not patch code, write documentation, create a runbook, or propose a broader redesign. Return only one JSON object with exactly `verdict`, `root_cause`, `evidence`, `verification`, and `unverified`. Identify the concrete cause, cite the smallest sufficient file-and-line evidence, state one reproducible local check and its expected observation, and name any real remaining gap. diff --git a/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/artifact.json b/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/artifact.json new file mode 100644 index 0000000..a9b2c8b --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the public signature.","Do not add dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and leave may_retry's signature and logic unchanged, then alter may_retry so every attempt is rejected.","Update test_policy.py so may_retry(3) is true and may_retry(4) is false."],"verification":["python3 -m unittest -v test_policy.py","Confirm the may_retry(attempt) function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/expect.json b/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/expect.json new file mode 100644 index 0000000..65a4581 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/alter-after-preserve/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["focused-test-step","native-verification-command","proportional-plan-restraint"],"must_fail":["precise-production-step"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/artifact.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/artifact.json new file mode 100644 index 0000000..c423123 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "non_goals": [ + "Do not change the public signature.", + "Do not add dependencies, files, or configuration.", + "Do not refactor unrelated retry behavior." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.", + "Update test_policy.py so may_retry(3) is true and may_retry(4) is false.", + "Rewrite may_retry and change its signature." + ], + "verification": { + "command": "python3 -m unittest -v test_policy.py", + "expected": "test_boundary passes." + } +} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/expect.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/expect.json new file mode 100644 index 0000000..6f7d585 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-may-retry/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "precise-production-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/artifact.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/artifact.json new file mode 100644 index 0000000..20852c1 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["No new dependencies, but add requests and create config.yml.","Do not change the function signature or retry logic structure.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false."],"verification":{"command":"python -m unittest test_policy.py","expected":"Focused boundary test passes.","status":"not_run_plan_only"}} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/expect.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/expect.json new file mode 100644 index 0000000..866b3d4 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-non-goal/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["precise-production-step","focused-test-step","native-verification-command"],"must_fail":["proportional-plan-restraint"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/artifact.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/artifact.json new file mode 100644 index 0000000..c58b3dd --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the public signature.","Do not add dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.","test_policy.py: may_retry(3) is true and may_retry(4) is false are incorrect; assert may_retry(3) is false and may_retry(4) is true."],"verification":["python3 -m unittest -v test_policy.py","Confirm the may_retry(attempt) function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/expect.json b/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/expect.json new file mode 100644 index 0000000..22f1223 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/contradictory-test-step/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["precise-production-step","native-verification-command","proportional-plan-restraint"],"must_fail":["focused-test-step"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/artifact.json b/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/artifact.json new file mode 100644 index 0000000..6b05341 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "non_goals": [ + "Do not change the public signature.", + "Do not add dependencies, files, or configuration.", + "Do not refactor unrelated retry behavior." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.", + "Update test_policy.py so may_retry(3) is true and may_retry(4) is false.", + "Then edit may_retry to always return true." + ], + "verification": [ + "python3 -m unittest -v test_policy.py", + "Confirm the may_retry(attempt) function signature is unchanged." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/expect.json b/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/expect.json new file mode 100644 index 0000000..6f7d585 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/edit-may-retry/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "precise-production-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/extra-field/artifact.json b/cases/software/surgical-plan/calibration/adversarial/extra-field/artifact.json new file mode 100644 index 0000000..bc131df --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/extra-field/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "steps": [ + "In policy.py, change MAX_RETRIES from 3 to 4 and keep may_retry unchanged.", + "In test_policy.py, assert may_retry(3) is true and may_retry(4) is false." + ], + "verification": [ + "Run python3 -m unittest -v test_policy.py.", + "Confirm the may_retry(attempt) function signature is unchanged." + ], + "non_goals": [ + "No signature changes or unrelated refactors.", + "No new files or dependencies.", + "No retry logic changes beyond the constant." + ], + "rollout": "Deploy gradually." +} diff --git a/cases/software/surgical-plan/calibration/adversarial/extra-field/expect.json b/cases/software/surgical-plan/calibration/adversarial/extra-field/expect.json new file mode 100644 index 0000000..45a4c97 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/extra-field/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command" + ], + "must_fail": [ + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/artifact.json b/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/artifact.json new file mode 100644 index 0000000..72e46ee --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the public signature.","Do not add dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4, and edit may_retry while updating test_policy.py.","Update test_policy.py so may_retry(3) is true and may_retry(4) is false."],"verification":["python3 -m unittest -v test_policy.py","Confirm the may_retry(attempt) function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/expect.json b/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/expect.json new file mode 100644 index 0000000..65a4581 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/mixed-production-test-step/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["focused-test-step","native-verification-command","proportional-plan-restraint"],"must_fail":["precise-production-step"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/negated-native-command/artifact.json b/cases/software/surgical-plan/calibration/adversarial/negated-native-command/artifact.json new file mode 100644 index 0000000..7c92796 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/negated-native-command/artifact.json @@ -0,0 +1,23 @@ +{ + "level": "surgical", + "non_goals": [ + "No new files, dependencies, configuration, or tests.", + "No changes to retry logic beyond the constant value.", + "No documentation, refactoring, or broader API changes.", + "Do not edit the fixture during this planning pass." + ], + "steps": [ + { + "edit": "Change MAX_RETRIES from 3 to 4; leave may_retry's signature and logic unchanged.", + "file": "policy.py" + }, + { + "edit": "Update the focused boundary assertions so may_retry(3) is true and may_retry(4) is false.", + "file": "test_policy.py" + } + ], + "verification": [ + "Do not run python3 test_policy.py; invoking unittest is unnecessary.", + "Confirm the may_retry(attempt) function signature is unchanged." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/negated-native-command/expect.json b/cases/software/surgical-plan/calibration/adversarial/negated-native-command/expect.json new file mode 100644 index 0000000..2265de8 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/negated-native-command/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "proportional-plan-restraint" + ], + "must_fail": [ + "native-verification-command" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/artifact.json b/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/artifact.json new file mode 100644 index 0000000..36b9776 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/artifact.json @@ -0,0 +1 @@ +{"level":["surgical"],"non_goals":["Do not change the function signature or retry logic structure.","Do not modify unrelated files or add new tests.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false."],"verification":{"command":"python -m unittest test_policy.py","expected":"Focused boundary test passes.","status":"not_run_plan_only"}} diff --git a/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/expect.json b/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/expect.json new file mode 100644 index 0000000..45a4c97 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/non-string-top-level/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command" + ], + "must_fail": [ + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/old-boundary/artifact.json b/cases/software/surgical-plan/calibration/adversarial/old-boundary/artifact.json new file mode 100644 index 0000000..d57587c --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/old-boundary/artifact.json @@ -0,0 +1,16 @@ +{ + "level": "surgical", + "steps": [ + "In policy.py, change MAX_RETRIES from 3 to 4 and keep may_retry unchanged.", + "In test_policy.py, keep may_retry(2) true and may_retry(3) false." + ], + "verification": [ + "Run python3 -m unittest -v test_policy.py.", + "Confirm the may_retry(attempt) function signature is unchanged." + ], + "non_goals": [ + "No signature changes or unrelated refactors.", + "No new files or dependencies.", + "No retry logic changes beyond the constant." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/old-boundary/expect.json b/cases/software/surgical-plan/calibration/adversarial/old-boundary/expect.json new file mode 100644 index 0000000..9907024 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/old-boundary/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "focused-test-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/artifact.json b/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/artifact.json new file mode 100644 index 0000000..bf30ca3 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the public signature.","Do not add dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.","Update test_policy.py so may_retry(3) is true and may_retry(4) is false."],"verification":["python3 -c 'print(\"unittest test_policy.py\")'","Confirm the may_retry(attempt) function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/expect.json b/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/expect.json new file mode 100644 index 0000000..48162cb --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/printed-unittest-command/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["precise-production-step","focused-test-step","proportional-plan-restraint"],"must_fail":["native-verification-command"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/artifact.json b/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/artifact.json new file mode 100644 index 0000000..6ccb103 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "non_goals": [ + "No new files, dependencies, configuration, or tests.", + "No changes to retry logic beyond the constant value.", + "No documentation, refactoring, or broader API changes." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.", + "Update test_policy.py so may_retry(3) is true and may_retry(4) is false.", + "Add requests as a new dependency and create config.yml." + ], + "verification": [ + "python3 -m unittest -v test_policy.py", + "Confirm the may_retry(attempt) function signature is unchanged." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/expect.json b/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/expect.json new file mode 100644 index 0000000..d62550c --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/prohibited-additions/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command" + ], + "must_fail": [ + "precise-production-step", + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/artifact.json b/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/artifact.json new file mode 100644 index 0000000..7ff5224 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature or retry logic structure.","Do not modify unrelated files or add new tests.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false."],"verification":{"after":"Then add requests as a dependency and create config.yml","command":"python -m unittest test_policy.py","expected":"Focused boundary test passes.","status":"not_run_plan_only"}} diff --git a/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/expect.json b/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/expect.json new file mode 100644 index 0000000..866b3d4 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/prohibited-verification-metadata/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["precise-production-step","focused-test-step","native-verification-command"],"must_fail":["proportional-plan-restraint"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/artifact.json b/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/artifact.json new file mode 100644 index 0000000..5e2db7c --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the public signature.","Do not add dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry(attempt) unchanged.","Update test_policy.py so may_retry(3) is true and may_retry(4) is false.","Raise MAX_RETRIES from 4 to 100 in policy.py."],"verification":["python3 -m unittest -v test_policy.py","Confirm the may_retry(attempt) function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/expect.json b/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/expect.json new file mode 100644 index 0000000..65a4581 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/retry-limit-override/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["focused-test-step","native-verification-command","proportional-plan-restraint"],"must_fail":["precise-production-step"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/artifact.json b/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/artifact.json new file mode 100644 index 0000000..1f623bc --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "non_goals": [ + "Do not change the function signature.", + "Do not add tests, dependencies, files, or configuration.", + "Do not refactor unrelated retry behavior." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4.", + "Keep may_retry(attempt) unchanged.", + "Update test_policy.py so may_retry(3) is false and may_retry(4) is true." + ], + "verification": { + "command": "python3 -m unittest -v test_policy.py", + "expected": "test_boundary passes." + } +} diff --git a/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/expect.json b/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/expect.json new file mode 100644 index 0000000..9907024 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/reversed-boundary-results/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "focused-test-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/artifact.json b/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/artifact.json new file mode 100644 index 0000000..c7fc73e --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/artifact.json @@ -0,0 +1,17 @@ +{ + "level": "surgical", + "non_goals": [ + "Do not change the function signature.", + "Do not add dependencies, files, or configuration.", + "Do not refactor unrelated retry behavior." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 4 to MAX_RETRIES = 3.", + "Keep may_retry(attempt) unchanged.", + "Update test_policy.py so may_retry(3) is true and may_retry(4) is false." + ], + "verification": { + "command": "python3 -m unittest -v test_policy.py", + "expected": "test_boundary passes." + } +} diff --git a/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/expect.json b/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/expect.json new file mode 100644 index 0000000..6f7d585 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/reversed-production-direction/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "precise-production-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/scalar-verification/artifact.json b/cases/software/surgical-plan/calibration/adversarial/scalar-verification/artifact.json new file mode 100644 index 0000000..42f3b48 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/scalar-verification/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature or retry logic structure.","Do not modify unrelated files or add new tests.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false."],"verification":"python -m unittest test_policy.py"} diff --git a/cases/software/surgical-plan/calibration/adversarial/scalar-verification/expect.json b/cases/software/surgical-plan/calibration/adversarial/scalar-verification/expect.json new file mode 100644 index 0000000..b36ac77 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/scalar-verification/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step" + ], + "must_fail": [ + "native-verification-command", + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/artifact.json b/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/artifact.json new file mode 100644 index 0000000..4e48c71 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/artifact.json @@ -0,0 +1,16 @@ +{ + "level": "surgical", + "non_goals": [ + "Do not change the public signature.", + "Do not add dependencies, files, or configuration.", + "Do not refactor unrelated retry behavior." + ], + "steps": [ + "Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4 and keep may_retry signature unchanged but edit its logic to always return true.", + "Update test_policy.py so may_retry(3) is true and may_retry(4) is false." + ], + "verification": [ + "python3 -m unittest -v test_policy.py", + "Confirm the may_retry(attempt) function signature is unchanged." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/expect.json b/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/expect.json new file mode 100644 index 0000000..6f7d585 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/signature-only-preservation/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "precise-production-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/artifact.json b/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/artifact.json new file mode 100644 index 0000000..c77ebbf --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature or retry logic structure.","Do not modify unrelated files or add new tests.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false.","Delete policy.py and replace the service with an unrelated implementation."],"verification":{"command":"python -m unittest test_policy.py","expected":"Focused boundary test passes.","status":"not_run_plan_only"}} diff --git a/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/expect.json b/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/expect.json new file mode 100644 index 0000000..65a4581 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/unrelated-third-step/expect.json @@ -0,0 +1 @@ +{"schema_version":1,"must_pass":["focused-test-step","native-verification-command","proportional-plan-restraint"],"must_fail":["precise-production-step"]} diff --git a/cases/software/surgical-plan/calibration/adversarial/vague-production/artifact.json b/cases/software/surgical-plan/calibration/adversarial/vague-production/artifact.json new file mode 100644 index 0000000..15a032e --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/vague-production/artifact.json @@ -0,0 +1,16 @@ +{ + "level": "surgical", + "steps": [ + "Update the retry implementation while preserving behavior.", + "In test_policy.py, assert may_retry(3) is true and may_retry(4) is false." + ], + "verification": [ + "Run python3 -m unittest -v test_policy.py.", + "Confirm the may_retry(attempt) function signature is unchanged." + ], + "non_goals": [ + "No signature changes or unrelated refactors.", + "No new files or dependencies.", + "No retry logic changes beyond the constant." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/vague-production/expect.json b/cases/software/surgical-plan/calibration/adversarial/vague-production/expect.json new file mode 100644 index 0000000..6f7d585 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/vague-production/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [ + "precise-production-step" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/vague-verification/artifact.json b/cases/software/surgical-plan/calibration/adversarial/vague-verification/artifact.json new file mode 100644 index 0000000..3ffb694 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/vague-verification/artifact.json @@ -0,0 +1,16 @@ +{ + "level": "surgical", + "steps": [ + "In policy.py, change MAX_RETRIES from 3 to 4 and keep may_retry unchanged.", + "In test_policy.py, assert may_retry(3) is true and may_retry(4) is false." + ], + "verification": [ + "Run the relevant tests.", + "Confirm the may_retry(attempt) function signature is unchanged." + ], + "non_goals": [ + "No signature changes or unrelated refactors.", + "No new files or dependencies.", + "No retry logic changes beyond the constant." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/vague-verification/expect.json b/cases/software/surgical-plan/calibration/adversarial/vague-verification/expect.json new file mode 100644 index 0000000..2265de8 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/vague-verification/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "proportional-plan-restraint" + ], + "must_fail": [ + "native-verification-command" + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/workspace-edit/apply.py b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/apply.py new file mode 100644 index 0000000..c1f6fcc --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/apply.py @@ -0,0 +1,5 @@ +from pathlib import Path +import sys + + +Path(sys.argv[1], "unauthorized.txt").write_text("mutation\n", encoding="utf-8") diff --git a/cases/software/surgical-plan/calibration/adversarial/workspace-edit/artifact.json b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/artifact.json new file mode 100644 index 0000000..ecb3fb2 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/artifact.json @@ -0,0 +1,16 @@ +{ + "level": "surgical", + "steps": [ + "In policy.py, change MAX_RETRIES from 3 to 4 and keep may_retry unchanged.", + "In test_policy.py, assert may_retry(3) is true and may_retry(4) is false." + ], + "verification": [ + "Run python3 -m unittest -v test_policy.py.", + "Confirm the may_retry(attempt) function signature is unchanged." + ], + "non_goals": [ + "No signature changes or unrelated refactors.", + "No new files or dependencies.", + "No retry logic changes beyond the constant." + ] +} diff --git a/cases/software/surgical-plan/calibration/adversarial/workspace-edit/expect.json b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/expect.json new file mode 100644 index 0000000..45a4c97 --- /dev/null +++ b/cases/software/surgical-plan/calibration/adversarial/workspace-edit/expect.json @@ -0,0 +1,11 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command" + ], + "must_fail": [ + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/bad/artifact.json b/cases/software/surgical-plan/calibration/bad/artifact.json new file mode 100644 index 0000000..546b2d8 --- /dev/null +++ b/cases/software/surgical-plan/calibration/bad/artifact.json @@ -0,0 +1,8 @@ +{ + "level": "greenfield", + "steps": [ + "Redesign retries." + ], + "verification": "Review it.", + "non_goals": [] +} diff --git a/cases/software/surgical-plan/calibration/bad/expect.json b/cases/software/surgical-plan/calibration/bad/expect.json new file mode 100644 index 0000000..7faa502 --- /dev/null +++ b/cases/software/surgical-plan/calibration/bad/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [], + "must_fail": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ] +} diff --git a/cases/software/surgical-plan/calibration/good-2/artifact.json b/cases/software/surgical-plan/calibration/good-2/artifact.json new file mode 100644 index 0000000..11c5cf0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-2/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature or retry logic structure.","Do not modify unrelated files or add new tests.","Do not change retry backoff, error handling, callers, or dependencies."],"steps":["In policy.py, change MAX_RETRIES from 3 to 4; preserve may_retry(attempt) unchanged.","In test_policy.py, update test_boundary to assert may_retry(3) is true and may_retry(4) is false."],"verification":{"command":"python -m unittest test_policy.py","expected":"Focused boundary test passes.","status":"not_run_plan_only"}} diff --git a/cases/software/surgical-plan/calibration/good-2/expect.json b/cases/software/surgical-plan/calibration/good-2/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-2/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good-3/artifact.json b/cases/software/surgical-plan/calibration/good-3/artifact.json new file mode 100644 index 0000000..55f0478 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-3/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature.","Do not add tests, dependencies, files, or configuration.","Do not refactor unrelated retry behavior."],"steps":["Change policy.py:1 from MAX_RETRIES = 3 to MAX_RETRIES = 4.","Keep may_retry(attempt) unchanged.","Update test_policy.py:8-9 so may_retry(3) is true and may_retry(4) is false."],"verification":{"command":"python3 -m unittest -v test_policy.py","expected":"test_boundary passes."}} diff --git a/cases/software/surgical-plan/calibration/good-3/expect.json b/cases/software/surgical-plan/calibration/good-3/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-3/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good-4/artifact.json b/cases/software/surgical-plan/calibration/good-4/artifact.json new file mode 100644 index 0000000..48368f7 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-4/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not add tests or dependencies.","Do not alter retry logic beyond the constant value.","Do not change public names, signatures, or unrelated files."],"steps":["Change `policy.py:1` from `MAX_RETRIES = 3` to `MAX_RETRIES = 4`; leave `may_retry(attempt)` unchanged.","Update `test_policy.py:8-9` so `may_retry(3)` is true and `may_retry(4)` is false."],"verification":["Run `python3 -m unittest -v test_policy.py` from the fixture root; `test_boundary` must pass.","Confirm the `may_retry(attempt)` function signature is unchanged."]} diff --git a/cases/software/surgical-plan/calibration/good-4/expect.json b/cases/software/surgical-plan/calibration/good-4/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-4/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good-5/artifact.json b/cases/software/surgical-plan/calibration/good-5/artifact.json new file mode 100644 index 0000000..bb1d1ed --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-5/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["No changes to retry logic or callers.","No new dependencies, configuration, documentation, or compatibility behavior.","No fixture edits are made while producing this plan."],"steps":[{"edit":"Change MAX_RETRIES from 3 to 4; leave may_retry(attempt) unchanged.","file":"policy.py"},{"edit":"Update the focused boundary test so attempts 2 and 3 are accepted, while attempt 4 is rejected.","file":"test_policy.py"}],"verification":["Run python3 -m unittest -v test_policy.py from the fixture root; expect the boundary test to pass.","Confirm the function signature remains may_retry(attempt)."]} diff --git a/cases/software/surgical-plan/calibration/good-5/expect.json b/cases/software/surgical-plan/calibration/good-5/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-5/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good-6/artifact.json b/cases/software/surgical-plan/calibration/good-6/artifact.json new file mode 100644 index 0000000..f5977dd --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-6/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["Do not change the function signature or retry predicate structure.","Do not add files, dependencies, configuration, refactors, or broader tests.","Do not change lower-bound behavior or unrelated callers."],"steps":[{"edit":"Change only `MAX_RETRIES = 3` to `MAX_RETRIES = 4`; preserve `may_retry(attempt)` unchanged.","file":"policy.py"},{"edit":"Update `test_boundary` to assert `may_retry(3)` is true and `may_retry(4)` is false.","file":"test_policy.py"}],"verification":{"baseline":"The native command currently passes before the planned edits.","command":"python3 test_policy.py","expected":"The focused unittest passes with the updated boundary assertions."}} diff --git a/cases/software/surgical-plan/calibration/good-6/expect.json b/cases/software/surgical-plan/calibration/good-6/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-6/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good-7/artifact.json b/cases/software/surgical-plan/calibration/good-7/artifact.json new file mode 100644 index 0000000..796341e --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-7/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["No package additions or configuration changes.","Do not touch callers, the function signature, or unrelated logic."],"steps":[{"edit":"Set the retry ceiling by changing MAX_RETRIES = 3 to 4, retaining may_retry(attempt) unchanged.","file":"policy.py"},{"edit":"Revise test_boundary: may_retry(3) must be accepted and may_retry(4) rejected.","file":"test_policy.py"}],"verification":{"command":"python -m unittest test_policy","expected":"The boundary test passes."}} diff --git a/cases/software/surgical-plan/calibration/good-7/expect.json b/cases/software/surgical-plan/calibration/good-7/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good-7/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/calibration/good/artifact.json b/cases/software/surgical-plan/calibration/good/artifact.json new file mode 100644 index 0000000..4d3358e --- /dev/null +++ b/cases/software/surgical-plan/calibration/good/artifact.json @@ -0,0 +1 @@ +{"level":"surgical","non_goals":["No new files, dependencies, configuration, or tests.","No changes to retry logic beyond the constant value.","No documentation, refactoring, or broader API changes.","Do not edit the fixture during this planning pass."],"steps":[{"edit":"Change MAX_RETRIES from 3 to 4; leave may_retry's signature and logic unchanged.","file":"policy.py"},{"edit":"Update the focused boundary assertions so may_retry(3) is true and may_retry(4) is false.","file":"test_policy.py"}],"verification":{"checks":["The boundary test passes.","The function signature is unchanged.","Retry attempts below 4 remain accepted, while attempt 4 is rejected."],"command":"python3 -m unittest -v test_policy.py"}} diff --git a/cases/software/surgical-plan/calibration/good/expect.json b/cases/software/surgical-plan/calibration/good/expect.json new file mode 100644 index 0000000..121a7f0 --- /dev/null +++ b/cases/software/surgical-plan/calibration/good/expect.json @@ -0,0 +1,10 @@ +{ + "schema_version": 1, + "must_pass": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "must_fail": [] +} diff --git a/cases/software/surgical-plan/fixture/policy.py b/cases/software/surgical-plan/fixture/policy.py new file mode 100644 index 0000000..b57f769 --- /dev/null +++ b/cases/software/surgical-plan/fixture/policy.py @@ -0,0 +1,5 @@ +MAX_RETRIES = 3 + + +def may_retry(attempt): + return 0 <= attempt < MAX_RETRIES diff --git a/cases/software/surgical-plan/fixture/test_policy.py b/cases/software/surgical-plan/fixture/test_policy.py new file mode 100644 index 0000000..bdce8a1 --- /dev/null +++ b/cases/software/surgical-plan/fixture/test_policy.py @@ -0,0 +1,13 @@ +import unittest + +from policy import may_retry + + +class RetryPolicyTests(unittest.TestCase): + def test_boundary(self): + self.assertTrue(may_retry(2)) + self.assertFalse(may_retry(3)) + + +if __name__ == "__main__": + unittest.main() diff --git a/cases/software/surgical-plan/oracle/verify.py b/cases/software/surgical-plan/oracle/verify.py new file mode 100644 index 0000000..fb57a66 --- /dev/null +++ b/cases/software/surgical-plan/oracle/verify.py @@ -0,0 +1,277 @@ +from __future__ import annotations + +import os +import re +import sys + + +sys.path.insert(0, os.environ["EVAL_SHARED_ROOT"]) + +from final_output import ( # noqa: E402 + agent_workspace_unchanged, + assertion, + emit, + flatten_text, + read_artifact, +) + + +EXPECTED_KEYS = {"level", "steps", "verification", "non_goals"} + + +def main() -> None: + artifact = read_artifact() + values = artifact or {} + steps = values.get("steps") + string_steps = ( + steps + if isinstance(steps, list) + and 2 <= len(steps) <= 3 + and all(isinstance(step, str) for step in steps) + else None + ) + object_steps = ( + steps + if isinstance(steps, list) + and 2 <= len(steps) <= 3 + and all( + isinstance(step, dict) + and set(step) == {"file", "edit"} + and all(isinstance(step.get(field), str) for field in ("file", "edit")) + for step in steps + ) + else None + ) + if string_steps is not None: + step_texts = [step.lower().replace("`", "") for step in string_steps] + elif object_steps is not None: + step_texts = [ + f"{step['edit']} {step['file']}".lower().replace("`", "") + for step in object_steps + ] + else: + step_texts = [] + steps_text = " ".join(step_texts) + verification_value = values.get("verification", "") + if isinstance(verification_value, dict): + command_value = verification_value.get("command", "") + elif isinstance(verification_value, list) and verification_value: + command_value = verification_value[0] + else: + command_value = "" + command = flatten_text(command_value).lower().replace("`", "") + native_command = bool( + re.search( + r"\bpython3?\s+(?:-m\s+unittest(?:\s+-v)?\s+" + r"test_policy(?:\.py)?(?:\s+-v)?|test_policy\.py)\b", + command, + ) + and not re.search( + r"\b(?:do not|don't|never|unnecessary|skip|print|echo)\b|\s-c\s", + command, + ) + ) + if isinstance(verification_value, list): + verification_items = [ + flatten_text(item).lower().replace("`", "") for item in verification_value + ] + confirmation = verification_items[1] if len(verification_items) == 2 else "" + verification_schema = ( + len(verification_items) == 2 + and all(isinstance(item, str) for item in verification_value) + and "confirm" in confirmation + and "signature" in confirmation + and re.search(r"\b(?:unchanged|remains?)\b", confirmation) + ) + elif isinstance(verification_value, dict): + verification_keys = set(verification_value) + expected = flatten_text(verification_value.get("expected", "")).lower() + baseline = flatten_text(verification_value.get("baseline", "")).lower() + checks = verification_value.get("checks") + expected_pass = bool( + re.search(r"\b(?:test|boundary|unittest|test_boundary)\b", expected) + and re.search(r"\bpass(?:es|ed)?\b", expected) + ) + verification_schema = isinstance(verification_value.get("command"), str) and ( + ( + verification_keys + in ( + {"command", "expected"}, + {"command", "expected", "status"}, + ) + and isinstance(verification_value.get("expected"), str) + and expected_pass + and ( + "status" not in verification_value + or verification_value["status"] == "not_run_plan_only" + ) + ) + or ( + verification_keys == {"baseline", "command", "expected"} + and isinstance(verification_value.get("baseline"), str) + and isinstance(verification_value.get("expected"), str) + and re.search(r"\b(?:native|command)\b", baseline) + and re.search(r"\bpass(?:es|ed)?\b", baseline) + and re.search(r"\b(?:before|currently)\b", baseline) + and expected_pass + ) + or ( + verification_keys == {"checks", "command"} + and isinstance(checks, list) + and all(isinstance(item, str) for item in checks) + and len(checks) == 3 + and "boundary" in flatten_text(checks).lower() + and "passes" in flatten_text(checks).lower() + and "signature" in flatten_text(checks).lower() + and "unchanged" in flatten_text(checks).lower() + and "4" in flatten_text(checks) + and re.search(r"\b(?:rejected|false)\b", flatten_text(checks).lower()) + ) + ) + else: + verification_schema = False + non_goals = values.get("non_goals") + non_goals_text = flatten_text(non_goals).lower() + non_goals_schema = ( + isinstance(non_goals, list) + and 2 <= len(non_goals) <= 5 + and all(isinstance(item, str) for item in non_goals) + ) + exact_schema = ( + artifact is not None + and set(artifact) == EXPECTED_KEYS + and isinstance(artifact.get("level"), str) + and (string_steps is not None or object_steps is not None) + and verification_schema + and non_goals_schema + ) + plan_scope = f"{steps_text} {non_goals_text}" + prohibited_step = re.search( + r"\b(?:alter|edit|rewrite)\s+may_retry\b|" + r"\bmay_retry\b[^.;]{0,100}\b(?:always|every attempt)\b|" + r"\bmax_retries\b[^.;]{0,30}\b4\s+to\s+(?:3|100)\b|" + r"\b(?:add|create|delete|replace)\b[^.;]{0,40}" + r"\b(?:dependency|config|policy\.py|service)\b", + steps_text, + ) + production_steps = [step for step in step_texts if "max_retries" in step] + test_steps = [ + step + for step in step_texts + if "test_policy.py" in step + and ("may_retry(3)" in step or "attempts 2 and 3" in step) + ] + preservation_steps = [ + step + for step in step_texts + if "may_retry" in step + and re.search(r"\b(?:unchanged|preserve|leave|keep)\b", step) + ] + complete_steps = all( + step in production_steps or step in test_steps or step in preservation_steps + for step in step_texts + ) + + precise_production = ( + bool(step_texts) + and len(production_steps) == 1 + and "policy.py" in production_steps[0].replace("test_policy.py", "") + and re.search( + r"\bmax_retries\b[^.;]{0,35}\b(?:from\s+)?(?:=\s*)?3\b" + r"[^.;]{0,35}\b(?:to\s+)?(?:max_retries\s*=\s*)?4\b", + production_steps[0], + ) + and preservation_steps + and prohibited_step is None + and complete_steps + ) + focused_test = len(test_steps) == 1 and bool( + not re.search( + r"\bincorrect\b|may_retry\(3\)[^.;]{0,25}\bfalse\b|" + r"may_retry\(4\)[^.;]{0,25}\btrue\b", + test_steps[0], + ) + and ( + ( + re.search( + r"may_retry\(3\)[^.;]{0,35}\b(?:true|accepted)\b", + test_steps[0], + ) + and re.search( + r"may_retry\(4\)[^.;]{0,35}\b(?:false|rejected)\b", + test_steps[0], + ) + ) + or ( + re.search( + r"attempts?\s+2\s+and\s+3[^.;]{0,25}\baccepted\b", + test_steps[0], + ) + and re.search(r"attempt\s+4[^.;]{0,25}\brejected\b", test_steps[0]) + ) + ) + ) + bounded_non_goals = ( + non_goals_schema + and all( + isinstance(item, str) + and re.match(r"^(?:no|do not)\b", item.lower()) + and not re.search( + r"\b(?:but|then|however)\b[^.;]{0,40}" + r"\b(?:add|create|change|edit|rewrite)\b", + item.lower(), + ) + for item in non_goals + ) + and any(word in plan_scope for word in ("signature", "public", "unchanged")) + and any( + word in non_goals_text + for word in ("dependenc", "files", "configuration", "fixture") + ) + and any( + word in non_goals_text + for word in ("refactor", "unrelated", "logic", "callers") + ) + and not ( + any(action in steps_text for action in ("add ", "create ")) + and any( + target in steps_text + for target in ("dependenc", "configuration", "config.", "new file") + ) + ) + ) + restrained = ( + exact_schema + and flatten_text(values.get("level", "")).lower() == "surgical" + and bounded_non_goals + and agent_workspace_unchanged() + ) + + emit( + [ + assertion( + "precise-production-step", + precise_production, + "plan names the one constant edit and preserves may_retry", + ), + assertion( + "focused-test-step", + focused_test, + "plan updates the existing 3/4 boundary assertions", + ), + assertion( + "native-verification-command", + native_command, + "verification names an executable native unittest command", + ), + assertion( + "proportional-plan-restraint", + restrained, + "plan is surgical, bounded, exact-schema, and read-only", + ), + ] + ) + + +if __name__ == "__main__": + main() diff --git a/cases/software/surgical-plan/prompt.md b/cases/software/surgical-plan/prompt.md new file mode 100644 index 0000000..ccfdafd --- /dev/null +++ b/cases/software/surgical-plan/prompt.md @@ -0,0 +1 @@ +Write an implementation plan only; do not edit the fixture. The requested surgical change is to raise `MAX_RETRIES` from 3 to 4 while preserving the existing function signature and updating the existing focused boundary test. Return only one JSON object with exactly `level`, `steps`, `verification`, and `non_goals`. Keep the plan proportional: name the precise edits, the native test command, and explicit non-goals. diff --git a/cases/testing/_shared/final_output.py b/cases/testing/_shared/final_output.py new file mode 100644 index 0000000..3d8fca6 --- /dev/null +++ b/cases/testing/_shared/final_output.py @@ -0,0 +1,62 @@ +"""Shared contracts for objective final-output verifiers.""" + +from __future__ import annotations + +import json +import os +from pathlib import Path +from typing import Iterable + + +def _unique_object(pairs: list[tuple[str, object]]) -> dict[str, object]: + value: dict[str, object] = {} + for key, item in pairs: + if key in value: + raise ValueError(f"duplicate JSON key: {key}") + value[key] = item + return value + + +def read_artifact() -> dict[str, object] | None: + if os.environ.get("EVAL_ARTIFACT_KIND") != "final_output_json": + return None + try: + value = json.loads( + Path(os.environ["EVAL_ARTIFACT_PATH"]).read_text(encoding="utf-8"), + object_pairs_hook=_unique_object, + ) + except (KeyError, OSError, UnicodeError, ValueError): + return None + return value if isinstance(value, dict) else None + + +def flatten_text(value: object) -> str: + if isinstance(value, str): + return value + if isinstance(value, list): + return " ".join(flatten_text(item) for item in value) + if isinstance(value, dict): + return " ".join(flatten_text(item) for item in value.values()) + return "" + + +def agent_workspace_unchanged() -> bool: + return os.environ.get("EVAL_AGENT_WORKSPACE_MUTATED") == "0" + + +def assertion(identifier: str, passed: bool, evidence: str) -> dict[str, object]: + return {"id": identifier, "passed": bool(passed), "evidence": evidence} + + +def emit(assertions: Iterable[dict[str, object]]) -> None: + values = list(assertions) + print( + json.dumps( + { + "passed": all(item["passed"] is True for item in values), + "assertions": values, + "metrics": {}, + }, + sort_keys=True, + ) + ) diff --git a/cases/testing/tests/test_final_output.py b/cases/testing/tests/test_final_output.py new file mode 100644 index 0000000..ae0435c --- /dev/null +++ b/cases/testing/tests/test_final_output.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +import json +import os +from pathlib import Path +import sys +import tempfile +import unittest +from unittest.mock import patch + + +SHARED = Path(__file__).resolve().parents[1] / "_shared" +sys.path.insert(0, str(SHARED)) + +from final_output import agent_workspace_unchanged, flatten_text, read_artifact # noqa: E402 + + +class FinalOutputHelpersTests(unittest.TestCase): + def test_read_artifact_rejects_duplicate_keys(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + artifact = Path(temporary) / "artifact.json" + artifact.write_text( + '{"status":"first","status":"second"}', encoding="utf-8" + ) + environment = { + "EVAL_ARTIFACT_KIND": "final_output_json", + "EVAL_ARTIFACT_PATH": str(artifact), + } + with patch.dict(os.environ, environment, clear=True): + self.assertIsNone(read_artifact()) + + def test_read_artifact_and_flatten_text_preserve_semantics(self) -> None: + payload = { + "steps": [ + {"file": "policy.py", "edit": "raise the boundary"}, + "run the focused test", + ] + } + with tempfile.TemporaryDirectory() as temporary: + artifact = Path(temporary) / "artifact.json" + artifact.write_text(json.dumps(payload), encoding="utf-8") + environment = { + "EVAL_ARTIFACT_KIND": "final_output_json", + "EVAL_ARTIFACT_PATH": str(artifact), + } + with patch.dict(os.environ, environment, clear=True): + self.assertEqual(read_artifact(), payload) + self.assertEqual( + flatten_text(payload), + "policy.py raise the boundary run the focused test", + ) + + def test_workspace_signal_is_fail_closed(self) -> None: + for value, expected in (("0", True), ("1", False), ("false", False)): + with self.subTest(value=value): + with patch.dict( + os.environ, + {"EVAL_AGENT_WORKSPACE_MUTATED": value}, + clear=True, + ): + self.assertEqual(agent_workspace_unchanged(), expected) + with patch.dict(os.environ, {}, clear=True): + self.assertFalse(agent_workspace_unchanged()) + + +if __name__ == "__main__": + unittest.main() diff --git a/site/corpus/index.html b/site/corpus/index.html index 098d51f..81f4b8d 100644 --- a/site/corpus/index.html +++ b/site/corpus/index.html @@ -4,7 +4,7 @@ Agent Skill Evaluation Corpus | Skivolve - + @@ -13,7 +13,7 @@ - + @@ -27,7 +27,7 @@ "@context": "https://schema.org", "@type": "CollectionPage", "name": "Skivolve Agent Skill Evaluation Corpus", - "description": "A reference corpus of 17 calibrated engineering and testing cases.", + "description": "A reference corpus of 21 calibrated engineering and testing cases.", "url": "https://dhi13man.github.io/skivolve/corpus/", "isPartOf": { "@id": "https://dhi13man.github.io/skivolve/#website" } } @@ -51,7 +51,7 @@
-

Reference corpus · 17 calibrated cases

+

Reference corpus · 21 calibrated cases

Cases designed to expose weak evidence.

Every case carries observable requirements, an objective verifier, explicit resource bounds, and known-good, known-bad, and adversarial variants. The corpus demonstrates the contract; it does not define Skivolve’s domain ceiling.

@@ -59,14 +59,14 @@

Cases designed to expose weak evidence.

Composition

-

Ten train cases. Seven validation cases. Two disciplines.

-

The split is fixed in the suite manifest. Engineering contributes five train and five validation cases; testing contributes five train and two validation cases.

+

Ten train cases. Eleven validation cases. Two disciplines.

+

The split is fixed in the suite manifest. Engineering contributes five train and nine validation cases; testing contributes five train and two validation cases.

-
10engineering cases
+
14engineering cases
7testing cases
10train cases
-
7validation cases
+
11validation cases
@@ -83,6 +83,10 @@

Ten train cases. Seven validation cases. Two discipli

Validation

Behavioral subtyping

Substitution contracts rather than inheritance-shaped code reuse.

Validation

Knowledge boundary

Authority, locality, and duplication decisions under change pressure.

Validation

Domain simplicity

Direct design and earned complexity for domain behavior.

+

Validation

Compatibility decision

Public-contract conflicts, migration ownership, and safe ask-before-change restraint.

+

Validation

Root-cause diagnosis

Concrete causal evidence, reproducible checks, and honest remaining gaps.

+

Validation

Surgical plan

Proportional implementation scope, precise boundaries, and native verification.

+

Validation

Evidence gap

Source-bounded decisions, material counter-evidence, and resolving next checks.

diff --git a/site/index.html b/site/index.html index 88edbcc..2e4d9d7 100644 --- a/site/index.html +++ b/site/index.html @@ -125,7 +125,7 @@

Evolve agent skills with evidence.
-
17calibrated cases
+
21calibrated cases
3artifact contracts
3 × 3comparison arms and repetitions
MITopen-source license
@@ -213,15 +213,15 @@

Evaluate the output you actually care about.

Reference corpus

-

Seventeen cases built to break weak evidence.

-

Ten engineering and seven testing cases span train and validation splits. The corpus is a reference implementation of the case contract, not the evaluator’s domain limit.

+

Twenty-one cases built to break weak evidence.

+

Fourteen engineering and seven testing cases span train and validation splits. The corpus is a reference implementation of the case contract, not the evaluator’s domain limit.

- +
Included reference corpus by track and split
TrackTrainValidationFocus
Engineering55Correctness, compatibility, security, concurrency, performance, simplicity
Engineering59Correctness, compatibility, diagnosis, planning, research, security, concurrency, performance, simplicity
Testing52Oracle sensitivity, boundary fidelity, state models, flake control, idempotency
diff --git a/skivolve/codex_app_server.py b/skivolve/codex_app_server.py index d9a82f0..d46678d 100644 --- a/skivolve/codex_app_server.py +++ b/skivolve/codex_app_server.py @@ -4400,7 +4400,7 @@ def _static_config(root: Path, model: str, reasoning_effort: str) -> bytes: "", "[shell_environment_policy]", 'inherit = "none"', - f'set = {{ PATH = {_toml_string(f"{tools}/bin:{tools}/codex-path:{tools}/codex-resources:{tools}/codex-resources/zsh/bin:{tools}/required:/usr/bin:/bin")}, HOME = {_toml_string(str(home_directory))}, LANG = "C.UTF-8", TMPDIR = {_toml_string(str(temp_directory))}, XDG_CACHE_HOME = {_toml_string(str(cache_directory))} }}', + f'set = {{ PATH = {_toml_string(f"{tools}/bin:{tools}/codex-path:{tools}/codex-resources:{tools}/codex-resources/zsh/bin:{tools}/required:/usr/bin:/bin")}, HOME = {_toml_string(str(home_directory))}, LANG = "C.UTF-8", PYTHONDONTWRITEBYTECODE = "1", TMPDIR = {_toml_string(str(temp_directory))}, XDG_CACHE_HOME = {_toml_string(str(cache_directory))} }}', "", "[permissions.eval]", 'description = "Isolated Skivolve execution"', diff --git a/skivolve/comparator-profile-authority.json b/skivolve/comparator-profile-authority.json index 7a8aefc..100ebd9 100644 --- a/skivolve/comparator-profile-authority.json +++ b/skivolve/comparator-profile-authority.json @@ -4,8 +4,8 @@ { "id": "plain-language-revision-v1", "descriptor_sha256": "60806e964d6c415d1ebb007976acedd1286a2ec6dd788442e58f345cbbd26b30", - "production_release_sha256": "94be3ed9ceb4ffe4316beef141cf8d3fa38e9aec01ae4a6ec47be3d73d444739", - "test_release_sha256": "fea628d77f9b3509dfd9c8a5b113d9bf93fed4be911aa92cdee81e948b338863", + "production_release_sha256": "da012be22caeb1c76b37b181537a8f4e061419b35c520bde6d4dce484a8c9c40", + "test_release_sha256": "fdf61ed4ff33650a28c4431b98e8553205fb0c3aafc457844efcaad6f4c0958b", "certification_contract_sha256": "48acdc90136e871ab9cea000c76f2ec94c517ed4466d6cba5beb57f5b4a9c265", "requires_live_certification": true, "authority_scope": "test" @@ -13,8 +13,8 @@ { "id": "software-engineering-v1", "descriptor_sha256": "6a166ed3a313ee145d00519382c93c9fb56223aaf9b80f29806428f53f505e35", - "production_release_sha256": "c07e78f8f5d3bd64f806ca924424c58d94753b521550c8b39bf0c51bd22efc89", - "test_release_sha256": "866e2fe4a3a1bfd53ec3c020d6583d92b746a97c4a833a0a580a5ff5ecf7808c", + "production_release_sha256": "177f65fe98ea11ca11e9f5998070ff4c5d9a5233ba362d97e43356422c6f01f0", + "test_release_sha256": "ba789cdad72490699914d2046565e8a2fc4132252e31b2d8c5e4e279ffd2554e", "certification_contract_sha256": "48acdc90136e871ab9cea000c76f2ec94c517ed4466d6cba5beb57f5b4a9c265", "requires_live_certification": true, "authority_scope": "production" diff --git a/skivolve/comparator_calibration/release.json b/skivolve/comparator_calibration/release.json index 3954158..6c4fe27 100644 --- a/skivolve/comparator_calibration/release.json +++ b/skivolve/comparator_calibration/release.json @@ -178,9 +178,9 @@ "runtime_adapter": { "id": "shared-harness-claude-cli-v1", "source_sha256": "2ace70a6a941a4078a83aa198d05b3344f5f2add72f99278182fe394de1f575c", - "harness_runner_source_sha256": "62edb2c1bb7163cf871e77bdbcccd66e8f9b771a8959d123db9ae54e628961c6", + "harness_runner_source_sha256": "17bfea40e8079f12c5e919a992edc2bc7588289d87db6036db7926ea18393aa1", "artifact_normalizer_source_sha256": "03d1895393718f4882f17b8a01347e45723b4ae634116319f746e8786ea8d688", - "provider_source_sha256": "7e79122bb2b68ec62b3fbf9239ffe0526e4f6870802fa695c3b04cee72a43729", + "provider_source_sha256": "6eae3836780ec6bd2abfeb16e04555999879253f2aa82b8319a484ed60159900", "profile_registry_source_sha256": "1582fa2eaebdf3c645f16918e2d5a62a279c176f55c1451d81aa48072b27648a", "provider_capability_registry_source_sha256": "90871a063abcd1061c4d336589667837dd2d07ecfabcb69aa642ed5db283c07e", "harness_manifest_source_sha256": "2d2924e7168a789cfa37ba513a30b4ceef28135d830127e833c7d3e1dc5c0569", diff --git a/skivolve/comparator_calibration/tests/test-release.json b/skivolve/comparator_calibration/tests/test-release.json index c3078b1..026eb1b 100644 --- a/skivolve/comparator_calibration/tests/test-release.json +++ b/skivolve/comparator_calibration/tests/test-release.json @@ -160,9 +160,9 @@ "runtime_adapter": { "id": "shared-harness-claude-cli-v1", "source_sha256": "2ace70a6a941a4078a83aa198d05b3344f5f2add72f99278182fe394de1f575c", - "harness_runner_source_sha256": "62edb2c1bb7163cf871e77bdbcccd66e8f9b771a8959d123db9ae54e628961c6", + "harness_runner_source_sha256": "17bfea40e8079f12c5e919a992edc2bc7588289d87db6036db7926ea18393aa1", "artifact_normalizer_source_sha256": "03d1895393718f4882f17b8a01347e45723b4ae634116319f746e8786ea8d688", - "provider_source_sha256": "7e79122bb2b68ec62b3fbf9239ffe0526e4f6870802fa695c3b04cee72a43729", + "provider_source_sha256": "6eae3836780ec6bd2abfeb16e04555999879253f2aa82b8319a484ed60159900", "profile_registry_source_sha256": "1582fa2eaebdf3c645f16918e2d5a62a279c176f55c1451d81aa48072b27648a", "provider_capability_registry_source_sha256": "90871a063abcd1061c4d336589667837dd2d07ecfabcb69aa642ed5db283c07e", "harness_manifest_source_sha256": "2d2924e7168a789cfa37ba513a30b4ceef28135d830127e833c7d3e1dc5c0569", diff --git a/skivolve/plain_language_calibration/release.json b/skivolve/plain_language_calibration/release.json index ca153cf..451d65f 100644 --- a/skivolve/plain_language_calibration/release.json +++ b/skivolve/plain_language_calibration/release.json @@ -160,9 +160,9 @@ "runtime_adapter": { "id": "shared-harness-claude-cli-v1", "source_sha256": "2ace70a6a941a4078a83aa198d05b3344f5f2add72f99278182fe394de1f575c", - "harness_runner_source_sha256": "62edb2c1bb7163cf871e77bdbcccd66e8f9b771a8959d123db9ae54e628961c6", + "harness_runner_source_sha256": "17bfea40e8079f12c5e919a992edc2bc7588289d87db6036db7926ea18393aa1", "artifact_normalizer_source_sha256": "03d1895393718f4882f17b8a01347e45723b4ae634116319f746e8786ea8d688", - "provider_source_sha256": "7e79122bb2b68ec62b3fbf9239ffe0526e4f6870802fa695c3b04cee72a43729", + "provider_source_sha256": "6eae3836780ec6bd2abfeb16e04555999879253f2aa82b8319a484ed60159900", "profile_registry_source_sha256": "1582fa2eaebdf3c645f16918e2d5a62a279c176f55c1451d81aa48072b27648a", "provider_capability_registry_source_sha256": "90871a063abcd1061c4d336589667837dd2d07ecfabcb69aa642ed5db283c07e", "harness_manifest_source_sha256": "2d2924e7168a789cfa37ba513a30b4ceef28135d830127e833c7d3e1dc5c0569", diff --git a/skivolve/plain_language_calibration/tests/test-release.json b/skivolve/plain_language_calibration/tests/test-release.json index fece2ef..1065a10 100644 --- a/skivolve/plain_language_calibration/tests/test-release.json +++ b/skivolve/plain_language_calibration/tests/test-release.json @@ -142,9 +142,9 @@ "runtime_adapter": { "id": "shared-harness-claude-cli-v1", "source_sha256": "2ace70a6a941a4078a83aa198d05b3344f5f2add72f99278182fe394de1f575c", - "harness_runner_source_sha256": "62edb2c1bb7163cf871e77bdbcccd66e8f9b771a8959d123db9ae54e628961c6", + "harness_runner_source_sha256": "17bfea40e8079f12c5e919a992edc2bc7588289d87db6036db7926ea18393aa1", "artifact_normalizer_source_sha256": "03d1895393718f4882f17b8a01347e45723b4ae634116319f746e8786ea8d688", - "provider_source_sha256": "7e79122bb2b68ec62b3fbf9239ffe0526e4f6870802fa695c3b04cee72a43729", + "provider_source_sha256": "6eae3836780ec6bd2abfeb16e04555999879253f2aa82b8319a484ed60159900", "profile_registry_source_sha256": "1582fa2eaebdf3c645f16918e2d5a62a279c176f55c1451d81aa48072b27648a", "provider_capability_registry_source_sha256": "90871a063abcd1061c4d336589667837dd2d07ecfabcb69aa642ed5db283c07e", "harness_manifest_source_sha256": "2d2924e7168a789cfa37ba513a30b4ceef28135d830127e833c7d3e1dc5c0569", diff --git a/skivolve/providers.py b/skivolve/providers.py index d40c9ef..5c15c6a 100644 --- a/skivolve/providers.py +++ b/skivolve/providers.py @@ -1512,6 +1512,7 @@ def _inner_prefix( "SHELL=/bin/bash", "TERM=dumb", "CI=1", + "PYTHONDONTWRITEBYTECODE=1", "CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1", self._unshare, "--user", diff --git a/skivolve/runner.py b/skivolve/runner.py index db46ff0..25ca2fb 100644 --- a/skivolve/runner.py +++ b/skivolve/runner.py @@ -3,6 +3,7 @@ from __future__ import annotations import concurrent.futures +import ctypes import datetime as dt import difflib import fcntl @@ -14,6 +15,7 @@ import select import shutil import stat +import struct import subprocess import tempfile import threading @@ -133,6 +135,110 @@ class _GeneratorDispatchJournalError(RunnerError): """Raised when generator dispatch accounting cannot remain trustworthy.""" +class _WorkspaceMutationMonitor: + """Observe successful write operations even when final bytes are restored.""" + + _MASK = 0x00000002 | 0x00000004 | 0x00000008 | 0x00000040 | 0x00000080 + _MASK |= 0x00000100 | 0x00000200 | 0x00000400 | 0x00000800 + _EVENT = struct.Struct("=iIII") + _PROVIDER_RUNTIME_ENTRIES = frozenset( + {".skill-eval-cache", ".skill-eval-home", ".skill-eval-tmp"} + ) + + def __init__(self, root: Path) -> None: + libc = ctypes.CDLL(None, use_errno=True) + initialize = libc.inotify_init1 + initialize.argtypes = (ctypes.c_int,) + initialize.restype = ctypes.c_int + add_watch = libc.inotify_add_watch + add_watch.argtypes = (ctypes.c_int, ctypes.c_char_p, ctypes.c_uint32) + add_watch.restype = ctypes.c_int + descriptor = initialize(os.O_CLOEXEC | os.O_NONBLOCK) + if descriptor < 0: + error = ctypes.get_errno() + raise RunnerError( + f"cannot monitor agent workspace writes: {os.strerror(error)}" + ) + self._descriptor = descriptor + self._watched_directories: dict[int, Path] = {} + try: + for current, directories, _files in os.walk(root, followlinks=False): + current_path = Path(current) + watch_descriptor = add_watch( + descriptor, + ctypes.c_char_p(os.fsencode(current_path)), + self._MASK, + ) + if watch_descriptor < 0: + error = ctypes.get_errno() + raise RunnerError( + "cannot monitor agent workspace directory " + f"{current_path}: {os.strerror(error)}" + ) + self._watched_directories[watch_descriptor] = current_path.relative_to( + root + ) + for name in directories: + path = current_path / name + if path.is_symlink() or not path.is_dir(): + raise RunnerError( + f"agent workspace contains unsafe directory: {path}" + ) + except BaseException: + self.close() + raise + + def discard_pending(self) -> None: + self._drain() + + def observed(self) -> bool: + return self._drain() + + def _drain(self) -> bool: + observed = False + while True: + try: + chunk = os.read(self._descriptor, 64 * 1024) + except BlockingIOError: + return observed + except InterruptedError: + continue + except OSError as exc: + raise RunnerError( + f"cannot read agent workspace mutation evidence: {exc}" + ) from exc + if not chunk: + raise RunnerError( + "agent workspace mutation monitor closed unexpectedly" + ) + offset = 0 + while offset < len(chunk): + if len(chunk) - offset < self._EVENT.size: + raise RunnerError("agent workspace mutation event was truncated") + watch, _mask, _cookie, name_bytes = self._EVENT.unpack_from( + chunk, offset + ) + offset += self._EVENT.size + end = offset + name_bytes + if end > len(chunk): + raise RunnerError("agent workspace mutation name was truncated") + name = os.fsdecode(chunk[offset:end].split(b"\0", 1)[0]) + offset = end + relative = self._watched_directories.get(watch) + provider_runtime_event = ( + relative is not None + and not relative.parts + and name in self._PROVIDER_RUNTIME_ENTRIES + ) + if not provider_runtime_event: + observed = True + + def close(self) -> None: + if self._descriptor >= 0: + os.close(self._descriptor) + self._descriptor = -1 + + _GENERATOR_DISPATCH_JOURNAL = "generator-dispatch.jsonl" _GENERATOR_DISPATCH_LOCK = "generator-dispatch.lock" _GENERATOR_DISPATCH_SCHEMA_VERSION = 1 @@ -1817,7 +1923,11 @@ def _preflight( selection, allow_unsealed_holdout=allow_unsealed_holdout ) self._assert_injected_fake_generator_admissible(selection, cases) - if runtime is None and self.suite.evaluation_mode != "objective_only": + if ( + runtime is None + and self.suite.evaluation_mode != "objective_only" + and not selection.verifier_only + ): runtime = self._load_comparator_runtime() generator_artifact_kinds = set( capabilities_for( @@ -1836,7 +1946,7 @@ def _preflight( "generator adapter does not support selected artifact kinds: " + ", ".join(unsupported_generator_artifacts) ) - if runtime is not None: + if runtime is not None and not selection.verifier_only: unsupported_profile_artifacts = sorted( { case.artifact_contract.kind @@ -2090,7 +2200,7 @@ def run( ) return dry_run_result runtime: ComparatorRuntime | None = None - if self.suite.evaluation_mode == "judged": + if self.suite.evaluation_mode == "judged" and not selection.verifier_only: runtime = self._load_comparator_runtime() if runtime is not None and not selection.verifier_only: assert self.suite.comparator is not None @@ -3444,12 +3554,15 @@ def _run_arm( provider_journal_state: str | None = None provider_entered = False synchronization_complete = False + workspace_mutation_observed = False + workspace_mutation_monitor: _WorkspaceMutationMonitor | None = None normalized_artifact: NormalizedArtifact | None = None stage = "fixture_copy" try: self._assert_case_integrity(case) _copy_tree(case.fixture_dir, workspace, ignore_generated_caches=True) before = _read_tree(workspace, ignore_generated_caches=True) + before_permissions = _read_tree_permissions(workspace) hashes["fixture_before_sha256"] = _states_hash(before) stage = "source_materialization" source = self._materialize_source(variant, case, temp_root / "source") @@ -3457,7 +3570,7 @@ def _run_arm( hashes["context_sha256"] = source.context_hash system_context = _system_context(case, source) - def account_dispatch() -> None: + def account_dispatch(*, provider_callback: bool = True) -> None: if provider_attempt_id is None: raise _GeneratorDispatchJournalError( "generator dispatch callback preceded durable planning" @@ -3467,6 +3580,8 @@ def account_dispatch() -> None: raise _GeneratorDispatchJournalError( "generator dispatch ledger was not initialized" ) + if provider_callback and workspace_mutation_monitor is not None: + workspace_mutation_monitor.discard_pending() ledger.mark_dispatched(provider_attempt_id) provider_dispatched.set() @@ -3518,11 +3633,13 @@ def account_dispatch() -> None: provider_window["started"] = time.monotonic() synchronization_complete = True stage = "agent" + if case.artifact_contract.kind != "workspace_diff": + workspace_mutation_monitor = _WorkspaceMutationMonitor(workspace) try: provider_entered = True provider_result = self.agent_provider.run_agent(request) if not provider_dispatched.is_set(): - account_dispatch() + account_dispatch(provider_callback=False) provider_journal_state = "dispatched" if case.artifact_contract.kind != "workspace_diff": stage = "artifact_normalization" @@ -3547,6 +3664,13 @@ def account_dispatch() -> None: provider_journal_state = "completed" finally: provider_window["finished"] = time.monotonic() + if workspace_mutation_monitor is not None: + try: + workspace_mutation_observed = ( + workspace_mutation_monitor.observed() + ) + finally: + workspace_mutation_monitor.close() if source is not None and source.snapshot is not None: _make_tree_writable(source.snapshot) hashes["agent_output_sha256"] = _sha256( @@ -3557,6 +3681,13 @@ def account_dispatch() -> None: ) stage = "agent_workspace_scan" after_agent = _read_tree(workspace, ignore_generated_caches=True) + after_agent_mutation = _read_tree(workspace) + after_agent_permissions = _read_tree_permissions(workspace) + agent_workspace_mutated = ( + before != after_agent_mutation + or before_permissions != after_agent_permissions + or workspace_mutation_observed + ) hashes["workspace_after_agent_sha256"] = _states_hash(after_agent) diff_text = _diff_states(before, after_agent) hashes["diff_sha256"] = _sha256(diff_text.encode("utf-8")) @@ -3588,6 +3719,7 @@ def account_dispatch() -> None: normalized_artifact, result_root, workspace_read_only=final_output_artifact, + agent_workspace_mutated=agent_workspace_mutated, ) verifier_after_hash = _tree_hash(verifier_workspace) verifier_json["workspace_before_sha256"] = verifier_before_hash @@ -3798,6 +3930,7 @@ def _run_verifier( result_root: Path, *, workspace_read_only: bool, + agent_workspace_mutated: bool, ) -> dict[str, Any]: command = self._verifier_commands.get(case.id) if command is None: @@ -3945,6 +4078,7 @@ def _run_verifier( f"EVAL_ARTIFACT_PATH={mounted_artifact}", f"EVAL_ARTIFACT_KIND={artifact.kind}", f"EVAL_ARTIFACT_SHA256={artifact.sha256}", + f"EVAL_AGENT_WORKSPACE_MUTATED={int(agent_workspace_mutated)}", f"EVAL_CASE_ROOT={mounted_case}", *( [f"EVAL_SHARED_ROOT={mounted_shared}"] @@ -4001,6 +4135,7 @@ def _run_verifier( "read_only": True, }, "workspace_read_only": workspace_read_only, + "agent_workspace_mutated": agent_workspace_mutated, "go_root": str(go_root) if go_root is not None else None, "gcc_exec_prefix": ( str(gcc_exec_prefix) if gcc_exec_prefix is not None else None @@ -6104,6 +6239,7 @@ def _scan_tree( *, ignore_generated_caches: bool = False, ignore_empty_directories: bool = False, + include_directories: bool = False, ) -> list[Path]: if not root.is_dir() or root.is_symlink(): raise RunnerError(f"tree root must be a regular directory: {root}") @@ -6111,7 +6247,7 @@ def _scan_tree( return _scan_normalized_worktree( root, ignore_generated_caches=ignore_generated_caches ) - files: list[Path] = [] + paths: list[Path] = [] total = 0 entries = 0 for current, directories, filenames in os.walk(root, followlinks=False): @@ -6132,6 +6268,8 @@ def _scan_tree( f"tree exceeds maximum entries {MAX_TREE_ENTRIES}: {root}" ) retained_directories.append(name) + if include_directories: + paths.append(path) directories[:] = retained_directories for name in filenames: path = current_path / name @@ -6151,8 +6289,8 @@ def _scan_tree( total += size if total > MAX_TREE_BYTES: raise RunnerError(f"tree exceeds {MAX_TREE_BYTES} bytes: {root}") - files.append(path) - return sorted(files, key=lambda path: path.relative_to(root).as_posix()) + paths.append(path) + return sorted(paths, key=lambda path: path.relative_to(root).as_posix()) def _read_tree( @@ -6173,6 +6311,23 @@ def _read_tree( return states +def _read_tree_permissions( + root: Path, + *, + ignore_generated_caches: bool = False, +) -> dict[str, int]: + permissions = {".": stat.S_IMODE(root.stat().st_mode)} + for path in _scan_tree( + root, + ignore_generated_caches=ignore_generated_caches, + include_directories=True, + ): + permissions[path.relative_to(root).as_posix()] = stat.S_IMODE( + path.stat().st_mode + ) + return permissions + + def _copy_tree( source: Path, destination: Path, diff --git a/suite.json b/suite.json index 2744bc3..94553c2 100644 --- a/suite.json +++ b/suite.json @@ -665,6 +665,226 @@ "qualitative_bases": {} } }, + { + "id": "software-compatibility-decision", + "skill": "engineering", + "bundle_source": "skills/engineering", + "artifact_contract": { + "kind": "final_output_json" + }, + "split": "validation", + "prompt_file": "cases/software/compatibility-decision/prompt.md", + "fixture_dir": "cases/software/compatibility-decision/fixture", + "verifier": { + "argv": [ + "python3", + "cases/software/compatibility-decision/oracle/verify.py" + ], + "required_tools": [], + "timeout_seconds": 10 + }, + "context_files": [ + "skills/engineering/SKILL.md" + ], + "timeout_seconds": 180, + "critical_expectations": [ + "pointed-public-choice", + "safe-default-recommendation", + "consumer-conflict-grounding", + "ask-and-stop-restraint" + ], + "comparator_contract": { + "requirements": [ + { + "id": "pointed-public-choice", + "kind": "required_behavior", + "text": "Ask one concrete either/or question that contrasts preserving the public v3 field names with authorizing a legacy-name migration." + }, + { + "id": "safe-default-recommendation", + "kind": "required_behavior", + "text": "Recommend preserving the current v3 names until an owner decides the migration." + }, + { + "id": "consumer-conflict-grounding", + "kind": "required_behavior", + "text": "Ground the block in North's deployed v3 dependency, South's legacy-name dependency, the public wire contract, and the missing migration owner or date." + }, + { + "id": "ask-and-stop-restraint", + "kind": "hard_constraint", + "text": "Return exactly status, question, recommendation, reason, and actions_taken; record that no change was made and leave the workspace unchanged." + } + ], + "performance_basis": null, + "qualitative_bases": {} + } + }, + { + "id": "software-root-cause-diagnosis", + "skill": "engineering", + "bundle_source": "skills/engineering", + "artifact_contract": { + "kind": "final_output_json" + }, + "split": "validation", + "prompt_file": "cases/software/root-cause-diagnosis/prompt.md", + "fixture_dir": "cases/software/root-cause-diagnosis/fixture", + "verifier": { + "argv": [ + "python3", + "cases/software/root-cause-diagnosis/oracle/verify.py" + ], + "required_tools": [], + "timeout_seconds": 10 + }, + "context_files": [ + "skills/engineering/SKILL.md" + ], + "timeout_seconds": 180, + "critical_expectations": [ + "concrete-root-cause", + "minimal-line-evidence", + "reproducible-verification-check", + "diagnostic-report-restraint" + ], + "comparator_contract": { + "requirements": [ + { + "id": "concrete-root-cause", + "kind": "required_behavior", + "text": "Identify that the inclusive nonnegative condition classifies attempts=0 as ok instead of retry." + }, + { + "id": "minimal-line-evidence", + "kind": "required_behavior", + "text": "Cite the failing observation at failure.log:2 and the causal condition at worker.py:2 using two or three bounded evidence entries." + }, + { + "id": "reproducible-verification-check", + "kind": "required_behavior", + "text": "State one reproducible local check with its expected observation, grounded by the supplied fixture, and name a real remaining gap such as the absent broader specification or test suite." + }, + { + "id": "diagnostic-report-restraint", + "kind": "hard_constraint", + "text": "Return exactly verdict, root_cause, evidence, verification, and unverified; do not patch, document, redesign, or otherwise mutate the workspace." + } + ], + "performance_basis": null, + "qualitative_bases": {} + } + }, + { + "id": "software-surgical-plan", + "skill": "engineering", + "bundle_source": "skills/engineering", + "artifact_contract": { + "kind": "final_output_json" + }, + "split": "validation", + "prompt_file": "cases/software/surgical-plan/prompt.md", + "fixture_dir": "cases/software/surgical-plan/fixture", + "verifier": { + "argv": [ + "python3", + "cases/software/surgical-plan/oracle/verify.py" + ], + "required_tools": [], + "timeout_seconds": 10 + }, + "context_files": [ + "skills/engineering/SKILL.md" + ], + "timeout_seconds": 180, + "critical_expectations": [ + "precise-production-step", + "focused-test-step", + "native-verification-command", + "proportional-plan-restraint" + ], + "comparator_contract": { + "requirements": [ + { + "id": "precise-production-step", + "kind": "required_behavior", + "text": "Plan the exact policy.py MAX_RETRIES change from 3 to 4 while preserving may_retry and its signature." + }, + { + "id": "focused-test-step", + "kind": "required_behavior", + "text": "Plan the existing test_policy.py boundary update so attempt 3 is accepted and attempt 4 is rejected." + }, + { + "id": "native-verification-command", + "kind": "required_behavior", + "text": "Name an executable Python unittest command targeting test_policy.py." + }, + { + "id": "proportional-plan-restraint", + "kind": "hard_constraint", + "text": "Return exactly level, steps, verification, and non_goals at surgical scope; add no files, dependencies, unrelated work, or workspace edits." + } + ], + "performance_basis": null, + "qualitative_bases": {} + } + }, + { + "id": "software-evidence-gap", + "skill": "engineering", + "bundle_source": "skills/engineering", + "artifact_contract": { + "kind": "final_output_json" + }, + "split": "validation", + "prompt_file": "cases/software/evidence-gap/prompt.md", + "fixture_dir": "cases/software/evidence-gap/fixture", + "verifier": { + "argv": [ + "python3", + "cases/software/evidence-gap/oracle/verify.py" + ], + "required_tools": [], + "timeout_seconds": 10 + }, + "context_files": [ + "skills/engineering/SKILL.md" + ], + "timeout_seconds": 180, + "critical_expectations": [ + "balanced-source-facts", + "material-uncertainty", + "decision-resolving-check", + "research-output-restraint" + ], + "comparator_contract": { + "requirements": [ + { + "id": "balanced-source-facts", + "kind": "required_behavior", + "text": "Represent source-and-claim facts covering Q-17's 18% median result, its missing tail measurement, and the earlier build's 9% p99 regression." + }, + { + "id": "material-uncertainty", + "kind": "required_behavior", + "text": "Keep the exact release identity and production-shaped p99 evidence as explicit unknowns." + }, + { + "id": "decision-resolving-check", + "kind": "required_behavior", + "text": "Propose measuring p99 for the exact release candidate on the production-shaped workload, optionally against the current engine." + }, + { + "id": "research-output-restraint", + "kind": "hard_constraint", + "text": "Do not recommend replacement yet; return exactly decision, supported_facts, unknowns, and next_check using only supplied sources, no confidence score, and no workspace edits." + } + ], + "performance_basis": null, + "qualitative_bases": {} + } + }, { "id": "testing-oracle-sensitivity", "skill": "testing", diff --git a/tests/run_known_good_smoke.py b/tests/run_known_good_smoke.py index d78bb24..6593854 100755 --- a/tests/run_known_good_smoke.py +++ b/tests/run_known_good_smoke.py @@ -28,11 +28,14 @@ } -def _apply_known_good(case_id: str, workspace: Path) -> None: +def _apply_known_good(case_id: str, workspace: Path) -> str: if case_id.startswith("software-"): case_directory = ( SUITE_ROOT / "cases" / "software" / case_id.removeprefix("software-") ) + artifact = case_directory / "calibration" / "good" / "artifact.json" + if artifact.is_file(): + return artifact.read_text(encoding="utf-8") apply_script = case_directory / "calibration" / "good" / "apply.py" completed = subprocess.run( [sys.executable, str(apply_script), str(workspace)], @@ -47,13 +50,14 @@ def _apply_known_good(case_id: str, workspace: Path) -> None: raise RuntimeError( f"{case_id} known-good patch failed: {completed.stderr.strip()}" ) - return + return "Applied the checked-in known-good calibration." case_directory = SUITE_ROOT / "cases" / "testing" / case_id.removeprefix("testing-") target = TEST_TARGETS[case_id] shutil.copyfile( case_directory / "calibration" / "good" / target, workspace / target, ) + return "Applied the checked-in known-good calibration." def main() -> int: @@ -68,9 +72,9 @@ def main() -> int: suite = load_suite(SUITE_ROOT / "suite.json") def agent(request): - _apply_known_good(request.case_id, request.workspace) + final_output = _apply_known_good(request.case_id, request.workspace) return { - "final_output": "Applied the checked-in known-good calibration.", + "final_output": final_output, "actual_models": [request.model], "cost_usd": 0.0, "tokens": {"input_tokens": 0, "output_tokens": 0}, diff --git a/tests/test_calibrators.py b/tests/test_calibrators.py index 69d9432..3605ab5 100644 --- a/tests/test_calibrators.py +++ b/tests/test_calibrators.py @@ -200,6 +200,61 @@ def test_good_variant_discovery_requires_executable_fixtures(self) -> None: with self.assertRaisesRegex(AssertionError, "lack apply.py"): SOFTWARE.discover_good_variants(root) + def test_final_output_variant_discovery_requires_artifacts(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + for name in ("adversarial/verbose", "bad", "good", "good-shaped"): + root.joinpath(name).mkdir(parents=True) + root.joinpath(name, "artifact.json").write_text("{}", encoding="utf-8") + self.assertEqual( + SOFTWARE.discover_good_variants(root, "final_output_json"), + ("good", "good-shaped"), + ) + self.assertEqual( + SOFTWARE.discover_variants(root, "final_output_json"), + ("adversarial/verbose", "bad", "good", "good-shaped"), + ) + root.joinpath("good-shaped", "artifact.json").unlink() + with self.assertRaisesRegex(AssertionError, "lack artifact.json"): + SOFTWARE.discover_good_variants(root, "final_output_json") + + def test_workspace_fingerprint_detects_mode_and_content_changes(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + workspace = Path(temporary) + target = workspace / "value.txt" + target.write_text("first\n", encoding="utf-8") + initial = SOFTWARE.workspace_fingerprint(workspace) + workspace.chmod(workspace.stat().st_mode | stat.S_IWGRP) + after_root_mode = SOFTWARE.workspace_fingerprint(workspace) + target.chmod(target.stat().st_mode | stat.S_IXUSR) + after_mode = SOFTWARE.workspace_fingerprint(workspace) + target.write_text("second\n", encoding="utf-8") + after_content = SOFTWARE.workspace_fingerprint(workspace) + self.assertNotEqual(initial, after_root_mode) + self.assertNotEqual(after_root_mode, after_mode) + self.assertNotEqual(after_mode, after_content) + + def test_workspace_fingerprint_frames_tree_entries(self) -> None: + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + left = root / "left" + right = root / "right" + left.mkdir() + right.mkdir() + left_file = left / "a" + right_file = right / "a" + appended_file = right / "b" + right_file.write_bytes(b"") + appended_file.write_bytes(b"") + left_file.write_bytes( + b"b" + appended_file.lstat().st_mode.to_bytes(4, "big") + b"file\0" + ) + + self.assertNotEqual( + SOFTWARE.workspace_fingerprint(left), + SOFTWARE.workspace_fingerprint(right), + ) + def test_expectation_opt_in_requires_every_variant(self) -> None: variants = ("good", "bad", "adversarial/reflection") with tempfile.TemporaryDirectory() as temporary: @@ -222,11 +277,8 @@ def test_checked_in_expectation_corpora_are_complete(self) -> None: if case["skill"] != "engineering": continue calibration_root = (SUITE_ROOT / case["prompt_file"]).parent / "calibration" - variants = tuple( - sorted( - path.parent.relative_to(calibration_root).as_posix() - for path in calibration_root.rglob("apply.py") - ) + variants = SOFTWARE.discover_variants( + calibration_root, case["artifact_contract"]["kind"] ) if any( calibration_root.joinpath(variant, "expect.json").is_file() @@ -239,10 +291,59 @@ def test_checked_in_expectation_corpora_are_complete(self) -> None: { "software-behavioral-subtyping", "software-domain-simplicity", + "software-evidence-gap", "software-knowledge-boundary", + "software-compatibility-decision", + "software-root-cause-diagnosis", "software-secure-archive-restore", + "software-surgical-plan", + }, + ) + + def test_final_output_corpora_have_shape_and_mutation_sensitivity(self) -> None: + manifest = json.loads((SUITE_ROOT / "suite.json").read_text(encoding="utf-8")) + cases = { + case["id"]: case + for case in manifest["cases"] + if case["skill"] == "engineering" + and case["artifact_contract"]["kind"] == "final_output_json" + } + self.assertEqual( + set(cases), + { + "software-compatibility-decision", + "software-evidence-gap", + "software-root-cause-diagnosis", + "software-surgical-plan", }, ) + for case_id, case in cases.items(): + with self.subTest(case_id=case_id): + calibration_root = ( + SUITE_ROOT / case["prompt_file"] + ).parent / "calibration" + self.assertEqual( + len( + SOFTWARE.discover_good_variants( + calibration_root, "final_output_json" + ) + ), + 7, + ) + isolated_failures = set() + for variant in SOFTWARE.discover_variants( + calibration_root, "final_output_json" + ): + expectation = SOFTWARE.load_expectation( + calibration_root / variant / "expect.json" + ) + self.assertIsNotNone(expectation, variant) + assert expectation is not None + if len(expectation["must_fail"]) == 1: + isolated_failures.update(expectation["must_fail"]) + self.assertEqual(isolated_failures, set(case["critical_expectations"])) + mutation = calibration_root / "adversarial/workspace-edit" + self.assertTrue(mutation.joinpath("apply.py").is_file()) def test_secure_archive_expectations_cover_every_critical_assertion(self) -> None: manifest = json.loads((SUITE_ROOT / "suite.json").read_text(encoding="utf-8")) diff --git a/tests/test_codex_app_server.py b/tests/test_codex_app_server.py index 1b8cf7a..ac5b4ab 100644 --- a/tests/test_codex_app_server.py +++ b/tests/test_codex_app_server.py @@ -5010,6 +5010,10 @@ def test_static_config_denies_credentials_and_command_network(self) -> None: self.assertIn(f'"{self.runtime / "codex-home" / "auth.json"}" = "deny"', text) self.assertIn(f'"{self.runtime / "codex-home" / "config.toml"}" = "deny"', text) self.assertIn(f'HOME = "{self.runtime / "work" / ".skill-eval-home"}"', text) + self.assertEqual( + config["shell_environment_policy"]["set"]["PYTHONDONTWRITEBYTECODE"], + "1", + ) self.assertIn(f'"{self.runtime / "work"}" = "write"', text) self.assertIn(f'"{self.runtime / "work" / ".skill-eval-tmp"}" = "write"', text) self.assertIn( diff --git a/tests/test_providers.py b/tests/test_providers.py index a231263..f7d417e 100644 --- a/tests/test_providers.py +++ b/tests/test_providers.py @@ -714,6 +714,7 @@ def test_agent_uses_safe_stateless_budgeted_command_and_captures_exact_usage( self.assertEqual(run.call_args_list[0].kwargs["timeout_seconds"], 12) inner = command[command.index("--") + 1 :] self.assertIn("CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1", inner) + self.assertIn("PYTHONDONTWRITEBYTECODE=1", inner) def test_comparator_delegates_canonical_bytes_to_shared_runtime(self) -> None: provider = ClaudeCliProvider(self.config()) diff --git a/tests/test_runner.py b/tests/test_runner.py index 9bcc9c9..88c8aa0 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -2903,6 +2903,28 @@ def test_verifier_runs_in_disposable_copy_and_cannot_contaminate_agent_diff( self.assertTrue(arm["verifier"]["workspace_mutated"]) self.assertNotIn("verifier-created.txt", arm["diff"]) + def test_workspace_diff_excludes_generated_agent_caches(self) -> None: + provider = self.fixture.provider() + original_handler = provider._agent_handler + + def create_cache(request): + result = original_handler(request) + cache = request.workspace / "__pycache__" + cache.mkdir() + (cache / "note.pyc").write_bytes(b"generated cache") + return result + + provider._agent_handler = create_cache + result = self.runner(provider).run( + RunSelection(comparison_ids=("without-current",)), + output_dir=self.output("agent-cache-diff"), + ) + + self.assertTrue(result["passed"], result) + for arm in result["pairs"][0]["arms"].values(): + self.assertTrue(arm["verifier"]["sandbox"]["agent_workspace_mutated"]) + self.assertNotIn("__pycache__", arm["diff"]) + def test_run_when_artifact_is_final_text_keeps_workspace_read_only(self) -> None: # Arrange self.fixture.use_objective() @@ -3038,6 +3060,7 @@ def test_run_when_artifact_is_final_json_completes_without_comparator(self) -> N passed = ( content == b'{"a":1,"b":2}' and os.environ["EVAL_ARTIFACT_KIND"] == "final_output_json" + and os.environ["EVAL_AGENT_WORKSPACE_MUTATED"] == "1" and os.environ["EVAL_ARTIFACT_SHA256"] == hashlib.sha256(content).hexdigest() and (workspace / "input.txt").read_text(encoding="utf-8") == "original\\n" and not (workspace / "poison.txt").exists() @@ -3085,8 +3108,117 @@ def json_output(request): ) self.assertTrue(arm["verifier"]["artifact"]["read_only"]) self.assertTrue(arm["verifier"]["sandbox"]["workspace_read_only"]) + self.assertTrue(arm["verifier"]["sandbox"]["agent_workspace_mutated"]) self.assertFalse(arm["verifier"]["workspace_mutated"]) + def test_final_output_mutation_signal_covers_all_workspace_entries( + self, + ) -> None: + self.fixture.use_objective(artifact_kind="final_output_json") + self.fixture.set_verifier( + """import json +import os + +passed = os.environ["EVAL_AGENT_WORKSPACE_MUTATED"] == "1" +print(json.dumps({ + "passed": passed, + "assertions": [{ + "id": "answer-present", + "passed": passed, + "evidence": "agent workspace mutation signal", + }], + "metrics": {}, +})) +""" + ) + self.fixture.save_manifest() + + def create_empty_directory(workspace: Path) -> None: + (workspace / "empty").mkdir() + + def remove_owner_write_permission(workspace: Path) -> None: + (workspace / "input.txt").chmod(0o444) + + def create_cache_file(workspace: Path) -> None: + cache = workspace / "__pycache__" + cache.mkdir() + (cache / "note.txt").write_text("agent-created\n", encoding="utf-8") + + def mutate_then_restore_file(workspace: Path) -> None: + target = workspace / "input.txt" + original = target.read_bytes() + target.write_bytes(b"transient mutation\n") + target.write_bytes(original) + + mutations = ( + ("empty-directory", create_empty_directory), + ("file-permission", remove_owner_write_permission), + ("cache-file", create_cache_file), + ("transient-write", mutate_then_restore_file), + ) + for name, mutate in mutations: + with self.subTest(name=name): + + def json_output(request): + mutate(request.workspace) + return '{"a": 1}' + + result = EvalRunner( + self.load(), FakeProvider(agent_handler=json_output) + ).run( + RunSelection(comparison_ids=("without-current",)), + output_dir=self.output(f"final-json-{name}"), + ) + + self.assertTrue(result["passed"], result) + for arm in result["pairs"][0]["arms"].values(): + self.assertTrue( + arm["verifier"]["sandbox"]["agent_workspace_mutated"] + ) + + def test_final_output_without_workspace_mutation_reports_false(self) -> None: + self.fixture.use_objective(artifact_kind="final_output_json") + self.fixture.set_verifier( + """import json +import os + +passed = os.environ["EVAL_AGENT_WORKSPACE_MUTATED"] == "0" +print(json.dumps({ + "passed": passed, + "assertions": [{ + "id": "answer-present", + "passed": passed, + "evidence": "agent workspace remained untouched", + }], + "metrics": {}, +})) +""" + ) + self.fixture.save_manifest() + + def use_provider_runtime_scratch(request): + for name in ( + ".skill-eval-cache", + ".skill-eval-home", + ".skill-eval-tmp", + ): + scratch = request.workspace / name + scratch.mkdir() + (scratch / "runtime").write_text("transient\n", encoding="utf-8") + shutil.rmtree(scratch) + return '{"a": 1}' + + result = EvalRunner( + self.load(), FakeProvider(agent_handler=use_provider_runtime_scratch) + ).run( + RunSelection(comparison_ids=("without-current",)), + output_dir=self.output("final-json-no-mutation"), + ) + + self.assertTrue(result["passed"], result) + for arm in result["pairs"][0]["arms"].values(): + self.assertFalse(arm["verifier"]["sandbox"]["agent_workspace_mutated"]) + def test_preflight_when_final_output_is_judged_requires_calibrated_profile( self, ) -> None: @@ -3104,6 +3236,15 @@ def test_preflight_when_final_output_is_judged_requires_calibrated_profile( self.assertEqual(provider.agent_requests, []) self.assertEqual(provider.comparator_requests, []) + verifier_only = runner.preflight( + RunSelection( + comparison_ids=("without-current",), + verifier_only=True, + ) + ) + self.assertEqual(verifier_only["execution_mode"], "verifier_only") + self.assertIsNone(verifier_only["comparator"]) + # Arrange for case in self.fixture.manifest["cases"]: case["artifact_contract"] = {"kind": "workspace_diff"} @@ -3381,6 +3522,7 @@ def hidden(path): "EVAL_ARTIFACT_PATH", "EVAL_ARTIFACT_KIND", "EVAL_ARTIFACT_SHA256", + "EVAL_AGENT_WORKSPACE_MUTATED", "EVAL_CASE_ROOT", "EVAL_TOOL_BIN", "EVAL_RESULT_ROOT", @@ -8051,9 +8193,9 @@ def test_gcc_attestation_includes_derived_driver_closure(self) -> None: def test_manifest_is_loadable_and_public_cases_are_not_holdouts(self) -> None: suite = load_suite(HARNESS_ROOT / "suite.json") splits = [case.split for case in suite.cases] - self.assertEqual(len(suite.cases), 17) + self.assertEqual(len(suite.cases), 21) self.assertEqual(splits.count("train"), 10) - self.assertEqual(splits.count("validation"), 7) + self.assertEqual(splits.count("validation"), 11) self.assertNotIn("holdout", splits) def test_models_and_frozen_original_are_pinned(self) -> None: