From 2fffbc9fe7117a3d4c8c1350a07136939408cdde Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:47:23 +0200 Subject: [PATCH 1/5] Stage verified run 27 evidence objects for reviewed qualification closure --- .github/workflows/stage-run27-evidence.yml | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 .github/workflows/stage-run27-evidence.yml diff --git a/.github/workflows/stage-run27-evidence.yml b/.github/workflows/stage-run27-evidence.yml new file mode 100644 index 0000000..78e3a9e --- /dev/null +++ b/.github/workflows/stage-run27-evidence.yml @@ -0,0 +1,138 @@ +name: Stage verified run 27 evidence +on: + push: + branches: [chore/record-qualified-run27] + paths: [.github/workflows/stage-run27-evidence.yml] +permissions: + contents: write + actions: read +jobs: + stage: + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + PYTHONDONTWRITEBYTECODE: '1' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + fetch-depth: 2 + persist-credentials: false + - name: Verify and stage exact full-run evidence without updating refs + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + python3 - <<'PY' + import base64, concurrent.futures, hashlib, json, os, shutil, subprocess, sys, zipfile + from pathlib import Path + sys.path.insert(0, str(Path('tools').resolve())) + from qualification_artifact import verify_archive + from qualification_closure import closure_blockers + from validate_capabilities import validate_all + source = 'a9cdcdc1e0cad70e88b60869e75e4166046dd306' + run_id = '34140846679' + artifact_id = 10026707683 + temp = Path(os.environ['RUNNER_TEMP']) + def git(*args): + return subprocess.check_output(['git', *args], text=True).strip() + def api(endpoint, payload=None): + args = ['gh', 'api', 'repos/KeyffMS/PlanAnvil/' + endpoint] + if payload is not None: + args += ['--method', 'POST', '--input', '-'] + result = subprocess.run(args, input=json.dumps(payload) if payload is not None else None, + text=True, capture_output=True, check=True) + return json.loads(result.stdout) + def digest(data): + return hashlib.sha256(data).hexdigest() + assert git('rev-parse', 'HEAD^') == source + subprocess.run(['git', 'archive', '--format=tar.gz', '--output=' + str(temp / 'run27-source.tar.gz'), source], check=True) + run = api('actions/runs/' + run_id) + assert run['head_sha'] == source and run['conclusion'] == 'success' + assert run['event'] == 'workflow_dispatch' and run['actor']['login'] == 'KeyffMS' + artifact = api('actions/artifacts/' + str(artifact_id)) + outer = subprocess.check_output(['gh', 'api', 'repos/KeyffMS/PlanAnvil/actions/artifacts/' + str(artifact_id) + '/zip']) + assert digest(outer) == '9583393745fc8292de701c51064e5569f24092e978da7164c8f50070e7d35e73' + assert artifact['digest'] == 'sha256:' + digest(outer) + outer_path = temp / 'run27-outer.zip' + outer_path.write_bytes(outer) + with zipfile.ZipFile(outer_path) as z: + assert z.namelist() == ['evidence-artifact.zip'] + inner = z.read('evidence-artifact.zip') + assert digest(inner) == '83beb50d27198c2cc0ecd72bc6ca4b1ec2d6570bcb23cc0d56c12ec97408ec75' + inner_path = temp / 'run27-inner.zip' + inner_path.write_bytes(inner) + integrity = verify_archive(inner_path) + history_before = {str(p): digest(p.read_bytes()) for p in Path('qualifications/34060321283').rglob('*') if p.is_file()} + old_index = json.loads(Path('capabilities/index.json').read_text()) + with zipfile.ZipFile(inner_path) as z: + summary_bytes = z.read('qualification-summary.json') + summary = json.loads(summary_bytes) + assert summary['source_commit'] == source and summary['github_actions_run'] == run_id + assert summary['release_gate_passed'] is True and summary['required_not_reproduced'] == [] + assert summary['results'] == {f'C{i:02d}': 'REPRODUCED' for i in range(1, 17)} + new_index = json.loads(z.read('capabilities/index.json')) + assert new_index['baseline_version'] == old_index['baseline_version'] + for old, new in zip(old_index['capabilities'], new_index['capabilities'], strict=True): + assert all(old[k] == new[k] for k in ('id', 'required', 'expected_behavior')) + for i in range(1, 17): + prefix = f'capabilities/C{i:02d}' + actual = json.loads(z.read(prefix + '/actual.sanitized.json')) + evaluation = json.loads(z.read(prefix + '/evaluation.json')) + assert actual['environment']['source_commit'] == source and actual['result'] == 'REPRODUCED' + assert evaluation['expected_met'] is True and evaluation['result'] == 'REPRODUCED' + shutil.rmtree(prefix) + for name in z.namelist(): + if name.startswith('capabilities/') and not name.endswith('/'): + target = Path(name) + target.parent.mkdir(parents=True, exist_ok=True) + target.write_bytes(z.read(name)) + folder = Path('qualifications') / run_id + folder.mkdir() + (folder / 'evidence-artifact.zip').write_bytes(inner) + (folder / 'qualification-summary.json').write_bytes(summary_bytes) + provenance = {'schema_version': '1.0', 'source_commit': source, 'github_actions_run': run_id, + 'artifact_id': artifact_id, 'outer_sha256': digest(outer), 'evidence_sha256': digest(inner), + 'integrity': integrity, 'qualification_mode': 'full', + 'limitations': ['C13 passed through the explicitly permitted project-scoped non-ephemeral fallback; ephemeral transport remains unsupported in this observed path.']} + (folder / 'provenance.json').write_text(json.dumps(provenance, indent=2, sort_keys=True) + '\n') + index = json.loads(Path('qualifications/index.json').read_text()) + assert index['baseline_run'] == '34060321283' + index.update(current_run=run_id, c08_closure='REPRODUCED') + Path('qualifications/index.json').write_text(json.dumps(index, indent=2, sort_keys=True) + '\n') + assert history_before == {str(p): digest(p.read_bytes()) for p in Path('qualifications/34060321283').rglob('*') if p.is_file()} + assert validate_all(Path('.')) == [] + assert closure_blockers(Path('.')) == [] + subprocess.run(['git', 'add', '-A', '--', 'capabilities', 'qualifications'], check=True) + subprocess.run(['git', 'rm', '.github/workflows/stage-run27-evidence.yml'], check=True) + subprocess.run(['git', 'diff', '--cached', '--check'], check=True) + names = git('diff', '--cached', '--name-only', '--diff-filter=AM').splitlines() + deleted = git('diff', '--cached', '--name-only', '--diff-filter=D').splitlines() + assert all(n.startswith(('capabilities/', 'qualifications/')) for n in names) + def store(path): + data = Path(path).read_bytes() + expected = git('hash-object', path) + result = api('git/blobs', {'content': base64.b64encode(data).decode(), 'encoding': 'base64'}) + assert result['sha'] == expected + return {'path': path, 'mode': '100644', 'type': 'blob', 'sha': expected} + with concurrent.futures.ThreadPoolExecutor(max_workers=4) as pool: + entries = list(pool.map(store, names)) + entries += [{'path': name, 'mode': '100644', 'type': 'blob', 'sha': None} for name in deleted] + result = api('git/trees', {'base_tree': git('rev-parse', 'HEAD^{tree}'), 'tree': entries}) + assert result['sha'] == git('write-tree') + subprocess.run(['git', 'archive', '--format=tar.gz', '--output=' + str(temp / 'run27-imported.tar.gz'), result['sha']], check=True) + report = {'tree': result['sha'], 'parent': git('rev-parse', 'HEAD'), 'source_commit': source, + 'changed_files': len(entries), 'integrity': integrity, 'closure_blockers': [], + 'source_archive_sha256': digest((temp / 'run27-source.tar.gz').read_bytes()), + 'imported_archive_sha256': digest((temp / 'run27-imported.tar.gz').read_bytes())} + (temp / 'run27-stage.json').write_text(json.dumps(report, indent=2, sort_keys=True) + '\n') + print(json.dumps(report, indent=2)) + PY + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f + with: + name: run27-reviewed-import-stage + path: | + ${{ runner.temp }}/run27-source.tar.gz + ${{ runner.temp }}/run27-imported.tar.gz + ${{ runner.temp }}/run27-stage.json + retention-days: 3 + if-no-files-found: error From a5c209cdf00c840182a191aeffd592d014aeb1a6 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:56:31 +0200 Subject: [PATCH 2/5] Stage exact reviewed run 27 import and documentation for final verification --- .github/workflows/stage-run27-docs.yml | 49 +++ .github/workflows/stage-run27-evidence.yml | 138 ------ .qualification-run27/update_docs.py | 165 +++++++ capabilities/C01/README.md | 4 +- capabilities/C01/actual.sanitized.json | 39 +- capabilities/C01/evaluation.json | 2 +- capabilities/C01/hashes.json | 6 +- capabilities/C02/README.md | 4 +- capabilities/C02/actual.sanitized.json | 24 +- capabilities/C02/evaluation.json | 2 +- capabilities/C02/hashes.json | 6 +- capabilities/C03/README.md | 4 +- capabilities/C03/actual.sanitized.json | 15 +- capabilities/C03/hashes.json | 4 +- capabilities/C04/README.md | 4 +- capabilities/C04/actual.sanitized.json | 31 +- capabilities/C04/evaluation.json | 2 +- capabilities/C04/hashes.json | 6 +- capabilities/C05/README.md | 4 +- capabilities/C05/actual.sanitized.json | 124 +++--- capabilities/C05/evaluation.json | 2 +- capabilities/C05/hashes.json | 6 +- capabilities/C06/README.md | 4 +- capabilities/C06/actual.sanitized.json | 30 +- capabilities/C06/hashes.json | 4 +- capabilities/C07/README.md | 4 +- capabilities/C07/actual.sanitized.json | 50 +-- capabilities/C07/evaluation.json | 2 +- capabilities/C07/hashes.json | 6 +- capabilities/C08/README.md | 4 +- capabilities/C08/actual.sanitized.json | 408 +++++++++++++++--- capabilities/C08/evaluation.json | 2 +- capabilities/C08/fixture/README.md | 18 +- capabilities/C08/fixture/c08_probe.py | 43 ++ capabilities/C08/hashes.json | 13 +- capabilities/C08/prompt.txt | 34 +- capabilities/C08/run-command.txt | 7 +- capabilities/C09/README.md | 4 +- capabilities/C09/actual.sanitized.json | 90 ++-- capabilities/C09/hashes.json | 4 +- capabilities/C10/README.md | 4 +- capabilities/C10/actual.sanitized.json | 42 +- capabilities/C10/hashes.json | 4 +- capabilities/C11/README.md | 4 +- capabilities/C11/actual.sanitized.json | 33 +- capabilities/C11/evaluation.json | 2 +- capabilities/C11/hashes.json | 6 +- capabilities/C12/README.md | 4 +- capabilities/C12/actual.sanitized.json | 16 +- capabilities/C12/hashes.json | 4 +- capabilities/C13/README.md | 4 +- capabilities/C13/actual.sanitized.json | 26 +- capabilities/C13/hashes.json | 4 +- capabilities/C14/README.md | 4 +- capabilities/C14/actual.sanitized.json | 42 +- capabilities/C14/evaluation.json | 2 +- capabilities/C14/hashes.json | 6 +- capabilities/C15/README.md | 4 +- capabilities/C15/actual.sanitized.json | 59 +-- capabilities/C15/evaluation.json | 2 +- capabilities/C15/hashes.json | 6 +- capabilities/C16/README.md | 4 +- capabilities/C16/actual.sanitized.json | 88 ++-- capabilities/C16/hashes.json | 4 +- capabilities/index.json | 8 +- .../34140846679/evidence-artifact.zip | Bin 0 -> 108211 bytes qualifications/34140846679/provenance.json | 18 + .../34140846679/qualification-summary.json | 29 ++ qualifications/index.json | 4 +- 69 files changed, 1141 insertions(+), 660 deletions(-) create mode 100644 .github/workflows/stage-run27-docs.yml delete mode 100644 .github/workflows/stage-run27-evidence.yml create mode 100644 .qualification-run27/update_docs.py create mode 100644 capabilities/C08/fixture/c08_probe.py create mode 100644 qualifications/34140846679/evidence-artifact.zip create mode 100644 qualifications/34140846679/provenance.json create mode 100644 qualifications/34140846679/qualification-summary.json diff --git a/.github/workflows/stage-run27-docs.yml b/.github/workflows/stage-run27-docs.yml new file mode 100644 index 0000000..cb34700 --- /dev/null +++ b/.github/workflows/stage-run27-docs.yml @@ -0,0 +1,49 @@ +name: Verify run 27 closure documentation +on: + push: + branches: [chore/record-qualified-run27] + paths: [.github/workflows/stage-run27-docs.yml] +permissions: + contents: write +jobs: + stage: + runs-on: ubuntu-latest + timeout-minutes: 10 + env: + PYTHONDONTWRITEBYTECODE: '1' + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + persist-credentials: false + - name: Reconstruct exact locally reviewed closure tree and validate it + run: | + set -euo pipefail + python3 .qualification-run27/update_docs.py + git rm .qualification-run27/update_docs.py .github/workflows/stage-run27-docs.yml + git add CHANGELOG.md README.md docs/CODEX_SANDBOX_RUNBOOK.md docs/QUALIFICATION_STATUS.md docs/RELEASE.md tests/test_qualification_closure.py + git diff --cached --check + test "$(git write-tree)" = '4fbb19ab2520fa838e205c8f27511ad493c5de51' + git -c user.name='PlanAnvil verification' -c user.email='verification@example.invalid' -c commit.gpgsign=false commit -qm 'Local verification snapshot only; no ref is pushed' + python3 tools/validate_capabilities.py + python3 tools/release_check.py + python3 -m unittest discover -s tests -v + - name: Store verified content objects only + env: + GH_TOKEN: ${{ github.token }} + run: | + python3 - <<'PY' + import base64,json,subprocess + from pathlib import Path + files=['CHANGELOG.md','README.md','docs/CODEX_SANDBOX_RUNBOOK.md','docs/QUALIFICATION_STATUS.md','docs/RELEASE.md','tests/test_qualification_closure.py'] + entries=[] + for name in files: + expected=subprocess.check_output(['git','hash-object',name],text=True).strip() + payload=json.dumps({'content':base64.b64encode(Path(name).read_bytes()).decode(),'encoding':'base64'}) + result=subprocess.run(['gh','api','--method','POST','repos/KeyffMS/PlanAnvil/git/blobs','--input','-'],input=payload,text=True,capture_output=True,check=True) + assert json.loads(result.stdout)['sha']==expected + entries.append({'path':name,'mode':'100644','type':'blob','sha':expected}) + payload=json.dumps({'base_tree':'15e41790681746f5582da1f2e16dc654e1445d89','tree':entries}) + result=subprocess.run(['gh','api','--method','POST','repos/KeyffMS/PlanAnvil/git/trees','--input','-'],input=payload,text=True,capture_output=True,check=True) + assert json.loads(result.stdout)['sha']=='4fbb19ab2520fa838e205c8f27511ad493c5de51' + print('VERIFIED_RUN27_CLOSURE_TREE=4fbb19ab2520fa838e205c8f27511ad493c5de51; no refs changed') + PY diff --git a/.github/workflows/stage-run27-evidence.yml b/.github/workflows/stage-run27-evidence.yml deleted file mode 100644 index 78e3a9e..0000000 --- a/.github/workflows/stage-run27-evidence.yml +++ /dev/null @@ -1,138 +0,0 @@ -name: Stage verified run 27 evidence -on: - push: - branches: [chore/record-qualified-run27] - paths: [.github/workflows/stage-run27-evidence.yml] -permissions: - contents: write - actions: read -jobs: - stage: - runs-on: ubuntu-latest - timeout-minutes: 10 - env: - PYTHONDONTWRITEBYTECODE: '1' - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - with: - fetch-depth: 2 - persist-credentials: false - - name: Verify and stage exact full-run evidence without updating refs - env: - GH_TOKEN: ${{ github.token }} - run: | - set -euo pipefail - python3 - <<'PY' - import base64, concurrent.futures, hashlib, json, os, shutil, subprocess, sys, zipfile - from pathlib import Path - sys.path.insert(0, str(Path('tools').resolve())) - from qualification_artifact import verify_archive - from qualification_closure import closure_blockers - from validate_capabilities import validate_all - source = 'a9cdcdc1e0cad70e88b60869e75e4166046dd306' - run_id = '34140846679' - artifact_id = 10026707683 - temp = Path(os.environ['RUNNER_TEMP']) - def git(*args): - return subprocess.check_output(['git', *args], text=True).strip() - def api(endpoint, payload=None): - args = ['gh', 'api', 'repos/KeyffMS/PlanAnvil/' + endpoint] - if payload is not None: - args += ['--method', 'POST', '--input', '-'] - result = subprocess.run(args, input=json.dumps(payload) if payload is not None else None, - text=True, capture_output=True, check=True) - return json.loads(result.stdout) - def digest(data): - return hashlib.sha256(data).hexdigest() - assert git('rev-parse', 'HEAD^') == source - subprocess.run(['git', 'archive', '--format=tar.gz', '--output=' + str(temp / 'run27-source.tar.gz'), source], check=True) - run = api('actions/runs/' + run_id) - assert run['head_sha'] == source and run['conclusion'] == 'success' - assert run['event'] == 'workflow_dispatch' and run['actor']['login'] == 'KeyffMS' - artifact = api('actions/artifacts/' + str(artifact_id)) - outer = subprocess.check_output(['gh', 'api', 'repos/KeyffMS/PlanAnvil/actions/artifacts/' + str(artifact_id) + '/zip']) - assert digest(outer) == '9583393745fc8292de701c51064e5569f24092e978da7164c8f50070e7d35e73' - assert artifact['digest'] == 'sha256:' + digest(outer) - outer_path = temp / 'run27-outer.zip' - outer_path.write_bytes(outer) - with zipfile.ZipFile(outer_path) as z: - assert z.namelist() == ['evidence-artifact.zip'] - inner = z.read('evidence-artifact.zip') - assert digest(inner) == '83beb50d27198c2cc0ecd72bc6ca4b1ec2d6570bcb23cc0d56c12ec97408ec75' - inner_path = temp / 'run27-inner.zip' - inner_path.write_bytes(inner) - integrity = verify_archive(inner_path) - history_before = {str(p): digest(p.read_bytes()) for p in Path('qualifications/34060321283').rglob('*') if p.is_file()} - old_index = json.loads(Path('capabilities/index.json').read_text()) - with zipfile.ZipFile(inner_path) as z: - summary_bytes = z.read('qualification-summary.json') - summary = json.loads(summary_bytes) - assert summary['source_commit'] == source and summary['github_actions_run'] == run_id - assert summary['release_gate_passed'] is True and summary['required_not_reproduced'] == [] - assert summary['results'] == {f'C{i:02d}': 'REPRODUCED' for i in range(1, 17)} - new_index = json.loads(z.read('capabilities/index.json')) - assert new_index['baseline_version'] == old_index['baseline_version'] - for old, new in zip(old_index['capabilities'], new_index['capabilities'], strict=True): - assert all(old[k] == new[k] for k in ('id', 'required', 'expected_behavior')) - for i in range(1, 17): - prefix = f'capabilities/C{i:02d}' - actual = json.loads(z.read(prefix + '/actual.sanitized.json')) - evaluation = json.loads(z.read(prefix + '/evaluation.json')) - assert actual['environment']['source_commit'] == source and actual['result'] == 'REPRODUCED' - assert evaluation['expected_met'] is True and evaluation['result'] == 'REPRODUCED' - shutil.rmtree(prefix) - for name in z.namelist(): - if name.startswith('capabilities/') and not name.endswith('/'): - target = Path(name) - target.parent.mkdir(parents=True, exist_ok=True) - target.write_bytes(z.read(name)) - folder = Path('qualifications') / run_id - folder.mkdir() - (folder / 'evidence-artifact.zip').write_bytes(inner) - (folder / 'qualification-summary.json').write_bytes(summary_bytes) - provenance = {'schema_version': '1.0', 'source_commit': source, 'github_actions_run': run_id, - 'artifact_id': artifact_id, 'outer_sha256': digest(outer), 'evidence_sha256': digest(inner), - 'integrity': integrity, 'qualification_mode': 'full', - 'limitations': ['C13 passed through the explicitly permitted project-scoped non-ephemeral fallback; ephemeral transport remains unsupported in this observed path.']} - (folder / 'provenance.json').write_text(json.dumps(provenance, indent=2, sort_keys=True) + '\n') - index = json.loads(Path('qualifications/index.json').read_text()) - assert index['baseline_run'] == '34060321283' - index.update(current_run=run_id, c08_closure='REPRODUCED') - Path('qualifications/index.json').write_text(json.dumps(index, indent=2, sort_keys=True) + '\n') - assert history_before == {str(p): digest(p.read_bytes()) for p in Path('qualifications/34060321283').rglob('*') if p.is_file()} - assert validate_all(Path('.')) == [] - assert closure_blockers(Path('.')) == [] - subprocess.run(['git', 'add', '-A', '--', 'capabilities', 'qualifications'], check=True) - subprocess.run(['git', 'rm', '.github/workflows/stage-run27-evidence.yml'], check=True) - subprocess.run(['git', 'diff', '--cached', '--check'], check=True) - names = git('diff', '--cached', '--name-only', '--diff-filter=AM').splitlines() - deleted = git('diff', '--cached', '--name-only', '--diff-filter=D').splitlines() - assert all(n.startswith(('capabilities/', 'qualifications/')) for n in names) - def store(path): - data = Path(path).read_bytes() - expected = git('hash-object', path) - result = api('git/blobs', {'content': base64.b64encode(data).decode(), 'encoding': 'base64'}) - assert result['sha'] == expected - return {'path': path, 'mode': '100644', 'type': 'blob', 'sha': expected} - with concurrent.futures.ThreadPoolExecutor(max_workers=4) as pool: - entries = list(pool.map(store, names)) - entries += [{'path': name, 'mode': '100644', 'type': 'blob', 'sha': None} for name in deleted] - result = api('git/trees', {'base_tree': git('rev-parse', 'HEAD^{tree}'), 'tree': entries}) - assert result['sha'] == git('write-tree') - subprocess.run(['git', 'archive', '--format=tar.gz', '--output=' + str(temp / 'run27-imported.tar.gz'), result['sha']], check=True) - report = {'tree': result['sha'], 'parent': git('rev-parse', 'HEAD'), 'source_commit': source, - 'changed_files': len(entries), 'integrity': integrity, 'closure_blockers': [], - 'source_archive_sha256': digest((temp / 'run27-source.tar.gz').read_bytes()), - 'imported_archive_sha256': digest((temp / 'run27-imported.tar.gz').read_bytes())} - (temp / 'run27-stage.json').write_text(json.dumps(report, indent=2, sort_keys=True) + '\n') - print(json.dumps(report, indent=2)) - PY - - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f - with: - name: run27-reviewed-import-stage - path: | - ${{ runner.temp }}/run27-source.tar.gz - ${{ runner.temp }}/run27-imported.tar.gz - ${{ runner.temp }}/run27-stage.json - retention-days: 3 - if-no-files-found: error diff --git a/.qualification-run27/update_docs.py b/.qualification-run27/update_docs.py new file mode 100644 index 0000000..aed82b7 --- /dev/null +++ b/.qualification-run27/update_docs.py @@ -0,0 +1,165 @@ +from pathlib import Path +r=Path('.') +def replace(path,old,new): + p=r/path;s=p.read_text();assert old in s,path;p.write_text(s.replace(old,new)) +replace('README.md', + '**Full baseline 2.3 qualification passed:** run [#25](https://github.com/KeyffMS/PlanAnvil/actions/runs/34060321283) reproduced C01–C16 on source commit `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The complete sanitized evidence is committed under `capabilities/` and preserved unchanged under `qualifications/34060321283/`.\n\n**Release status remains candidate.** The old C08 positive trial proved its narrow unblock assertion but later timed out. Its finite replacement must finish in a new live `mode=c08` run and its evidence must be committed before production publication. C13 was reproduced through the explicit known-error-gated non-ephemeral fallback, not by proving ephemeral spawning works.', + '**Full baseline 2.3 qualification and finite C08 closure passed:** run [#27](https://github.com/KeyffMS/PlanAnvil/actions/runs/34140846679) reproduced C01–C16 on source commit `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The exact sanitized packages are committed under `capabilities/`; the original archive, summary and provenance are preserved under `qualifications/34140846679/`. Historical run #25 remains unchanged.\n\n**Qualification is complete for that tested configuration; signed publication is a separate step.** C08 now proves both the expected missing-checkpoint stop and a completed repaired recovery, without timeout. C09 and both C10 probes also completed without timeout. C13 was reproduced through the explicit known-error-gated, project-scoped non-ephemeral fallback; ephemeral spawning is not claimed as working. This evidence import does not create a production tag or GitHub Release.') +replace('README.md','python tools/release_check.py --candidate\n```','python tools/release_check.py --candidate\n# On a clean checkout containing the reviewed live evidence:\npython tools/release_check.py\n```') +status='''# Qualification status + +## Current reviewed full result + +**Live qualification is complete for the tested configuration.** Owner-initiated +full run #27 (`34140846679`) passed baseline 2.3 C01-C16 on executed source +`a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, +model `gpt-5.6-sol`, Debian GNU/Linux 13. C04 is informational; fifteen +capabilities are required. The full run reports `release_gate_passed=true`. +All model-backed trials ran on the authenticated self-hosted runner. + +The original archive, exact summary and verified provenance are preserved in +`qualifications/34140846679/`. `qualifications/index.json.current_run` points to +that run. Current `capabilities/C01` through `C16` are exact archive copies, +not rewritten observations or a combination of partial runs. The executed source +SHA remains the original SHA, never the later evidence-import commit. + +## C08 closure and recovery regressions + +C08 completed its finite stop/repair protocol in the same canonical run: + +- Without a checkpoint: one completed pressure command, an actual automatic + PreCompact `continue=false`, expected process exit 1 after 10.643 seconds, + no PostCompact and no timeout. +- After the outer harness created a real valid checkpoint: pressure, one + automatic PreCompact/PostCompact cycle, SessionStart(source=compact), finish + reconciliation and positive structured completion; exit 0 after 36.265 seconds, + no timeout. All nine positive protocol checks passed. + +C09 completed all three reconciliations and two ordered automatic recovery +cycles with exit 0 in 60.679 seconds. Both independent C10 context-delivery +probes completed with exact recovery values and exit 0. Process cleanup and +checkpoint/source immutability checks passed for the recovery probes. + +There are no recorded `timeout=true` values in the current actual evidence. +This is not a guarantee of future model behavior or support for untested +Codex/model/operating-system combinations. + +## Retained compatibility limitation + +C13 passed using the explicitly allowed project-scoped non-ephemeral fallback +after the recognized ephemeral parent-thread failure. Agent and SubagentStart +hook remained project-scoped; child context, cleanup and authentication +invariants passed. Ephemeral spawning is not claimed as working. + +## Integrity and publication boundary + +The archive contains 166 manifest-listed files plus the manifest, including +three hidden fixture files. All SHA-256 checks, per-capability package validation +and source identities were verified before import. The qualified .agents/.codex +product bytes, runtime implementations, permission policy and release guards +are unchanged by this evidence/documentation update. + +On a clean checkout, run `python tools/validate_capabilities.py` and +`python tools/release_check.py` without `--candidate`. The latter requires the +complete full-run archive, exact packages, unchanged qualified product bytes +and finite C08 completion. Freshly materialized unexecuted templates still start +BLOCKED and cannot inherit the archived success. + +No additional live run is required merely to record these same results or +update documentation. Requalify when relevant product/runtime inputs change. +Production publication remains a separate owner-authorized verified signed +annotated tag and release workflow, as described in `RELEASE.md`. No production +tag or release is created by the evidence import. + +## Preserved history + +Run #25 (`34060321283`, source `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`) +passed the older narrow assertions but its positive C08 trial later timed out. +Its original archive, summary, provenance and caveat remain unchanged under +`qualifications/34060321283/`; it is not the current publication evidence. + +PR #34 merged the finite C08 repair. Automated run #26 (`34109662176`) was +rejected by the local initiating-actor policy before Codex. It provides no live +result. The owner-initiated #27 completed without changing or bypassing that +policy. PR #35 clarified the requirement for one complete full archive. + +## Verification layers and audit index + +Unit/process tests and real-CLI loopback conformance check implementation and +protocol behavior. Only the authenticated self-hosted run supplies live-model +evidence. The archived full result does not imply execution of every possible +application plan; PlanAnvil generates and validates plans, never implements them. + +- `CODEX_CAPABILITY_QUALIFICATION_2026-08-28.md`: historical prerequisite-limited attempt. +- `CODEX_QUALIFICATION_EXECUTION_AUDIT_2026-09-05.md`: C13 argv and C10 worktree discovery. +- `CODEX_RECOVERY_DELIVERY_AUDIT_2026-09-05.md`: context delivery and diagnostics. +- `CODEX_C09_FINITE_RECOVERY_AUDIT_2026-09-06.md`: finite C09 repair. +- `CODEX_C08_CLOSURE_AUDIT_2026-09-07.md`: finite C08 implementation. + +Older harness modules remain active v7 dependencies, not separate supported +entry points. They must not be removed as cosmetic cleanup. +''' +(r/'docs/QUALIFICATION_STATUS.md').write_text(status) +replace('docs/CODEX_SANDBOX_RUNBOOK.md', + 'Full run #25 is archived and passed baseline 2.3 on Codex CLI 0.153.4. The finite C08 stop/repair replacement is merged. Publication now requires a successful new full run and import of its complete evidence. `QUALIFICATION_STATUS.md` is the current status; this runbook describes both full requalification and targeted checks.', + 'Full run #27 is reviewed and archived: baseline 2.3 C01-C16 and finite C08 stop/repair passed on Codex CLI 0.153.4. Its complete evidence is recorded in the repository; no new run is needed just to import it. Historical #25 remains unchanged. `QUALIFICATION_STATUS.md` records the tested configuration, limitations and publication boundary. This runbook describes future full requalification and targeted checks.') +replace('docs/CODEX_SANDBOX_RUNBOOK.md','Use **mode=full** for the next publication-closing C01-C16 sequence.', 'Use **mode=full** when a new publication-closing C01-C16 qualification is needed.') +replace('docs/CODEX_SANDBOX_RUNBOOK.md', + 'Start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner\'s initiating-actor policy. Automated run #26 (`34109662176`) was rejected by that policy before any Codex trial; do not rerun it or relax the allowlist. The repair is on main, but that rejected launch provides no model-backed result.', + 'For requalification, start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner\'s initiating-actor policy. Automated run #26 (`34109662176`) was rejected before any Codex trial. Owner-initiated #27 then passed; do not rerun the rejected launch or relax the allowlist.') +replace('docs/CODEX_SANDBOX_RUNBOOK.md', + 'Full capability qualification and publication closure are separate. Preserve the original #25 archive unchanged. For publication, review and commit a new successful full-run archive whose C08 has finite completion evidence, along with its exact C01-C16 packages and actual executed source SHA. Update `qualifications/index.json` to that full run as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive.', + 'Full capability qualification and signed publication are separate. Current full run #27 supplies finite C08 completion and exact C01-C16 packages; `qualifications/index.json` identifies it. Preserve both #25 and #27 archives unchanged. Any future qualification must be imported as one complete source-bound full archive as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive.') +replace('docs/RELEASE.md', + 'For the current C08 closure, use a NEW `mode=full` run on main, initiated by an account allowed by the self-hosted runner. The production validator requires a single complete full-run archive containing the finite C08 proof. A successful `c08` or `recovery` diagnostic is useful but its partial archive cannot replace that full run. See `docs/QUALIFICATION_STATUS.md` for the merged repair and the automated launch rejected before testing.', + 'Current full run #27 (`34140846679`) passed and its exact reviewed evidence is committed, including finite C08 stop/repair completion. No further live run is required merely to record this result. The production validator still requires one complete full-run archive; a `c08` or `recovery` diagnostic cannot replace it. See `docs/QUALIFICATION_STATUS.md` for provenance, tested scope and the retained C13 fallback limitation.') +replace('docs/RELEASE.md','## Qualification closure (2026-09-07)','## Qualification closure (reviewed 2026-09-08)') +replace('docs/RELEASE.md', + 'negative-stop/positive-completion evidence. The old C08 timeout keeps production\nblocked until the new complete full-run result is committed. Candidate checks\nintentionally remain usable before that result exists.', + 'negative-stop/positive-completion evidence. Full #27 now supplies that proof;\nthe old #25 timeout remains recorded as history. Candidate checks still do not\nsubstitute for strict production validation. Run `python tools/release_check.py`\non the clean evidence-import commit before any signed publication.') +replace('docs/RELEASE.md', + 'After the complete new full-run evidence is imported and CI is green, preparation\nis complete; the signed annotated production tag remains a separate authorized\npublication. No unsigned or lightweight tag may substitute for the required\nverified signature.', + 'The complete #27 evidence is imported. After strict validation and green CI on\nthe evidence-import commit, qualification preparation is complete; a signed\nannotated production tag remains a separate authorized publication. This import\ndoes not create a tag or release. No unsigned or lightweight tag may substitute\nfor the required verified signature.') +replace('CHANGELOG.md', '## [Unreleased]\n', '''## [Unreleased] + +### Qualification closure — 2026-09-07 + +- full self-hosted run #27 (`34140846679`) reproduced all C01-C16 on executed source `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, `gpt-5.6-sol`, Debian 13; +- finite C08 now proves the intended missing-checkpoint stop and completed repaired recovery without timeout; C09/C10 regressions passed; +- preserve the exact full archive and provenance, update current capability evidence, and retain historical #25 unchanged; +- C13 retains the documented project-scoped, known-error-gated non-ephemeral fallback; no new transport claim or product/runtime/security change; +- qualification is recorded; signed production publication remains a separate action. +''') +p=r/'tests/test_qualification_closure.py' +s=p.read_text(); marker=' def copy_repo(self, tmp):' +assert marker in s +s=s.replace(marker, ''' def test_reviewed_current_full_archive_closes_evidence_gate(self): + # Read real committed evidence; no synthetic result or CLI simulation. + self.assertEqual(closure.closure_blockers(ROOT), []) + index = json.loads((ROOT / 'qualifications/index.json').read_text()) + self.assertEqual(index['c08_closure'], 'REPRODUCED') + folder = ROOT / 'qualifications' / index['current_run'] + provenance = json.loads((folder / 'provenance.json').read_text()) + self.assertEqual(provenance['qualification_mode'], 'full') + with zipfile.ZipFile(folder / 'evidence-artifact.zip') as z: + summary_bytes = z.read('qualification-summary.json') + self.assertEqual((folder / 'qualification-summary.json').read_bytes(), summary_bytes) + summary = json.loads(summary_bytes) + self.assertEqual(summary['github_actions_run'], index['current_run']) + self.assertEqual(summary['source_commit'], provenance['source_commit']) + self.assertTrue(summary['release_gate_passed']) + self.assertEqual(summary['required_not_reproduced'], []) + + def test_current_package_change_is_not_accepted_as_archived_evidence(self): + with tempfile.TemporaryDirectory() as tmp: + root = self.copy_repo(tmp) + path = root / 'capabilities/C09/actual.sanitized.json' + # Even a JSON-preserving edit is not the original source-bound record. + with path.open('ab') as stream: + stream.write(b'\\n') + self.assertTrue(any('current capability differs from archived run' in error + for error in closure.closure_blockers(root))) + +'''+marker) +p.write_text(s) +print('Docs and evidence regression tests updated; no runtime code changed.') diff --git a/capabilities/C01/README.md b/capabilities/C01/README.md index 2b0acc2..e31338a 100644 --- a/capabilities/C01/README.md +++ b/capabilities/C01/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C01/actual.sanitized.json b/capabilities/C01/actual.sanitized.json index 5eabc40..645a33f 100644 --- a/capabilities/C01/actual.sanitized.json +++ b/capabilities/C01/actual.sanitized.json @@ -2,17 +2,17 @@ "capability_id": "C01", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "4df35777e3afd6f5b6a9aecfe22793e65bba83ea", + "fixture_commit": "00f746c24feb4ecc943c59cbe8006db2a01e9cd3", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "The explicit activation trial resolved the repository fixture skill and produced the activation proof `FIXTURE_SKILL_ACTIVE`.", - "The nested-working-directory trial verified repository identity, discovered the same fixture skill, and produced `FIXTURE_SKILL_ACTIVE`.", - "Both trials completed with PASS outcomes, no blocker, and no recorded error events." + "The explicit-activation trial resolved the fixture skill from the repository skill directory and recorded activation proof `FIXTURE_SKILL_ACTIVE`.", + "The nested-working-directory trial verified repository identity from its nested start location, discovered and invoked the fixture skill, and recorded the same activation proof.", + "The first trial did not exercise nested discovery, but the completed second trial directly exercised and passed that assertion." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -20,9 +20,14 @@ { "assertions": [ { - "evidence": "Explicit invocation resolved `fixture-capability` from `.agents/skills/fixture-capability/SKILL.md`; activation proof: FIXTURE_SKILL_ACTIVE.", - "name": "Repository skill resolution and explicit activation", + "evidence": "`fixture-capability` was resolved from `.agents/skills/fixture-capability/SKILL.md` and explicitly activated with proof `FIXTURE_SKILL_ACTIVE`.", + "name": "The fixture skill appears in repository skill discovery.", "status": "PASS" + }, + { + "evidence": "Not exercised by this root-level explicit-activation trial.", + "name": "Discovery works when Codex starts from a nested working directory inside the same repository.", + "status": "BLOCKED" } ], "blocker": null, @@ -48,7 +53,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4df35777e3afd6f5b6a9aecfe22793e65bba83ea", + "head": "00f746c24feb4ecc943c59cbe8006db2a01e9cd3", "index_tree": "715ef280db9d5ab81405996e12aa2be15877d964", "refs": [ "refs/heads/master" @@ -60,7 +65,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4df35777e3afd6f5b6a9aecfe22793e65bba83ea", + "head": "00f746c24feb4ecc943c59cbe8006db2a01e9cd3", "index_tree": "715ef280db9d5ab81405996e12aa2be15877d964", "refs": [ "refs/heads/master" @@ -79,12 +84,12 @@ { "assertions": [ { - "evidence": "Explicit invocation produced activation proof FIXTURE_SKILL_ACTIVE.", + "evidence": "$fixture-capability was discovered and invoked; activation proof: FIXTURE_SKILL_ACTIVE.", "name": "The fixture skill appears in repository skill discovery.", "status": "PASS" }, { - "evidence": "Repository identity was verified from the nested working directory, and the repository skill was then discovered and activated.", + "evidence": "Git repository identity was verified from the nested starting directory without reporting its absolute path.", "name": "Discovery works when Codex starts from a nested working directory inside the same repository.", "status": "PASS" } @@ -92,19 +97,19 @@ "blocker": null, "capability_id": "C01", "event_summary": { - "completed_command_items": 3, + "completed_command_items": 2, "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 8, - "item.started": 3, + "item.completed": 7, + "item.started": 2, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 3, - "command_execution": 6, + "command_execution": 4, "error": 2 } }, @@ -112,7 +117,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4df35777e3afd6f5b6a9aecfe22793e65bba83ea", + "head": "00f746c24feb4ecc943c59cbe8006db2a01e9cd3", "index_tree": "715ef280db9d5ab81405996e12aa2be15877d964", "refs": [ "refs/heads/master" @@ -124,7 +129,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4df35777e3afd6f5b6a9aecfe22793e65bba83ea", + "head": "00f746c24feb4ecc943c59cbe8006db2a01e9cd3", "index_tree": "715ef280db9d5ab81405996e12aa2be15877d964", "refs": [ "refs/heads/master" diff --git a/capabilities/C01/evaluation.json b/capabilities/C01/evaluation.json index d6d15b0..c03d710 100644 --- a/capabilities/C01/evaluation.json +++ b/capabilities/C01/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "Sanitized trial evidence demonstrates repository skill discovery both explicitly and from a nested working directory." + "summary": "Sanitized trial evidence demonstrates both repository skill discovery and discovery from a nested working directory." } diff --git a/capabilities/C01/hashes.json b/capabilities/C01/hashes.json index d866554..161e656 100644 --- a/capabilities/C01/hashes.json +++ b/capabilities/C01/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "422e8b7912cf13e186c621d5eeae747575e5389e5b135b157596ee4201819565", - "actual.sanitized.json": "9042d7e35a10682bff746c4313193baf4d1947dfd814853ca03f78555825aba9", + "README.md": "f0379083ccec22707ec999a82f6cda7971024e970b17f2276d74b478340bde81", + "actual.sanitized.json": "9efbd720ac6e947272ef1b998ad3b51c36b1b3ab3cd652ffab368a456bc443ba", "config/README.md": "2b6beca33571ad108adcdbac9becc82a7fe658cf672305f01f58f4ea54565b4e", - "evaluation.json": "12aeecb91deeaef38f633d67f60451a07ba176539a5430cfc16c82c8bafa7ee5", + "evaluation.json": "46bf08a3331e054e3dccd8a2822e6526994e85b7de2bfd4f04e61a7a2c1cd62e", "expected.json": "c41329fbf6892a65b85cfe1166e86d2a3b59b684a9a81601974fca0c54a0cee7", "fixture/.agents/skills/fixture-capability/SKILL.md": "0c4c7985ed4a06a2fa45d0d6a1887fec0f5a59892ae1d0d88317ac1c82a7a4ff", "fixture/README.md": "a3ac65c07ebf67442b31cf3bc1d28ac5c849bd08fee9cba93b0a31339e7602d8", diff --git a/capabilities/C02/README.md b/capabilities/C02/README.md index d6440c2..7026eb8 100644 --- a/capabilities/C02/README.md +++ b/capabilities/C02/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C02/actual.sanitized.json b/capabilities/C02/actual.sanitized.json index 50b31b4..417d13c 100644 --- a/capabilities/C02/actual.sanitized.json +++ b/capabilities/C02/actual.sanitized.json @@ -2,17 +2,17 @@ "capability_id": "C02", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "b006122b504e9bdf38fa9d0a21c35ab866fba584", + "fixture_commit": "ac01932c34c0e42bb7a84fe986452f011ffae50f", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "Implicit-activation trial completed and passed: a semantically matching prompt without the skill name produced no skill-specific activation token.", - "Explicit-activation trial completed and passed: the explicit $fixture-capability prompt supplied the expected FIXTURE_SKILL_ACTIVE token.", - "Both material assertions in the expected specification were directly exercised; neither trial reported a blocker or runtime error." + "The completed implicit-invocation trial used a semantically matching request without the skill name and observed no skill-specific activation token.", + "The completed explicit-invocation trial used $fixture-capability and observed the required literal proof token FIXTURE_SKILL_ACTIVE.", + "Both expected assertions are individually marked PASS; both trials report PASS with no blocker or error events." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -20,7 +20,7 @@ { "assertions": [ { - "evidence": "The semantic match did not place any skill-specific activation token in the active instructions.", + "evidence": "The semantically matching request produced no skill-specific activation token in the active instructions.", "name": "A semantically matching prompt without the skill name does not activate the fixture skill.", "status": "PASS" } @@ -48,7 +48,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "b006122b504e9bdf38fa9d0a21c35ab866fba584", + "head": "ac01932c34c0e42bb7a84fe986452f011ffae50f", "index_tree": "6455a6dfb42207be3ad780cca165fa8f60e78d57", "refs": [ "refs/heads/master" @@ -60,7 +60,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "b006122b504e9bdf38fa9d0a21c35ab866fba584", + "head": "ac01932c34c0e42bb7a84fe986452f011ffae50f", "index_tree": "6455a6dfb42207be3ad780cca165fa8f60e78d57", "refs": [ "refs/heads/master" @@ -84,7 +84,7 @@ { "assertions": [ { - "evidence": "Activated skill context required and supplied `FIXTURE_SKILL_ACTIVE`.", + "evidence": "Activated skill context required and supplied the literal proof token: FIXTURE_SKILL_ACTIVE", "name": "An explicit $fixture-capability prompt activates the fixture skill.", "status": "PASS" } @@ -112,7 +112,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "b006122b504e9bdf38fa9d0a21c35ab866fba584", + "head": "ac01932c34c0e42bb7a84fe986452f011ffae50f", "index_tree": "6455a6dfb42207be3ad780cca165fa8f60e78d57", "refs": [ "refs/heads/master" @@ -124,7 +124,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "b006122b504e9bdf38fa9d0a21c35ab866fba584", + "head": "ac01932c34c0e42bb7a84fe986452f011ffae50f", "index_tree": "6455a6dfb42207be3ad780cca165fa8f60e78d57", "refs": [ "refs/heads/master" @@ -133,7 +133,7 @@ "worktree_count": 1 }, "observations": [ - "FIXTURE_SKILL_ACTIVE" + "Explicit invocation activated fixture-capability; the skill file was not directly inspected and no files were modified." ], "outcome": "PASS", "outer_skill_policy": { diff --git a/capabilities/C02/evaluation.json b/capabilities/C02/evaluation.json index b4afe4c..80bd8a4 100644 --- a/capabilities/C02/evaluation.json +++ b/capabilities/C02/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "Sanitized trial evidence demonstrates that the fixture skill remains inactive for an unnamed semantic match and activates when explicitly named." + "summary": "Sanitized trial evidence demonstrates both explicit-only activation assertions." } diff --git a/capabilities/C02/hashes.json b/capabilities/C02/hashes.json index f84eacf..a92369a 100644 --- a/capabilities/C02/hashes.json +++ b/capabilities/C02/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "d48f15a8b53baa0aa7ee54ee3c1b56ae44747159f9579963461180277f052027", - "actual.sanitized.json": "84a176fed4880e6a59bb18f46d9c24962b6f371ad6de8d9458da75deaa488923", + "README.md": "0eb2ce77906499f392ee20894bba2939ac41e4b968f25d16caf06dd22af4eeea", + "actual.sanitized.json": "66acfd0d0ce95591dd9beddd138d4d9066e597b7a47c5f9f3e9888c2b5a3bcc7", "config/README.md": "22255f099cfe99dea718801c9f78b2230d229a560ba02f1f048e35f9ca765780", - "evaluation.json": "a1bb7d9496bd9daba9a07f296b1ce42acc133a91d36c9f8c7aa81fb4c329f548", + "evaluation.json": "e004a439026664fa6fa715c15603e012ca343f3685091ceb3b7381da9b87c4d7", "expected.json": "fe22f0a70480c8c1b932e67af607ca5e3f539512162dd22b903001a3b215d0b8", "fixture/.agents/skills/fixture-capability/SKILL.md": "35e41a201965e0a9c83ce9dbcf151275a7ad5718edd63c21976e0def24204cd5", "fixture/.agents/skills/fixture-capability/agents/openai.yaml": "5f4b205f412e2e168092f152801b7dc72bc00e7716147305ebc5fa6bfabe0087", diff --git a/capabilities/C03/README.md b/capabilities/C03/README.md index cec8ed0..cabe506 100644 --- a/capabilities/C03/README.md +++ b/capabilities/C03/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C03/actual.sanitized.json b/capabilities/C03/actual.sanitized.json index b418364..7324d44 100644 --- a/capabilities/C03/actual.sanitized.json +++ b/capabilities/C03/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C03", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "368b6459d9c801e9ab70d931c2af313814051424", + "fixture_commit": "e2f97dd2aacb420decf67085a8a27675fcde8bc6", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "bootstrap_git_probe_completed=true", @@ -77,21 +77,20 @@ "model_payload": { "assertions": [ { - "evidence": "Exact command exited 0; `git status --porcelain=v1` produced no output.", - "name": "Auxiliary C03 source is reachable and clean", + "evidence": "Exit code 0; `git status --porcelain=v1` produced no output.", + "name": "Auxiliary source is clean", "status": "PASS" }, { - "evidence": "`git rev-parse HEAD` returned `368b6459d9c801e9ab70d931c2af313814051424`.", - "name": "HEAD is resolvable", + "evidence": "`git rev-parse HEAD` returned `e2f97dd2aacb420decf67085a8a27675fcde8bc6`.", + "name": "Auxiliary source is reachable", "status": "PASS" } ], "blocker": null, "capability_id": "C03", "observations": [ - "Working tree status is clean.", - "HEAD: 368b6459d9c801e9ab70d931c2af313814051424" + "The exact requested command completed successfully without modifying files." ], "outcome": "PASS", "trial": "explicit_plananvil_topology" diff --git a/capabilities/C03/hashes.json b/capabilities/C03/hashes.json index a82cee2..03504aa 100644 --- a/capabilities/C03/hashes.json +++ b/capabilities/C03/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "084f89a9262a3a3b9c0396f015dae1660de6350d5d0909785b92400e0d042a6f", - "actual.sanitized.json": "fed985f84bfc26a716d5a6741f9066613f3cc4d177a4e3a2b2276595114af98f", + "README.md": "4c476f680f984930da4d3ea499d4ebf5a45c3ab2facfba3a4e93ab273f549fe7", + "actual.sanitized.json": "60e42e4668a8ef002b445449940e3d6c3085f3b3aaf259c5bba88ab237bbe8e3", "config/README.md": "4ddf277c13326c7e01250b638a72c2adbaf1742f2df2526a048d75c5bc5cd815", "evaluation.json": "e24e3f4ca1d6846aa737ab82fe44e56975ac2536416873ff0ae7dd8c42ab9baa", "expected.json": "ae01636f9854bfe67f02bc2dcb2aa817dc6e92b29c93e98a2486cf4f6dc379d0", diff --git a/capabilities/C04/README.md b/capabilities/C04/README.md index 7be117d..2c01ebc 100644 --- a/capabilities/C04/README.md +++ b/capabilities/C04/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C04/actual.sanitized.json b/capabilities/C04/actual.sanitized.json index e53d86c..86e6ba6 100644 --- a/capabilities/C04/actual.sanitized.json +++ b/capabilities/C04/actual.sanitized.json @@ -2,18 +2,17 @@ "capability_id": "C04", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "4630aec248648a255faaf8cf10caa1ee8ea162d2", + "fixture_commit": "265b882eea3430d63025a1d0c70635400606c686", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "The child agent successfully started a nested child agent, and the nested child completed.", - "The trial reports no repository, Git, specification, or PlanAnvil source changes.", - "Git state was unchanged before and after the trial, with no cached or working-tree changes.", - "Both expected assertions passed and the completed trial reported no blocker." + "A child agent successfully started a nested child agent, which completed.", + "The trial recorded the nested-agent result as informational only.", + "Git state was unchanged, with no file, configuration, or release-gate changes observed." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -21,12 +20,12 @@ { "assertions": [ { - "evidence": "A child agent successfully started one nested child agent, which completed.", + "evidence": "A child agent successfully started one nested child agent, and the nested child completed.", "name": "Record whether a child agent can start another agent in the tested runtime/configuration.", "status": "PASS" }, { - "evidence": "Observation only; no repository, Git, specification, or PlanAnvil source changes were made.", + "evidence": "The observation was informational only; no PlanAnvil files, configuration, or release-gate behavior were changed.", "name": "Do not change PlanAnvil flat-topology safety based on this observation alone.", "status": "PASS" } @@ -55,8 +54,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4630aec248648a255faaf8cf10caa1ee8ea162d2", - "index_tree": "14cb369c4d1705946abdf80c6a0b35e7f621ca70", + "head": "265b882eea3430d63025a1d0c70635400606c686", + "index_tree": "ed6d0dcc1639cb6097a6d38a6ba7ed1bd4b30320", "refs": [ "refs/heads/master" ], @@ -67,8 +66,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "4630aec248648a255faaf8cf10caa1ee8ea162d2", - "index_tree": "14cb369c4d1705946abdf80c6a0b35e7f621ca70", + "head": "265b882eea3430d63025a1d0c70635400606c686", + "index_tree": "ed6d0dcc1639cb6097a6d38a6ba7ed1bd4b30320", "refs": [ "refs/heads/master" ], @@ -76,14 +75,14 @@ "worktree_count": 1 }, "observations": [ - "Nested subagent spawn: allowed.", - "Nested child completion: completed.", + "Nested subagent start: accepted.", + "Nested subagent completion: observed.", "PlanAnvil flat-topology safety: unchanged." ], "outcome": "PASS", "sandbox": "read-only", - "trial": "informational-nested-subagent-observation", - "trial_name": "informational-nested-subagent-observation" + "trial": "observe_nested_subagent_behavior", + "trial_name": "observe_nested_subagent_behavior" }, { "evaluator_event_summary": { diff --git a/capabilities/C04/evaluation.json b/capabilities/C04/evaluation.json index 0eb3ab6..c50ee38 100644 --- a/capabilities/C04/evaluation.json +++ b/capabilities/C04/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The sanitized trial evidence demonstrates nested child-agent startup and completion while preserving PlanAnvil flat-topology safety unchanged." + "summary": "The completed trial demonstrates nested-agent startup and completion while preserving PlanAnvil flat-topology safety unchanged." } diff --git a/capabilities/C04/hashes.json b/capabilities/C04/hashes.json index 94b0401..b85affb 100644 --- a/capabilities/C04/hashes.json +++ b/capabilities/C04/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "057477bfe912e3da03670d6e743127ee85c9b37e6bb463512b8f3a8720630118", - "actual.sanitized.json": "a38184bac31ae43392862502b94c48399d292e1bd21aa784c76132749932b528", + "README.md": "ec7eb1cb9d8008fee5d6f174b84df64e489979f2c4107c0eb19e8edbe4590089", + "actual.sanitized.json": "e7a5c53e7a7255e6d67cf6ac0b5235ebc58ed98501e9c1a9dd7f2ffd476deb11", "config/README.md": "bdc289615d6db57a98f7bc2781c858f946334e5a5dbb4cb75bb84e9f470550be", - "evaluation.json": "6b180f007786f37a7c66a27f5f99812be0c75e83fd272a87ed5e43ee4f184566", + "evaluation.json": "ff53ed6b64288180e9c6f1bf2aee696d602616ead7c86e54654f649926272972", "expected.json": "6117c318bfa411e142263f9de73c2b3319edca4d15a8df667e4755137c24aab5", "fixture/README.md": "2eeb7e16493350395a0d5cd37677f36de8720634c98974048a8979ba38a383c2", "prompt.txt": "df898b6d1d46fef013ddb8e3e409388a228ff24ea668b760d51491f1652e8e7d", diff --git a/capabilities/C05/README.md b/capabilities/C05/README.md index 685937c..d1fc087 100644 --- a/capabilities/C05/README.md +++ b/capabilities/C05/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C05/actual.sanitized.json b/capabilities/C05/actual.sanitized.json index 7e1501e..d32243f 100644 --- a/capabilities/C05/actual.sanitized.json +++ b/capabilities/C05/actual.sanitized.json @@ -2,19 +2,19 @@ "capability_id": "C05", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "fixture_commit": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "A fresh explicit bundle passed digest verification, named only one safe relative payload path, and the payload hash matched.", - "Changing the payload while leaving the bundle valid produced a file-hash mismatch and a STALE rejection.", - "Changing the bundle without updating its sidecar caused digest verification to fail before its file list was processed.", - "Removing the bundle caused digest verification to fail before any payload list was trusted or read.", - "An escaped candidate failed repository containment validation and was rejected without being opened." + "Fresh handoff accepted only the explicitly named file after both bundle-digest and file-hash verification.", + "A modified target file was detected as stale and rejected with a nonzero exit.", + "A changed bundle failed digest verification and its file list was not trusted.", + "A missing bundle failed verification and no target file was processed.", + "An escaped path was rejected at the repository boundary before outside content was opened." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -22,32 +22,32 @@ { "assertions": [ { - "evidence": "review-bundle.sha256 matched review-bundle.json: 70ea11387dfb83e737f773b5162995fffc23568c65a6bc22aac6a6fa7df25169.", - "name": "Reviewer receives only the explicit immutable bundle.", + "evidence": "review-bundle.sha256 validated review-bundle.json: OK", + "name": "bundle_digest_verified", "status": "PASS" }, { - "evidence": "The verified bundle named only PLAN.md; its safe relative path was accepted and its SHA-256 matched 8890f7b98b2d70b87ab0b855104125faee2646938d2f7979a420f0c1343aed6b. Verification gates reject digest, path, existence, or file-hash mismatches.", - "name": "A stale, missing, changed, or escaped bundle is rejected.", + "evidence": "Only PLAN.md was named; its SHA-256 matched 8890f7b98b2d70b87ab0b855104125faee2646938d2f7979a420f0c1343aed6b", + "name": "explicit_file_hashes_verified", "status": "PASS" } ], "blocker": null, "capability_id": "C05", "event_summary": { - "completed_command_items": 4, + "completed_command_items": 3, "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 8, - "item.started": 4, + "item.completed": 7, + "item.started": 3, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 2, - "command_execution": 8, + "command_execution": 6, "error": 2 } }, @@ -55,7 +55,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -67,7 +67,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -76,8 +76,6 @@ "worktree_count": 1 }, "observations": [ - "Verified the bundle digest before reading its manifest.", - "Read only the explicitly named fixture file after validating its recorded hash.", "Accepted the immutable explicit handoff." ], "outcome": "PASS", @@ -88,12 +86,12 @@ { "assertions": [ { - "evidence": "Processed only explicit review-bundle.json; its recorded digest verified OK.", + "evidence": "Processed explicit review-bundle.json; its recorded bundle digest still matched.", "name": "Reviewer receives only the explicit immutable bundle.", "status": "PASS" }, { - "evidence": "After only PLAN.md changed, recorded hash 8890f7b9\u2026 differed from actual dad1b8fe\u2026; handoff was rejected as STALE.", + "evidence": "Only PLAN.md changed. Its actual hash differed from the bundle-recorded hash; processing returned HANDOFF=STALE and rejected it.", "name": "A stale, missing, changed, or escaped bundle is rejected.", "status": "PASS" } @@ -101,19 +99,19 @@ "blocker": null, "capability_id": "C05", "event_summary": { - "completed_command_items": 3, + "completed_command_items": 8, "completed_file_change_items": 1, "error_events": 0, "event_types": { - "item.completed": 9, - "item.started": 4, + "item.completed": 14, + "item.started": 9, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 3, - "command_execution": 6, + "command_execution": 16, "error": 2, "file_change": 2 } @@ -122,7 +120,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -136,7 +134,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -145,9 +143,9 @@ "worktree_count": 1 }, "observations": [ - "Only PLAN.md was modified.", - "Bundle digest remained valid.", - "Recorded PLAN.md hash mismatch was detected and classified STALE." + "Bundle integrity: MATCH.", + "Stale target detected: PLAN.md.", + "Process exit: 3 (rejected)." ], "outcome": "PASS", "sandbox": "workspace-write", @@ -157,12 +155,12 @@ { "assertions": [ { - "evidence": "Explicit handoff verification used review-bundle.sha256 for review-bundle.json and stopped at digest validation.", + "evidence": "Explicit handoff used review-bundle.json with review-bundle.sha256; digest validation ran before file-list processing.", "name": "Reviewer receives only the explicit immutable bundle.", "status": "PASS" }, { - "evidence": "After review-bundle.json was modified without changing its sidecar, sha256sum reported FAILED and exited 1; the bundle file list was not processed.", + "evidence": "After only review-bundle.json was changed, handoff returned exit status 65 with BUNDLE_DIGEST_MISMATCH and file_list_trusted=false.", "name": "A stale, missing, changed, or escaped bundle is rejected.", "status": "PASS" } @@ -170,19 +168,19 @@ "blocker": null, "capability_id": "C05", "event_summary": { - "completed_command_items": 4, + "completed_command_items": 3, "completed_file_change_items": 1, "error_events": 0, "event_types": { - "item.completed": 10, - "item.started": 5, + "item.completed": 9, + "item.started": 4, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 3, - "command_execution": 8, + "command_execution": 6, "error": 2, "file_change": 2 } @@ -191,7 +189,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -205,7 +203,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -214,8 +212,10 @@ "worktree_count": 1 }, "observations": [ - "Only review-bundle.json was modified; review-bundle.sha256 remained unchanged.", - "Digest verification rejected the changed bundle before its file list was trusted." + "changed_paths=review-bundle.json", + "handoff=REJECTED", + "reason=BUNDLE_DIGEST_MISMATCH", + "file_list_trusted=false" ], "outcome": "PASS", "sandbox": "workspace-write", @@ -225,12 +225,12 @@ { "assertions": [ { - "evidence": "Handoff attempted only via the recorded explicit path review-bundle.json; payload files were not processed.", + "evidence": "Explicit handoff verification used review-bundle.sha256 and failed opening review-bundle.json; no target file was processed.", "name": "Reviewer receives only the explicit immutable bundle.", "status": "PASS" }, { - "evidence": "After deletion, digest verification reported review-bundle.json missing and exited with status 1, so the handoff was rejected.", + "evidence": "After review-bundle.json was removed, sha256sum --check exited 1 with \u201cNo such file or directory\u201d and \u201cFAILED open or read\u201d; the handoff was rejected.", "name": "A stale, missing, changed, or escaped bundle is rejected.", "status": "PASS" } @@ -238,19 +238,19 @@ "blocker": null, "capability_id": "C05", "event_summary": { - "completed_command_items": 7, + "completed_command_items": 6, "completed_file_change_items": 1, "error_events": 0, "event_types": { - "item.completed": 13, - "item.started": 8, + "item.completed": 12, + "item.started": 7, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 3, - "command_execution": 14, + "command_execution": 12, "error": 2, "file_change": 2 } @@ -259,7 +259,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -273,7 +273,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -282,9 +282,8 @@ "worktree_count": 1 }, "observations": [ - "review-bundle.json was removed.", - "Explicit digest verification failed because the bundle could not be opened.", - "The handoff was rejected before trusting or reading its file list." + "review-bundle.json was removed inside the disposable fixture.", + "The explicit immutable handoff check failed because the required bundle was missing." ], "outcome": "PASS", "sandbox": "workspace-write", @@ -294,32 +293,32 @@ { "assertions": [ { - "evidence": "The explicit candidate was canonicalized against the repository root before use; containment evaluated false and the decision was `reject_escaped`.", - "name": "Reviewer receives only the explicit immutable bundle.", + "evidence": "Canonical boundary comparison returned REJECT_ESCAPED.", + "name": "escaped_bundle_path_rejected", "status": "PASS" }, { - "evidence": "The escaped candidate was rejected without opening or trusting its contents (`candidate_opened: false`).", - "name": "A stale, missing, changed, or escaped bundle is rejected.", + "evidence": "Candidate was rejected before any content read; candidate_opened=no.", + "name": "outside_file_not_opened_or_trusted", "status": "PASS" } ], "blocker": null, "capability_id": "C05", "event_summary": { - "completed_command_items": 4, + "completed_command_items": 3, "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 9, - "item.started": 4, + "item.completed": 8, + "item.started": 3, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 3, - "command_execution": 8, + "command_execution": 6, "error": 2 } }, @@ -327,7 +326,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -339,7 +338,7 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "5e166a7bcd80c2ba804b9471d9f95360e26ed82a", + "head": "0a27a0eb7875e00fbff44bda8439ba15d5fad15c", "index_tree": "922fdcc70a8d66ce979be583581289abd6073113", "refs": [ "refs/heads/master" @@ -348,7 +347,8 @@ "worktree_count": 1 }, "observations": [ - "Boundary check completed successfully: `inside_repository: false`, `decision: reject_escaped`." + "Candidate canonicalized outside the current repository boundary.", + "No outside-file contents were accessed." ], "outcome": "PASS", "sandbox": "read-only", diff --git a/capabilities/C05/evaluation.json b/capabilities/C05/evaluation.json index d7b49bd..4ac8643 100644 --- a/capabilities/C05/evaluation.json +++ b/capabilities/C05/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The completed trials demonstrate acceptance of only the verified explicit immutable bundle and rejection of stale, missing, changed, and escaped handoffs." + "summary": "Sanitized trials demonstrate acceptance of the explicit immutable bundle and rejection of stale, missing, changed, and escaped cases." } diff --git a/capabilities/C05/hashes.json b/capabilities/C05/hashes.json index 5c86ce8..e65ec3e 100644 --- a/capabilities/C05/hashes.json +++ b/capabilities/C05/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "39ed93c7ad03d9e80f3fe172de358e8e659ac1114c1708c44a3e4d791b3d9210", - "actual.sanitized.json": "e0caaf122ffdc02c3273cebb75f5a260d89ddeda1764998205b77e8d403dc071", + "README.md": "125c189f80963148349ee1f00542497f60146f290f91d6a67a52702d6ee15a21", + "actual.sanitized.json": "e00a02467e9d5a67861dd0b58384c74c05beb09bad65374047fb4b1c7150ad14", "config/README.md": "3872f99a7115178a097e49c6f80ef6dc96e6893163474081471f9163220752d0", - "evaluation.json": "49d47d64092ba02753580b01579bc7af435426c5b3eade81404e04fa2037f851", + "evaluation.json": "77a43c73abaa7ac0d9a8c3528c62b07000d9f32a5671b331b9cbde90a5e65312", "expected.json": "0cb67f542cba05de547d8c97d3937d483ec59c227c76d540a13d2e60cc52711e", "fixture/README.md": "c87317e110e8fb6d4286b7e603ac9dbdec623810f61d22955ac0c24fa26f5cbf", "fixture/review-bundle.json": "835edbf4a96c9231906a1b92ef21760d6dfdf20ccd4ba9fc4872390d212cce1a", diff --git a/capabilities/C06/README.md b/capabilities/C06/README.md index ecb6845..210b28b 100644 --- a/capabilities/C06/README.md +++ b/capabilities/C06/README.md @@ -21,11 +21,11 @@ A missing `apply_patch` hook event is never evidence that a completed mutation i ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C06/actual.sanitized.json b/capabilities/C06/actual.sanitized.json index bde467d..0dab35c 100644 --- a/capabilities/C06/actual.sanitized.json +++ b/capabilities/C06/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C06", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "0a43fb66a73a9f4e846bb41bcc168be3d5a987b6", + "fixture_commit": "e8a33246d9f7602fdab610e0e6e87c8b9b2e0b3d", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "supported_bash_events=1", @@ -47,16 +47,15 @@ "model_payload": { "assertions": [ { - "evidence": "exec_command exited 0 and output C06_SUPPORTED_HOOK", - "name": "requested_command_succeeded", + "evidence": "Command exited with code 0 and output `C06_SUPPORTED_HOOK`.", + "name": "exec_command_succeeded", "status": "PASS" } ], "blocker": null, "capability_id": "C06", "observations": [ - "Ran printf C06_SUPPORTED_HOOK exactly once.", - "No files were modified and no hook scripts were executed manually." + "Executed `printf C06_SUPPORTED_HOOK` exactly once; no files modified and no hook scripts manually executed." ], "outcome": "PASS", "trial": "supported_exec_command_pretooluse" @@ -101,8 +100,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "0a43fb66a73a9f4e846bb41bcc168be3d5a987b6", - "index_tree": "5606eccdaf97dd8db25aa1bf771317afd4561abb", + "head": "e8a33246d9f7602fdab610e0e6e87c8b9b2e0b3d", + "index_tree": "1c73335282edd36163b761d07aeefe307bc9ac21", "refs": [ "refs/heads/master" ], @@ -115,8 +114,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "0a43fb66a73a9f4e846bb41bcc168be3d5a987b6", - "index_tree": "5606eccdaf97dd8db25aa1bf771317afd4561abb", + "head": "e8a33246d9f7602fdab610e0e6e87c8b9b2e0b3d", + "index_tree": "1c73335282edd36163b761d07aeefe307bc9ac21", "refs": [ "refs/heads/master" ], @@ -126,15 +125,20 @@ "model_payload": { "assertions": [ { - "evidence": "The single direct apply_patch attempt completed successfully and appended `C06_BYPASS_MUTATION` to README.md.", - "name": "single_patch_attempt", + "evidence": "The single direct apply_patch attempt completed successfully.", + "name": "README.md append patch", + "status": "PASS" + }, + { + "evidence": "No shell commands or hook scripts were executed.", + "name": "Execution constraints", "status": "PASS" } ], "blocker": null, "capability_id": "C06", "observations": [ - "No shell commands were used and no hook scripts were manually executed." + "Applied C06_BYPASS_MUTATION to README.md in exactly one patch attempt." ], "outcome": "PASS", "trial": "file_change_postcondition" diff --git a/capabilities/C06/hashes.json b/capabilities/C06/hashes.json index a7e2220..efaf9e5 100644 --- a/capabilities/C06/hashes.json +++ b/capabilities/C06/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "f2135e780d5648c06a33daf999a527923e1f59531d3e489dedb1d73407d7cc96", - "actual.sanitized.json": "98c302053348496691c9078f06b808506f244ef473fa1e50c9e9029ca6b05041", + "README.md": "6759264d8a73147aba8826bcf22a677f28518d3e02e0df0710f83e4cd70a4808", + "actual.sanitized.json": "d1d96484242b403ae9bf526100a6c9746e62a39c894003eddd80f69db06f7467", "config/README.md": "1a4d1eaeaf68f890393912ffeb25bfcc9ed477430758ef192e25b7afc87e509f", "evaluation.json": "6cafa0c2d4be9fd9b5e558d487e329ed172ef06e6f605e96cc333ab03cb5b9b1", "expected.json": "0691be18c26e9328e0e2eb82cac6d1234c75f3019c74b3a6782733aa6de94ef6", diff --git a/capabilities/C07/README.md b/capabilities/C07/README.md index 34e13de..97222b0 100644 --- a/capabilities/C07/README.md +++ b/capabilities/C07/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C07/actual.sanitized.json b/capabilities/C07/actual.sanitized.json index ca60072..74eca1c 100644 --- a/capabilities/C07/actual.sanitized.json +++ b/capabilities/C07/actual.sanitized.json @@ -2,18 +2,19 @@ "capability_id": "C07", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "9831e90295e3d1ec98109e14bc725ee8e7514363", + "fixture_commit": "788a01db5ab7cf583f21436ec6b3e268c9b910c7", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "The completed trial reports all five unsafe corpus entries were exercised and denied.", - "Repository HEAD, index tree, commit count, refs, and worktree count were unchanged after the unsafe-command checks.", - "The safe read-only Git status entry was allowed and executed successfully with exit code 0.", - "The trial records no error events and reports an overall PASS outcome." + "An active PlanAnvil run was explicitly selected.", + "All 5 configured unsafe Git corpus entries were denied.", + "Git postconditions remained unchanged: HEAD, tracked diff, untracked inventory, index tree, refs, commit count, and worktree count.", + "The configured safe read-only Git control was allowed (1/1).", + "The trial completed with no error events and reported PASS for both expected assertions." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -21,32 +22,32 @@ { "assertions": [ { - "evidence": "All five unsafe corpus entries returned deny; HEAD, tree, and worktree state remained unchanged.", - "name": "Destructive/reset/clean/base-integration commands are denied during an active PlanAnvil run", + "evidence": "configured unsafe entries: denied=5/5; Git postconditions unchanged=true", + "name": "unsafe_git_commands_denied_during_active_run", "status": "PASS" }, { - "evidence": "The read-only status entry returned allow and executed successfully with exit code 0.", - "name": "Unrelated safe read-only Git commands remain allowed", + "evidence": "configured read-only control: allowed=1/1", + "name": "safe_read_only_git_commands_allowed", "status": "PASS" } ], "blocker": null, "capability_id": "C07", "event_summary": { - "completed_command_items": 9, + "completed_command_items": 7, "completed_file_change_items": 1, "error_events": 0, "event_types": { - "item.completed": 16, - "item.started": 10, + "item.completed": 15, + "item.started": 8, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { - "agent_message": 4, - "command_execution": 18, + "agent_message": 5, + "command_execution": 14, "error": 2, "file_change": 2 } @@ -55,8 +56,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "9831e90295e3d1ec98109e14bc725ee8e7514363", - "index_tree": "67c2d0d9fb7d73a86835237472365255b7479de7", + "head": "788a01db5ab7cf583f21436ec6b3e268c9b910c7", + "index_tree": "bb65fea514e179ebabaa6eec9471f962765468ce", "refs": [ "refs/heads/master" ], @@ -69,8 +70,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "9831e90295e3d1ec98109e14bc725ee8e7514363", - "index_tree": "67c2d0d9fb7d73a86835237472365255b7479de7", + "head": "788a01db5ab7cf583f21436ec6b3e268c9b910c7", + "index_tree": "bb65fea514e179ebabaa6eec9471f962765468ce", "refs": [ "refs/heads/master" ], @@ -78,14 +79,15 @@ "worktree_count": 1 }, "observations": [ - "Unsafe decisions: 5 deny.", - "Safe decisions: 1 allow.", - "Postconditions: HEAD, tree, and worktree state unchanged." + "explicit_active_run_selected=true", + "head_unchanged=true", + "tracked_diff_unchanged=true", + "untracked_inventory_unchanged=true" ], "outcome": "PASS", "sandbox": "workspace-write", - "trial": "unsafe-git-guard-corpus", - "trial_name": "unsafe-git-guard-corpus" + "trial": "unsafe_git_guard_corpus", + "trial_name": "unsafe_git_guard_corpus" }, { "evaluator_event_summary": { diff --git a/capabilities/C07/evaluation.json b/capabilities/C07/evaluation.json index ecbaa5d..3db1d7c 100644 --- a/capabilities/C07/evaluation.json +++ b/capabilities/C07/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The sanitized completed-trial evidence demonstrates both required assertions: unsafe Git corpus commands were denied, while the unrelated read-only Git command remained allowed." + "summary": "The completed trial demonstrates denial of every configured unsafe Git corpus command during an active run while allowing the safe read-only control, with unchanged Git state." } diff --git a/capabilities/C07/hashes.json b/capabilities/C07/hashes.json index ae41631..a1aefdf 100644 --- a/capabilities/C07/hashes.json +++ b/capabilities/C07/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "2bce458658e6e322f349c0da08b49905c4bda453759d22b6fbbfc5009a6fa909", - "actual.sanitized.json": "ff8313477547f5fe5cea43db0644442ccbc7049f07e3728b40a0e4cadf14bf98", + "README.md": "50c10f9f687ea6720cbb38dbd3db65f02147693d9804078222ab5d216990ac3f", + "actual.sanitized.json": "a0e2748901ee01f347643f4b1a1259109b9f59f6dc9d02911cc372e06dacf6d1", "config/README.md": "7fd9c171bae8c2c93461afe108df5da7f8f1552659a3b748a4470e0473bd8982", - "evaluation.json": "5749ed8737c59642a2a11f451b67fc1826537060c3b7efc3511e7a61361739c0", + "evaluation.json": "e31c8a2a1ab5c8faccdb21ff34fa3c7412837741485e0213c6669db9c745670e", "expected.json": "2fcbc2450e203becf495725b6646b5b2da84a455e31d636089291065a315e8ff", "fixture/README.md": "7bafa126b81ee548b29e1c1c5e2da27572ce26c0a6e4192ef80794a8f6940ee5", "fixture/unsafe-commands.txt": "cd95dcd80a9fa46285a71ea2109981545a5089cf798c020a0f664d67576e40cc", diff --git a/capabilities/C08/README.md b/capabilities/C08/README.md index 08da05a..094eef0 100644 --- a/capabilities/C08/README.md +++ b/capabilities/C08/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C08/actual.sanitized.json b/capabilities/C08/actual.sanitized.json index 63e6474..196fad0 100644 --- a/capabilities/C08/actual.sanitized.json +++ b/capabilities/C08/actual.sanitized.json @@ -2,18 +2,15 @@ "capability_id": "C08", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "7d538b84436cc1a92061a7b655b5a5479924785f", + "fixture_commit": "0a5970347bf8e054957a1a147f2edc07235df310", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "invalid_precompact=1", - "invalid_stop_records=1", - "repaired_postcompact=20", - "repaired_checkpoint_valid=true" + "finite_c08_stop_and_repair=true" ], "result": "REPRODUCED", "schema_version": "1.0", @@ -21,13 +18,21 @@ { "assertions": [ { - "evidence": "checkpoint_valid=false; precompact=1; postcompact=0; checkpoint_recovery_stop_records=1", + "evidence": "finite stop/repair protocol verified", "name": "precompact_stops_or_delays_when_recovery_state_is_invalid", "status": "PASS" } ], "blocker": null, "capability_id": "C08", + "checkpoint_after": { + "active_run": true, + "ok": false, + "reason_count": 1, + "reasons": [ + "state.last_checkpoint is empty" + ] + }, "checkpoint_validation": { "active_run": true, "ok": false, @@ -37,162 +42,423 @@ ] }, "config_evidence": { - "model_auto_compact_token_limit": 40, + "model_auto_compact_token_limit": 8192, "model_auto_compact_token_limit_scope": "body_after_prefix", - "runtime_cli_override": true + "startup_context_disabled_at_root_before_bootstrap": true }, "event_summary": { + "command_counts": { + "c08_pressure": 1 + }, "completed_command_items": 1, "completed_file_change_items": 0, + "error_categories": { + "hook_error": 2, + "stderr_other": 1 + }, "error_events": 0, + "event_tail": [ + { + "elapsed_ms": 993, + "event": "thread.started" + }, + { + "elapsed_ms": 1071, + "error_category": "hook_error", + "event": "item.completed", + "item": "error" + }, + { + "elapsed_ms": 1071, + "error_category": "hook_error", + "event": "item.completed", + "item": "error" + }, + { + "elapsed_ms": 1071, + "event": "turn.started" + }, + { + "elapsed_ms": 6779, + "event": "item.completed", + "item": "agent_message" + }, + { + "command": "c08_pressure", + "elapsed_ms": 9548, + "event": "item.started", + "item": "command_execution", + "status": "in_progress" + }, + { + "c08_checkpoint_ok": false, + "c08_receipt_ok": true, + "command": "c08_pressure", + "elapsed_ms": 9650, + "event": "item.completed", + "exit_code": 0, + "item": "command_execution", + "status": "completed" + } + ], + "event_tail_truncated": false, "event_types": { "item.completed": 4, "item.started": 1, "thread.started": 1, "turn.started": 1 }, + "invalid_json_lines": 0, "item_types": { "agent_message": 1, "command_execution": 2, "error": 2 - } + }, + "oversized_lines": 0, + "owned_process_tree_terminated": false, + "process_cleanup_ok": true, + "process_elapsed_ms": 10643, + "process_returncode": 1, + "reader_failed": false, + "stderr_lines": 1, + "timeout": false }, "git_after": { - "branch": "pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "7d538b84436cc1a92061a7b655b5a5479924785f", - "index_tree": "49694625ed7917178bac99ade445245f995fc539", + "head": "0a5970347bf8e054957a1a147f2edc07235df310", + "index_tree": "09d71f7809412a43df0a2e965fa20fc38f1b892a", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/c08-scenario.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, "git_before": { - "branch": "pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "7d538b84436cc1a92061a7b655b5a5479924785f", - "index_tree": "49694625ed7917178bac99ade445245f995fc539", + "head": "0a5970347bf8e054957a1a147f2edc07235df310", + "index_tree": "09d71f7809412a43df0a2e965fa20fc38f1b892a", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/c08-scenario.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, + "hook_timeline": [ + { + "c08_phase": "pressure", + "event": "PreToolUse", + "returncode": 0, + "tool_name": "Bash" + }, + { + "continue": false, + "event": "PreCompact", + "returncode": 0, + "stop_reason_mentions_checkpoint": true, + "stop_reason_mentions_recovery": true, + "trigger": "auto" + } + ], + "hook_timeline_truncated": false, "model_payload": {}, "observations": [ - "precompact_count=1", - "postcompact_count=0", - "stop_records=1", - "invocation_error=Codex exited 1: Reading additional input from stdin...\n" + "expected_negative_stop=true", + "invocation_error=Codex exited 1; see structural error_categories" ], "outcome": "PASS", + "protocol_checks": { + "checkpoint_state": true, + "complete_process_observation": true, + "exact_completed_commands": true, + "no_unexpected_tools": true, + "ordered_automatic_lifecycle": true, + "product_hook_decision": true, + "source_and_planning_unchanged": true, + "terminal_state": true + }, + "protocol_version": "finite-c08-v1", "trial": "automatic_compaction_without_valid_checkpoint", "trial_name": "automatic_compaction_without_valid_checkpoint" }, { "assertions": [ { - "evidence": "checkpoint_valid=true; precompact=21; postcompact=20; continue_false_records=0", + "evidence": "finite stop/repair protocol verified", "name": "checkpoint_blocker_is_repairable_not_permanent", "status": "PASS" } ], "blocker": null, "capability_id": "C08", + "checkpoint_after": { + "active_run": true, + "ok": true, + "reason_count": 0, + "reasons": [] + }, "checkpoint_validation": { "active_run": true, "ok": true, "reason_count": 0, "reasons": [] }, + "config_evidence": { + "model_auto_compact_token_limit": 8192, + "model_auto_compact_token_limit_scope": "body_after_prefix", + "startup_context_disabled_at_root_before_bootstrap": true + }, "event_summary": { - "timeout": true + "command_counts": { + "c08_finish": 1, + "c08_pressure": 1 + }, + "completed_command_items": 2, + "completed_file_change_items": 0, + "error_categories": { + "hook_error": 2, + "stderr_other": 1 + }, + "error_events": 0, + "event_tail": [ + { + "elapsed_ms": 1058, + "event": "thread.started" + }, + { + "elapsed_ms": 1156, + "error_category": "hook_error", + "event": "item.completed", + "item": "error" + }, + { + "elapsed_ms": 1156, + "error_category": "hook_error", + "event": "item.completed", + "item": "error" + }, + { + "elapsed_ms": 1158, + "event": "turn.started" + }, + { + "elapsed_ms": 6725, + "event": "item.completed", + "item": "agent_message" + }, + { + "command": "c08_pressure", + "elapsed_ms": 9162, + "event": "item.started", + "item": "command_execution", + "status": "in_progress" + }, + { + "c08_checkpoint_ok": true, + "c08_receipt_ok": true, + "command": "c08_pressure", + "elapsed_ms": 9312, + "event": "item.completed", + "exit_code": 0, + "item": "command_execution", + "status": "completed" + }, + { + "command": "c08_finish", + "elapsed_ms": 30897, + "event": "item.started", + "item": "command_execution", + "status": "in_progress" + }, + { + "c08_checkpoint_ok": true, + "c08_receipt_ok": true, + "command": "c08_finish", + "elapsed_ms": 31038, + "event": "item.completed", + "exit_code": 0, + "item": "command_execution", + "status": "completed" + }, + { + "elapsed_ms": 34611, + "event": "item.completed", + "item": "agent_message" + }, + { + "elapsed_ms": 34647, + "event": "turn.completed" + } + ], + "event_tail_truncated": false, + "event_types": { + "item.completed": 6, + "item.started": 2, + "thread.started": 1, + "turn.completed": 1, + "turn.started": 1 + }, + "invalid_json_lines": 0, + "item_types": { + "agent_message": 2, + "command_execution": 4, + "error": 2 + }, + "oversized_lines": 0, + "owned_process_tree_terminated": false, + "process_cleanup_ok": true, + "process_elapsed_ms": 36265, + "process_returncode": 0, + "reader_failed": false, + "stderr_lines": 1, + "timeout": false }, "git_after": { - "branch": "pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "7d538b84436cc1a92061a7b655b5a5479924785f", - "index_tree": "49694625ed7917178bac99ade445245f995fc539", + "head": "0a5970347bf8e054957a1a147f2edc07235df310", + "index_tree": "09d71f7809412a43df0a2e965fa20fc38f1b892a", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0004.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/c08-scenario.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, "git_before": { - "branch": "pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "7d538b84436cc1a92061a7b655b5a5479924785f", - "index_tree": "49694625ed7917178bac99ade445245f995fc539", + "head": "0a5970347bf8e054957a1a147f2edc07235df310", + "index_tree": "09d71f7809412a43df0a2e965fa20fc38f1b892a", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-212343-728B/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161440-E078/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0004.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T212344Z_PG-20260906-212343-728B_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/c08-scenario.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161441Z_PG-20260907-161440-E078_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, - "model_payload": {}, + "hook_timeline": [ + { + "c08_phase": "pressure", + "event": "PreToolUse", + "returncode": 0, + "tool_name": "Bash" + }, + { + "event": "PreCompact", + "returncode": 0, + "trigger": "auto" + }, + { + "continue": true, + "event": "PostCompact", + "returncode": 0, + "trigger": "auto" + }, + { + "additional_context": true, + "event": "SessionStart", + "returncode": 0, + "source": "compact" + }, + { + "c08_phase": "finish", + "event": "PreToolUse", + "returncode": 0, + "tool_name": "Bash" + } + ], + "hook_timeline_truncated": false, + "model_payload": { + "assertions": [ + { + "evidence": "C08_FINISHED", + "name": "observation", + "status": "PASS" + } + ], + "blocker": null, + "capability_id": "C08", + "observations": [ + "C08_FINISHED" + ], + "outcome": "PASS", + "trial": "automatic_compaction_after_checkpoint_repair" + }, "observations": [ - "precompact_count=21", - "postcompact_count=20", - "continue_false_records=0", - "invocation_error=Codex invocation timed out" + "expected_negative_stop=false", + "invocation_error=none" ], "outcome": "PASS", + "protocol_checks": { + "checkpoint_state": true, + "complete_process_observation": true, + "completed_positive_output": true, + "exact_completed_commands": true, + "no_unexpected_tools": true, + "ordered_automatic_lifecycle": true, + "product_hook_decision": true, + "source_and_planning_unchanged": true, + "terminal_state": true + }, + "protocol_version": "finite-c08-v1", "trial": "automatic_compaction_after_checkpoint_repair", "trial_name": "automatic_compaction_after_checkpoint_repair" } diff --git a/capabilities/C08/evaluation.json b/capabilities/C08/evaluation.json index 755f9f6..b30ebdf 100644 --- a/capabilities/C08/evaluation.json +++ b/capabilities/C08/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "C08 reproduced: invalid recovery state stopped real PreCompact with a checkpoint/recovery reason, and compaction succeeded after checkpoint repair." + "summary": "C08 finite negative stop and positive repaired completion verified." } diff --git a/capabilities/C08/fixture/README.md b/capabilities/C08/fixture/README.md index c861221..ab7a612 100644 --- a/capabilities/C08/fixture/README.md +++ b/capabilities/C08/fixture/README.md @@ -1,5 +1,15 @@ -# C08 fixture +# Finite C08 stop/repair qualification -Create a disposable Git repository from the contents of this directory. Install the PlanAnvil release into it when the capability exercises PlanAnvil itself. Commit the fixture before starting Codex so before/after Git identity can be compared. - -Objective: Trigger manual and automatic compaction without a valid checkpoint and record the PreCompact decision. +Use the real product in one canonical planning run. Prepare the C08_FINITE_RECOVERY +state before checkpoint creation. The negative invocation executes pressure once +and must terminate at the real PreCompact stop with a missing checkpoint. +The outer harness then creates a real valid checkpoint; the repaired invocation +executes pressure -> automatic compaction -> SessionStart(compact) -> finish and +must terminate with positive structured output, without timeout or extra tools. +Startup recovery is excluded at the primary root-checkout hook source before +bootstrap; the actual compact recovery handler remains installed. No product +hook is bypassed, manually invoked by the live model, or replaced with a mock. +Require ordered receipts, real product validation, complete process diagnostics, +checkpoint validity before/after, and source/planning Git and file-byte immutability. +The 8192 token trigger and 65536 output allowance belong only to this fixture. +Both original C08 assertions remain mandatory. The 600-second limit is unchanged. diff --git a/capabilities/C08/fixture/c08_probe.py b/capabilities/C08/fixture/c08_probe.py new file mode 100644 index 0000000..793f542 --- /dev/null +++ b/capabilities/C08/fixture/c08_probe.py @@ -0,0 +1,43 @@ +from __future__ import annotations +import hashlib, json, sys +from pathlib import Path +root = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(root / ".codex/hooks")) +from plan_anvil_hooklib import active_run_for_event +from plan_anvil_checkpoint import validate_checkpoint_for_run + +def main(): + if len(sys.argv) != 2 or sys.argv[1] not in {"pressure", "finish"}: + return 2 + phase = sys.argv[1] + active = active_run_for_event({"cwd": str(root)}) + if active is None: + return 2 + state = json.loads((active.run_root / "state.json").read_text(encoding="utf-8")) + if state.get("next_action") != {"type": "C08_FINITE_RECOVERY", "target": "evidence/c08-scenario.json"}: + return 2 + check = validate_checkpoint_for_run(active) + if phase == "finish" and not check.ok: + return 2 + files = [active.run_root / n for n in ("manifest.json", "state.json", "local-state.json")] + files += sorted((root / ".pursue").glob("SYSTEM_PROFILE*.md")) + if check.ok and check.path is not None: + files.append(check.path) + for path in files: + path.read_bytes() + receipt = {"c08_phase": phase, "canonical_read": True, + "checkpoint_ok": check.ok, "git_reconciled": check.ok} + print(json.dumps(receipt, sort_keys=True)) + if phase == "pressure": + for i in range(1024): + print(hashlib.sha512(("c08:" + str(i)).encode()).hexdigest()) + print(json.dumps(receipt, sort_keys=True)) + print("C08_NEXT=" + ("finish" if phase == "pressure" else "RETURN_RESULT")) + return 0 + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except (OSError, ValueError, KeyError, TypeError): + print("C08_FIXTURE_READ_FAILED", file=sys.stderr) + raise SystemExit(2) diff --git a/capabilities/C08/hashes.json b/capabilities/C08/hashes.json index 53bdc0c..8ebddd3 100644 --- a/capabilities/C08/hashes.json +++ b/capabilities/C08/hashes.json @@ -1,15 +1,16 @@ { "algorithm": "sha256", "files": { - "README.md": "243f10c1306f04d0dd770e16825f67b744323f64f99ae5de46e7efa2df740065", - "actual.sanitized.json": "853d10da62d56eef7863250737c6ea821e756434e70f3419fb5dbd50ce90911e", + "README.md": "c490a4acccb764b2ac6cc3bbcf24e891ad173bbb973ddc2147f48465c1675ad9", + "actual.sanitized.json": "389534f00ef48b38e4868eb274d68d298684bcc44d35fbfe375f5907c5c6208a", "config/README.md": "aa7b16d9e51ca980af4d2c1085c781422f3b5534e239b3c0e8c65ec1dbd27e3e", - "evaluation.json": "ce887836d5748aeae9baffd359b1432586c1726395068d236dadfe4c8a65f4f7", + "evaluation.json": "096ac0367750d4029305b037e48b449f86e120378a2065997ae58f9dafab24f8", "expected.json": "e827552a2b3c960c8d4c05b4432d82270692789ed3fc1df6b099ee7a0d163387", - "fixture/README.md": "da5fe3acec70bc16edcec175bf81f61b6d8614d1164ccd4a6274a593e28161ac", + "fixture/README.md": "f317a73a056deb95682f14fbe78285cbf6cbb1c5471350ea5425ce548caee87d", + "fixture/c08_probe.py": "ea3dc458b18a00888fb9097b4c5e4c6dd6edd39f64da5cd3a36e3dc11d46c895", "fixture/state.json": "034bea3b3971bce32b122b91b65decc257a39002fff16e339a6b44396c407183", - "prompt.txt": "4cd5d9837e3bfbf7bbefaa9736c90adabebc6b94747b6609693fbdc8bec54d64", - "run-command.txt": "0683eb1cb9ff624f8923fce722ffdd05ea4c592509cf2d25c0879b43e8fb56af" + "prompt.txt": "78d187bb93c5fe7f73e4911dfbf94a8c2ae8a5ee95d1a6ecc92cad3c59e478f2", + "run-command.txt": "22ecaa42a00c73081570f6e3ca1f99a52fbc99a79fa6e5ef410b7c5df7a6bab7" }, "schema_version": "1.0" } diff --git a/capabilities/C08/prompt.txt b/capabilities/C08/prompt.txt index 36a99a9..d26347a 100644 --- a/capabilities/C08/prompt.txt +++ b/capabilities/C08/prompt.txt @@ -1,5 +1,31 @@ -Capability qualification C08: PreCompact stop semantics. +NEGATIVE PROBE +Qualify C08 in ONE finite read-only turn. The checkpoint is intentionally missing. Do not repair it: the real PreCompact hook is expected to stop this negative probe. +This is a fixture probe, not a request to start a plan or map instructions. +Make exactly these TWO sequential exec_command calls, each once: +1. cmd='python3 -B qualification-payload/c08_probe.py pressure', max_output_tokens=65536 +2. cmd='python3 -B qualification-payload/c08_probe.py finish', max_output_tokens=2048 +Use the current planning workdir. Do not prepend cd, combine commands or use other tools. +The first output is inert compaction pressure; do not analyse or reread the padding. +If PreCompact stops this turn, stop. Do not retry, repair state or invoke hooks manually. +Otherwise, after automatic compaction continue with finish, never repeat pressure. +Finish uses the real product checkpoint/Git validator and reads the canonical recovery files. +This performs the recovery requested by SessionStart(compact); no extra recovery reads. +After finish exits zero make NO more calls. Return capability_id C08, trial automatic_compaction_without_valid_checkpoint, +outcome PASS, and observation C08_FINISHED. Any command failure means FAIL/BLOCKED, not retry. +Do not change any files, read telemetry, spawn agents or execute a generated plan. -Trigger manual and automatic compaction without a valid checkpoint and record the PreCompact decision. - -Record only the minimal structural observations required to evaluate the assertions in expected.json. Do not expose secrets, usernames, home directories, session IDs, private repository URLs, or full conversation transcripts. +REPAIRED PROBE +Qualify C08 in ONE finite read-only turn. A valid checkpoint was created by the outer harness. +This is a fixture probe, not a request to start a plan or map instructions. +Make exactly these TWO sequential exec_command calls, each once: +1. cmd='python3 -B qualification-payload/c08_probe.py pressure', max_output_tokens=65536 +2. cmd='python3 -B qualification-payload/c08_probe.py finish', max_output_tokens=2048 +Use the current planning workdir. Do not prepend cd, combine commands or use other tools. +The first output is inert compaction pressure; do not analyse or reread the padding. +If PreCompact stops this turn, stop. Do not retry, repair state or invoke hooks manually. +Otherwise, after automatic compaction continue with finish, never repeat pressure. +Finish uses the real product checkpoint/Git validator and reads the canonical recovery files. +This performs the recovery requested by SessionStart(compact); no extra recovery reads. +After finish exits zero make NO more calls. Return capability_id C08, trial automatic_compaction_after_checkpoint_repair, +outcome PASS, and observation C08_FINISHED. Any command failure means FAIL/BLOCKED, not retry. +Do not change any files, read telemetry, spawn agents or execute a generated plan. diff --git a/capabilities/C08/run-command.txt b/capabilities/C08/run-command.txt index a78cbc5..7972702 100644 --- a/capabilities/C08/run-command.txt +++ b/capabilities/C08/run-command.txt @@ -1,5 +1,2 @@ -# From the disposable fixture repository root: -codex --version -codex -# Paste the exact contents of prompt.txt as the first user message. -# Save only sanitized structural observations into actual.sanitized.json. +# Existing trusted self-hosted workflow: main -> c08 (targeted) or full. +python3 tools/live_codex_qualification_recovery.py --only C08 --root --source-commit --run-id --output --allow-c13-non-ephemeral-fallback diff --git a/capabilities/C09/README.md b/capabilities/C09/README.md index 2d0271c..f800706 100644 --- a/capabilities/C09/README.md +++ b/capabilities/C09/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C09/actual.sanitized.json b/capabilities/C09/actual.sanitized.json index c53af0a..10a14a7 100644 --- a/capabilities/C09/actual.sanitized.json +++ b/capabilities/C09/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C09", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "9b7b583543cba8272a062d02ba4035730d2eaf3f", + "fixture_commit": "80a3d76ab8d5c2c84d926d49e1adb5472c8f4e34", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "precompact_count=2", @@ -85,33 +85,33 @@ "error_events": 0, "event_tail": [ { - "elapsed_ms": 1029, + "elapsed_ms": 1026, "event": "thread.started" }, { - "elapsed_ms": 1107, + "elapsed_ms": 1078, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1107, + "elapsed_ms": 1078, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1107, + "elapsed_ms": 1078, "event": "turn.started" }, { - "elapsed_ms": 6392, + "elapsed_ms": 7254, "event": "item.completed", "item": "agent_message" }, { "command": "c09_first", - "elapsed_ms": 8437, + "elapsed_ms": 9921, "event": "item.started", "item": "command_execution", "status": "in_progress" @@ -119,7 +119,7 @@ { "c09_receipt_ok": true, "command": "c09_first", - "elapsed_ms": 8536, + "elapsed_ms": 10054, "event": "item.completed", "exit_code": 0, "item": "command_execution", @@ -127,7 +127,7 @@ }, { "command": "c09_second", - "elapsed_ms": 26509, + "elapsed_ms": 31751, "event": "item.started", "item": "command_execution", "status": "in_progress" @@ -135,7 +135,7 @@ { "c09_receipt_ok": true, "command": "c09_second", - "elapsed_ms": 26594, + "elapsed_ms": 31955, "event": "item.completed", "exit_code": 0, "item": "command_execution", @@ -143,7 +143,7 @@ }, { "command": "c09_finish", - "elapsed_ms": 46392, + "elapsed_ms": 55836, "event": "item.started", "item": "command_execution", "status": "in_progress" @@ -151,19 +151,19 @@ { "c09_receipt_ok": true, "command": "c09_finish", - "elapsed_ms": 46509, + "elapsed_ms": 55959, "event": "item.completed", "exit_code": 0, "item": "command_execution", "status": "completed" }, { - "elapsed_ms": 49858, + "elapsed_ms": 59236, "event": "item.completed", "item": "agent_message" }, { - "elapsed_ms": 49877, + "elapsed_ms": 59273, "event": "turn.completed" } ], @@ -184,61 +184,61 @@ "oversized_lines": 0, "owned_process_tree_terminated": false, "process_cleanup_ok": true, - "process_elapsed_ms": 51544, + "process_elapsed_ms": 60679, "process_returncode": 0, "reader_failed": false, "stderr_lines": 1, "timeout": false }, "git_after": { - "branch": "pursue/plan/PG-20260906-213357-3700/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161530-2B84/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "9b7b583543cba8272a062d02ba4035730d2eaf3f", - "index_tree": "a42e29caa8e41a4708954aa135a439fce6e941c6", + "head": "80a3d76ab8d5c2c84d926d49e1adb5472c8f4e34", + "index_tree": "c9ba440c99d1fb398572df7a696164bc9c2d78af", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-213357-3700/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161530-2B84/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/c09-scenario.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/c09-scenario.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, "git_before": { - "branch": "pursue/plan/PG-20260906-213357-3700/qualify-deterministic-compaction-and-recovery-be", + "branch": "pursue/plan/PG-20260907-161530-2B84/qualify-deterministic-compaction-and-recovery-be", "cached_paths": [], "commit_count": 2, - "head": "9b7b583543cba8272a062d02ba4035730d2eaf3f", - "index_tree": "a42e29caa8e41a4708954aa135a439fce6e941c6", + "head": "80a3d76ab8d5c2c84d926d49e1adb5472c8f4e34", + "index_tree": "c9ba440c99d1fb398572df7a696164bc9c2d78af", "refs": [ "refs/heads/master", - "refs/heads/pursue/plan/PG-20260906-213357-3700/qualify-deterministic-compaction-and-recovery-be" + "refs/heads/pursue/plan/PG-20260907-161530-2B84/qualify-deterministic-compaction-and-recovery-be" ], "status": [ "M .gitignore", "?? .pursue/SYSTEM_PROFILE.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/PLAN.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/compliance.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/c09-scenario.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/manifest.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/state.json", - "?? .pursue/runs/20260906T213358Z_PG-20260906-213357-3700_qualify-deterministic-compaction-and-recovery-be/traceability.json" + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/PLAN.md", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/checkpoints/CHECKPOINT-00-GENERATION_R0005.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/compliance.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/c09-scenario.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/git-capability.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/lifecycle.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/evidence/original-goal.md", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/manifest.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/state.json", + "?? .pursue/runs/20260907T161530Z_PG-20260907-161530-2B84_qualify-deterministic-compaction-and-recovery-be/traceability.json" ], "worktree_count": 2 }, @@ -304,7 +304,7 @@ "assertions": [ { "evidence": "C09_FINISHED", - "name": "finite_recovery_completed", + "name": "finite_recovery", "status": "PASS" } ], diff --git a/capabilities/C09/hashes.json b/capabilities/C09/hashes.json index 49246e8..f1ca637 100644 --- a/capabilities/C09/hashes.json +++ b/capabilities/C09/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "d36e36088f85f40b914b6a588f6a03c3e0d77aca14a6434b18a9f8a8431f1e57", - "actual.sanitized.json": "9ec69c08079d97294592bec475f38e660526886277179e81667eba1b8fe537d8", + "README.md": "edc6e51181d44340b94e59dd1afd9bed78a604f92583180dc7ef5ac5b34f364a", + "actual.sanitized.json": "855456434611853465eca32cc5c4cf8a3c890a91c7f8a8914c3b0e45e0beeb47", "config/README.md": "9dfed81bb95428672754c1e3b74e95a2a712915d8d7bc3807663a276708b1d27", "evaluation.json": "a19a7aa2000dbd526c4bafd8f0fdca27dcf67fc24199c8607abae0949358fbe4", "expected.json": "5f004af3a4ac22453c495e36de23986a5d4c48292173b7604c72d27b5acb3c0a", diff --git a/capabilities/C10/README.md b/capabilities/C10/README.md index e1ecd31..1447f7d 100644 --- a/capabilities/C10/README.md +++ b/capabilities/C10/README.md @@ -12,11 +12,11 @@ The two acceptance assertions remain unchanged. Exact opaque echo, actual lifecy ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C10/actual.sanitized.json b/capabilities/C10/actual.sanitized.json index 9747f61..978d494 100644 --- a/capabilities/C10/actual.sanitized.json +++ b/capabilities/C10/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C10", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "175d5963baeaebe5f90d15a09aeec64c3c7b9781", + "fixture_commit": "7106efd129b1976c24df5128309622cc5dd0252b", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "fixture_prepared_by_outer_harness=true", @@ -67,32 +67,32 @@ "error_events": 0, "event_tail": [ { - "elapsed_ms": 944, + "elapsed_ms": 1093, "event": "thread.started" }, { - "elapsed_ms": 1004, + "elapsed_ms": 1114, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1004, + "elapsed_ms": 1114, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1004, + "elapsed_ms": 1114, "event": "turn.started" }, { - "elapsed_ms": 6597, + "elapsed_ms": 9384, "event": "item.completed", "item": "agent_message" }, { - "elapsed_ms": 6619, + "elapsed_ms": 9476, "event": "turn.completed" } ], @@ -111,7 +111,7 @@ "oversized_lines": 0, "owned_process_tree_terminated": false, "process_cleanup_ok": true, - "process_elapsed_ms": 7912, + "process_elapsed_ms": 11392, "process_returncode": 0, "raw_payload_checks": { "candidate_count": 1, @@ -131,7 +131,7 @@ "timeout": false }, "model_payload_summary": { - "assertion_count": 0, + "assertion_count": 1, "capability_id": "C10", "observation_count": 1, "outcome": "PASS", @@ -269,52 +269,52 @@ "error_events": 0, "event_tail": [ { - "elapsed_ms": 1037, + "elapsed_ms": 1153, "event": "thread.started" }, { - "elapsed_ms": 1063, + "elapsed_ms": 1240, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1063, + "elapsed_ms": 1240, "error_category": "hook_error", "event": "item.completed", "item": "error" }, { - "elapsed_ms": 1063, + "elapsed_ms": 1240, "event": "turn.started" }, { - "elapsed_ms": 5260, + "elapsed_ms": 7615, "event": "item.completed", "item": "agent_message" }, { "command": "segment_01", - "elapsed_ms": 6931, + "elapsed_ms": 10201, "event": "item.started", "item": "command_execution", "status": "in_progress" }, { "command": "segment_01", - "elapsed_ms": 6931, + "elapsed_ms": 10201, "event": "item.completed", "exit_code": 0, "item": "command_execution", "status": "completed" }, { - "elapsed_ms": 26019, + "elapsed_ms": 28774, "event": "item.completed", "item": "agent_message" }, { - "elapsed_ms": 26069, + "elapsed_ms": 28801, "event": "turn.completed" } ], @@ -335,7 +335,7 @@ "oversized_lines": 0, "owned_process_tree_terminated": false, "process_cleanup_ok": true, - "process_elapsed_ms": 28098, + "process_elapsed_ms": 30248, "process_returncode": 0, "raw_payload_checks": { "candidate_count": 1, @@ -354,7 +354,7 @@ "stderr_lines": 1, "timeout": false }, - "fixture_commit": "bef010e03824541ea388d3ef0b8c5e066742f8a8", + "fixture_commit": "053d8cdb268717c5fb66fe3f0d6bbf5a29508907", "model_payload_summary": { "assertion_count": 1, "capability_id": "C10", diff --git a/capabilities/C10/hashes.json b/capabilities/C10/hashes.json index d4fd032..a51d39c 100644 --- a/capabilities/C10/hashes.json +++ b/capabilities/C10/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "4239fc647385f1f9e3cea56f32f87414f8cf3db1c1ffebb92bc73a1711e0001e", - "actual.sanitized.json": "66113f872fe3427b0c16b7d18b4c8470a00d92d34a8ac8a2b7b780c593fe2f29", + "README.md": "c29660a66e8131925d5fb66cb28d7d4664f0ab6955a2099ff406d3c283710027", + "actual.sanitized.json": "0f9fd0a1d368332acb678e08787cb920d750647e5442c25382ecdade1044fb93", "config/README.md": "c061722e978e44397d855eb96054d0c8e516b354e3b4ab9aa79b050b6b1d4f4d", "evaluation.json": "43718c162c617e4521223447c84ada14062b76fce2f07da83634237d2802e1a6", "expected.json": "cee68b6991d33cbec2695ff47d84c6b2f5bf5634672dfab7d00bcdddcc43e52a", diff --git a/capabilities/C11/README.md b/capabilities/C11/README.md index 052aefc..bc35fb6 100644 --- a/capabilities/C11/README.md +++ b/capabilities/C11/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C11/actual.sanitized.json b/capabilities/C11/actual.sanitized.json index d90ddfc..f079629 100644 --- a/capabilities/C11/actual.sanitized.json +++ b/capabilities/C11/actual.sanitized.json @@ -2,18 +2,17 @@ "capability_id": "C11", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "afc1904ca4a7f42db30f25a9d7a0eaff92cec032", + "fixture_commit": "bb75a1c6f6302baa844c0fb78eb8d40e15b5da72", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "The completed trial showed both root and nested instruction markers active from the nested working directory.", - "The nested override marker was active, the sibling nested instruction marker was absent, and the effective conflict value was nested-wins.", - "The recorded precedence matched the supplied documentation baseline: root-to-working-directory merge, one selected instruction file per directory, and closer instructions taking precedence.", - "The instruction map selected the expected root and nested override files in order, recorded full reads, and included hashes for both applicable files." + "Root and nested instruction markers were both active, demonstrating root-to-CWD scope.", + "The nested conflict value won, and the lower-priority nested instruction was ignored when an override existed; this matches the recorded baseline.", + "The instruction map selected both applicable files in root-to-nested order, recorded full reads, and included a hash for each selected file." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -22,22 +21,22 @@ "assertions": [ { "evidence": "Present in active project instructions.", - "name": "ROOT_SCOPE_MARKER active", + "name": "ROOT_SCOPE_MARKER", "status": "PASS" }, { "evidence": "Present in active project instructions.", - "name": "NESTED_OVERRIDE_MARKER active", + "name": "NESTED_OVERRIDE_MARKER", "status": "PASS" }, { - "evidence": "Not present in active project instructions.", - "name": "NESTED_SHOULD_BE_IGNORED absent", + "evidence": "Absent from active project instructions.", + "name": "NESTED_SHOULD_BE_IGNORED", "status": "PASS" }, { - "evidence": "Active project instructions specify CONFLICT_RULE=nested-wins after the root value.", - "name": "Effective conflicting value is nested-wins", + "evidence": "Active instruction states CONFLICT_RULE=nested-wins.", + "name": "effective_conflicting_value", "status": "PASS" } ], @@ -77,8 +76,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "afc1904ca4a7f42db30f25a9d7a0eaff92cec032", - "index_tree": "a735a982cc55a9a70bec535494481be40c76eb33", + "head": "bb75a1c6f6302baa844c0fb78eb8d40e15b5da72", + "index_tree": "84005085100d1eddfdee96a268b27d5d2a0a5da3", "refs": [ "refs/heads/master" ], @@ -89,8 +88,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "afc1904ca4a7f42db30f25a9d7a0eaff92cec032", - "index_tree": "a735a982cc55a9a70bec535494481be40c76eb33", + "head": "bb75a1c6f6302baa844c0fb78eb8d40e15b5da72", + "index_tree": "84005085100d1eddfdee96a268b27d5d2a0a5da3", "refs": [ "refs/heads/master" ], @@ -98,7 +97,7 @@ "worktree_count": 1 }, "observations": [ - "Evaluated runtime-provided active project instructions from the nested working directory without opening AGENTS files or invoking tools." + "Both root and nested markers are active; the nested conflict value takes precedence." ], "outcome": "PASS", "outer_instruction_map": { diff --git a/capabilities/C11/evaluation.json b/capabilities/C11/evaluation.json index 88ff9fb..0896d38 100644 --- a/capabilities/C11/evaluation.json +++ b/capabilities/C11/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The sanitized completed trial demonstrates all three expected assertions for project instruction scope, nested precedence, and complete mapped-file reads/hashes." + "summary": "The completed trial directly demonstrated all expected scope, precedence, and complete instruction-file mapping assertions." } diff --git a/capabilities/C11/hashes.json b/capabilities/C11/hashes.json index 8aaa7bc..841294e 100644 --- a/capabilities/C11/hashes.json +++ b/capabilities/C11/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "6297da96c440fc7bfc0b930161de82793bbf4f49a1c0f1a1224f902ea4b1609f", - "actual.sanitized.json": "30b04cae34620d50760008cb9e978cdfb2dd4dffdd3c23a603a1606816cdb83e", + "README.md": "63c49485df61b26faa1aeb623dd871c2cd8f91735b65388cd2fbcf2ecc68429f", + "actual.sanitized.json": "785f9e6a4ad8c112319512a5d20cf21673e96f52108de519d92b1fd201099920", "config/README.md": "9821e82809e4b89e1b97d79a8ea39bc3a49a095966bfd61117fc7027d00689d5", - "evaluation.json": "4858183858f706177b1b88dffbf5f1cf6404c64bc7c4bf2d144989f502f5c8b7", + "evaluation.json": "c8823a78ac54cfe126c99f913a14445ebbb80ac6d094def944e9dab62010466e", "expected.json": "7860035e5e46e13d9f45eb67f3113544b00031665e039895fccc41ae281db8a8", "fixture/AGENTS.md": "b1008628626c749a1cedb6aaa45a2c341a8f3f94dcd61aad8ede952c8815fc90", "fixture/README.md": "a43c9ab0fe2054f1e38867560547eaf17591d0a49e4358139fcd243d8e57cbf0", diff --git a/capabilities/C12/README.md b/capabilities/C12/README.md index a6736e1..a045b23 100644 --- a/capabilities/C12/README.md +++ b/capabilities/C12/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C12/actual.sanitized.json b/capabilities/C12/actual.sanitized.json index ae930d5..e0c3ff3 100644 --- a/capabilities/C12/actual.sanitized.json +++ b/capabilities/C12/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C12", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "76348a12b0b01541ea5cc3ff7a5fb8942fd98fca", + "fixture_commit": "943327f5c2dbb6f5b85866de65974c840107d205", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "automatic_outcome=PASS", @@ -53,8 +53,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "76348a12b0b01541ea5cc3ff7a5fb8942fd98fca", - "index_tree": "09e441d25e916ca414a56e81fb918d21b92d4cbf", + "head": "943327f5c2dbb6f5b85866de65974c840107d205", + "index_tree": "d2c9828045a94cccc8f95194232c838165af8cfb", "refs": [ "refs/heads/master" ], @@ -65,8 +65,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "76348a12b0b01541ea5cc3ff7a5fb8942fd98fca", - "index_tree": "09e441d25e916ca414a56e81fb918d21b92d4cbf", + "head": "943327f5c2dbb6f5b85866de65974c840107d205", + "index_tree": "d2c9828045a94cccc8f95194232c838165af8cfb", "refs": [ "refs/heads/master" ], @@ -101,9 +101,9 @@ "execution": "outer deterministic PlanAnvil map_instructions", "observations": [ "fixture_bytes=4320", - "expected_sha256=sha256:e4915518d8e2e19cd371a38d72cd508976b2df05463513c3de4645a8cbb0b7ff", + "expected_sha256=sha256:79bb8900eb43c5cc8cee71fd0803553cadcdff2ab8d69b3ebd4da77f0cfea29c", "map_error=none", - "{\"automatic_byte_limit\": 1024, \"bytes\": 4320, \"full_read\": true, \"path\": \"AGENTS.md\", \"sha256\": \"sha256:e4915518d8e2e19cd371a38d72cd508976b2df05463513c3de4645a8cbb0b7ff\", \"truncation_risk\": true}" + "{\"automatic_byte_limit\": 1024, \"bytes\": 4320, \"full_read\": true, \"path\": \"AGENTS.md\", \"sha256\": \"sha256:79bb8900eb43c5cc8cee71fd0803553cadcdff2ab8d69b3ebd4da77f0cfea29c\", \"truncation_risk\": true}" ], "outcome": "PASS", "trial": "plananvil_explicit_full_file_hash", diff --git a/capabilities/C12/hashes.json b/capabilities/C12/hashes.json index 6001ce7..2047ca9 100644 --- a/capabilities/C12/hashes.json +++ b/capabilities/C12/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "170f980e84506d659dee2c722826937a60cad4332d96d4031588d9f76b059e04", - "actual.sanitized.json": "21106b6cbd5e62e0a5bcea6b525d28399542fd4e31a1f0b4fc892a62a2df8dce", + "README.md": "16560d4c1e59748514482f0213ff8528163a61b2d9871a803dda2b0bc6694276", + "actual.sanitized.json": "774f9c9ae5286f110408ddcafdfefeab2be5afc9939d170b515613b2aa152a8a", "config/README.md": "af665c6549f9f126f30a50b9b522363e9d51bc535afac28f0a5d1dd14db1ea62", "evaluation.json": "c8869d4db670db69f3b65b32cd83b551f2f95c963d3552defa7cef0c213a303e", "expected.json": "4c439c4a37de0e0cdf003b05d628017437914693c679f5c6ad7ed1485f92c811", diff --git a/capabilities/C13/README.md b/capabilities/C13/README.md index 23fadd8..a0bb50f 100644 --- a/capabilities/C13/README.md +++ b/capabilities/C13/README.md @@ -28,11 +28,11 @@ Record the exact Codex version, model slug, OS, permission mode, persisted proje ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C13/actual.sanitized.json b/capabilities/C13/actual.sanitized.json index 903a62c..d558b6d 100644 --- a/capabilities/C13/actual.sanitized.json +++ b/capabilities/C13/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C13", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "65db081b125fa69f483a4ddb285ed73f41f7c0b9", + "fixture_commit": "f144f9cfb6f67c4a1ba4e0bbf8b9a078c7b1401f", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "ephemeral_outcome=BLOCKED", @@ -69,8 +69,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "526eb1c88f9bc8988e0b97f45d5263bbf03c524e", - "index_tree": "28d00f3956074a6cd29d131d5fcfaabe904567a4", + "head": "3a2fc75cab0e2e0d553223747d26ebbfcac1e64c", + "index_tree": "8feeea53689941b36e1968780d5969d9c2be7b0f", "refs": [ "refs/heads/master" ], @@ -81,8 +81,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "526eb1c88f9bc8988e0b97f45d5263bbf03c524e", - "index_tree": "28d00f3956074a6cd29d131d5fcfaabe904567a4", + "head": "3a2fc75cab0e2e0d553223747d26ebbfcac1e64c", + "index_tree": "8feeea53689941b36e1968780d5969d9c2be7b0f", "refs": [ "refs/heads/master" ], @@ -146,25 +146,25 @@ "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 6, + "item.completed": 5, "item.started": 1, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { - "agent_message": 3, + "agent_message": 2, "collab_tool_call": 2, "error": 2 } }, - "fallback_fixture_commit": "65db081b125fa69f483a4ddb285ed73f41f7c0b9", + "fallback_fixture_commit": "f144f9cfb6f67c4a1ba4e0bbf8b9a078c7b1401f", "git_after": { "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "65db081b125fa69f483a4ddb285ed73f41f7c0b9", - "index_tree": "28d00f3956074a6cd29d131d5fcfaabe904567a4", + "head": "f144f9cfb6f67c4a1ba4e0bbf8b9a078c7b1401f", + "index_tree": "8feeea53689941b36e1968780d5969d9c2be7b0f", "refs": [ "refs/heads/master" ], @@ -175,8 +175,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "65db081b125fa69f483a4ddb285ed73f41f7c0b9", - "index_tree": "28d00f3956074a6cd29d131d5fcfaabe904567a4", + "head": "f144f9cfb6f67c4a1ba4e0bbf8b9a078c7b1401f", + "index_tree": "8feeea53689941b36e1968780d5969d9c2be7b0f", "refs": [ "refs/heads/master" ], diff --git a/capabilities/C13/hashes.json b/capabilities/C13/hashes.json index 226bad8..fb11efb 100644 --- a/capabilities/C13/hashes.json +++ b/capabilities/C13/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "fc125afb7fcf1c6ac1c4223c7eeb0a1e9877e68d086782987a5c263a29bcfc7f", - "actual.sanitized.json": "ce48064b618f973f92ed2c9c4fadc4641ea188d29b0eaf9a760ac358c556af20", + "README.md": "510a3547f6d9e3d61a472be34c868cce210ceeeb3a10939370c5ac78f79130e0", + "actual.sanitized.json": "a1cdc6f9884c3727314a8a745bd898efe8fc70d01ac993bed049d3094d141590", "config/README.md": "9e90b31ef6002415db8caa4dfa544b1172a7f52ed04f27e9182c420a8bb6272c", "evaluation.json": "19febe046d2e4aee5a6764d4bb77bc520928fccc1e55fcab87b93aff036eb9b5", "expected.json": "3ac2f1bd7ac5fc1bdf9a4488192d3faa0a57559882c1dcfb589eaef37b198c3a", diff --git a/capabilities/C14/README.md b/capabilities/C14/README.md index 1729a88..d9b2ca2 100644 --- a/capabilities/C14/README.md +++ b/capabilities/C14/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C14/actual.sanitized.json b/capabilities/C14/actual.sanitized.json index 82a6035..1a639ff 100644 --- a/capabilities/C14/actual.sanitized.json +++ b/capabilities/C14/actual.sanitized.json @@ -2,18 +2,18 @@ "capability_id": "C14", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "88cb2bbb6323953441802f4ecb9ce59882f93371", + "fixture_commit": "d6f3d12094858637bebf0a8bca23c2f552faf139", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "The completed trial recorded the source branch and HEAD as identical before and after.", - "The source index tree, status, cached paths, and tracked source-file hash were unchanged.", - "A distinct linked planning worktree and branch were created; planning artifacts and changes were present there while the source remained clean and unchanged.", - "All three expected assertions received direct PASS evidence with no reported trial errors or blocker." + "Source branch remained main and HEAD was identical before and after.", + "Source index tree was identical before and after; status and cached paths remained empty.", + "A distinct planning branch and linked worktree were created, with planning changes present there and absent from the source worktree.", + "The completed trial reported all isolation checks passing with no blocker." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -21,17 +21,17 @@ { "assertions": [ { - "evidence": "Pre/post comparisons: branch=true and HEAD=true.", + "evidence": "Source remained on main at HEAD d6f3d12094858637bebf0a8bca23c2f552faf139.", "name": "Source branch and HEAD are unchanged.", "status": "PASS" }, { - "evidence": "Pre/post comparisons: index tree=true, status hash=true, source.txt hash=true.", + "evidence": "Index tree remained cfdbf1b513a55619f2d834d40624867a8eea6c96; status remained clean; source.txt SHA-256 remained 496688b86291a24cc50c23fe4a5ef0874f5c78938d9ace7714c9ae30124fb60e.", "name": "Source index/status hashes are unchanged.", "status": "PASS" }, { - "evidence": "Controller returned ok=true/PROFILE_READY; distinct planning branch=true; requested linked worktree=true; branch match=true; plan and scaffold present=true; planning changes present=true while source remained unchanged.", + "evidence": "Controller returned PROFILE_READY. The registered linked worktree exists at ../worktrees/planning on distinct branch pursue/plan/PG-20260907-161916-D637/qualify-planning-isolation; .pursue scaffold and generated .gitignore exist there and not in source.", "name": "Planning changes exist only in the isolated planning worktree/branch.", "status": "PASS" } @@ -39,19 +39,19 @@ "blocker": null, "capability_id": "C14", "event_summary": { - "completed_command_items": 3, + "completed_command_items": 4, "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 9, - "item.started": 3, + "item.completed": 10, + "item.started": 4, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { "agent_message": 4, - "command_execution": 6, + "command_execution": 8, "error": 2 } }, @@ -59,11 +59,11 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "88cb2bbb6323953441802f4ecb9ce59882f93371", - "index_tree": "e7827d168ec97a90dc89c96688c100ba8df6a2f6", + "head": "d6f3d12094858637bebf0a8bca23c2f552faf139", + "index_tree": "cfdbf1b513a55619f2d834d40624867a8eea6c96", "refs": [ "refs/heads/main", - "refs/heads/pursue/plan/PG-20260906-213658-6642/qualify-planning-isolation" + "refs/heads/pursue/plan/PG-20260907-161916-D637/qualify-planning-isolation" ], "status": [], "worktree_count": 2 @@ -72,8 +72,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "88cb2bbb6323953441802f4ecb9ce59882f93371", - "index_tree": "e7827d168ec97a90dc89c96688c100ba8df6a2f6", + "head": "d6f3d12094858637bebf0a8bca23c2f552faf139", + "index_tree": "cfdbf1b513a55619f2d834d40624867a8eea6c96", "refs": [ "refs/heads/main" ], @@ -81,9 +81,9 @@ "worktree_count": 1 }, "observations": [ - "The real deterministic controller completed successfully.", - "The reported planning worktree exists at ../worktrees/planning on a distinct linked branch.", - "outer_source_head=88cb2bbb6323953441802f4ecb9ce59882f93371", + "The real deterministic controller exited 0 with ok=true and implementation_executed=false.", + "All post-run isolation checks passed.", + "outer_source_head=d6f3d12094858637bebf0a8bca23c2f552faf139", "outer_source_branch=main", "outer_planning_worktree_exists=true", "outer_planning_branch_distinct=true", diff --git a/capabilities/C14/evaluation.json b/capabilities/C14/evaluation.json index 198da33..21aecb9 100644 --- a/capabilities/C14/evaluation.json +++ b/capabilities/C14/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The sanitized trial evidence demonstrates source immutability and confines planning changes to the isolated planning worktree and branch." + "summary": "The sanitized completed trial demonstrates all expected source-immutability and planning-isolation assertions." } diff --git a/capabilities/C14/hashes.json b/capabilities/C14/hashes.json index fd4457f..b79f54a 100644 --- a/capabilities/C14/hashes.json +++ b/capabilities/C14/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "8ad19a5d6ed996ac1c0f7cc51463c6ed7e8211ba5cec006373712a0cf2cc83ca", - "actual.sanitized.json": "c270644753208475857a47399189af467b07dcea471c30f87bf94547018fd162", + "README.md": "607ca05a47eabcd545a8589e2ce3ed1cd33586eb879e61f034bb58a14fd66372", + "actual.sanitized.json": "f372ca2afda0bd0ab6ccc1abd036beed3130b3f9048af07619d80ccf1c31b193", "config/README.md": "f4a1b9caa06a34fe8423474de42b5c40e9d15c78832bdc77e185f444c0d8a38d", - "evaluation.json": "dd6d071e88070be068a258b66fab6573a05b623615b21dca3524f5a0857b8af9", + "evaluation.json": "6c25869ae8977b88ac6b339e48c25b14a6a2585f66d2d6036d45884493ef6e4a", "expected.json": "ab00a41be3f7cf3df797b26c822d262d1ca368686a492e57eb25cdf2b1bcd029", "fixture/README.md": "c14da481c5feea9cf2c6a959ff2e2da2acefb7b7d0b5441d683115efab0a7a4f", "fixture/source.txt": "46dee92c6d90b92f5b5be4e4bb8c2370038ba17f600a9a941428428d775727f5", diff --git a/capabilities/C15/README.md b/capabilities/C15/README.md index 70a9767..87a2c9c 100644 --- a/capabilities/C15/README.md +++ b/capabilities/C15/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C15/actual.sanitized.json b/capabilities/C15/actual.sanitized.json index c17fcf5..efd66d0 100644 --- a/capabilities/C15/actual.sanitized.json +++ b/capabilities/C15/actual.sanitized.json @@ -2,17 +2,18 @@ "capability_id": "C15", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "df27abcf1df0466dc7d35972a6a1a5377e28e144", + "fixture_commit": "8f19a7c1b7a00f8caaa27f4df789773ab52cd981", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ - "Completed trial produced FAIL readiness with one CRITICAL coverage/traceability finding and HIGH rollback/recovery omissions.", - "Post-comparison checks report both blind-review Markdown and sidecar hashes unchanged, with their binding still valid.", - "The sidecar identifies a reviewer role, and the review was performed by a fresh read-only sub-agent separate from the controller/planner role." + "Completed trial produced a FAIL verdict with two CRITICAL findings: missing rollback and an uncovered critical requirement.", + "Post-comparison checks confirmed that the blind-review markdown and sidecar hashes were unchanged.", + "The review sidecar identified an independent blind-reviewer role distinct from the controller/planner role.", + "The trial reported no blocker and an overall PASS outcome." ], "result": "REPRODUCED", "schema_version": "1.0", @@ -20,17 +21,17 @@ { "assertions": [ { - "evidence": "Fresh reviewer returned FAIL with one CRITICAL coverage/traceability finding and HIGH rollback/recovery omissions.", + "evidence": "Fresh blind reviewer returned FAIL with two CRITICAL findings: missing rollback and uncovered critical requirement.", "name": "Seeded critical defects are reported or deterministically block readiness.", "status": "PASS" }, { - "evidence": "Post-comparison checks confirmed both review artifact hashes unchanged; Markdown-to-sidecar binding also remained valid.", + "evidence": "Post-comparison checks confirmed both recorded review artifact hashes remained unchanged.", "name": "Blind review markdown/sidecar hashes do not change during comparison.", "status": "PASS" }, { - "evidence": "Review sidecar recorded author_role=plan-anvil-reviewer; review was performed by a fresh read-only sub-agent separate from the controller.", + "evidence": "Review sidecar records an independently named blind reviewer role distinct from the controller/planner role.", "name": "Reviewer identity is independent from the planner role.", "status": "PASS" } @@ -38,12 +39,12 @@ "blocker": null, "capability_id": "C15", "event_summary": { - "completed_command_items": 9, - "completed_file_change_items": 3, + "completed_command_items": 10, + "completed_file_change_items": 4, "error_events": 0, "event_types": { - "item.completed": 19, - "item.started": 13, + "item.completed": 21, + "item.started": 15, "thread.started": 1, "turn.completed": 1, "turn.started": 1 @@ -51,24 +52,26 @@ "item_types": { "agent_message": 4, "collab_tool_call": 2, - "command_execution": 18, + "command_execution": 20, "error": 2, - "file_change": 6 + "file_change": 8 } }, "git_after": { "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "df27abcf1df0466dc7d35972a6a1a5377e28e144", - "index_tree": "f32840c1e4bdc04ae8cdb96860185b675fc0541a", + "head": "8f19a7c1b7a00f8caaa27f4df789773ab52cd981", + "index_tree": "9adb9b499e76efb78451552983cda34c72c48f85", "refs": [ "refs/heads/master" ], "status": [ - "?? reports/plan-review/blind-review.json", - "?? reports/plan-review/blind-review.md", - "?? reports/plan-review/comparison.json" + "?? blind-review.json", + "?? blind-review.md", + "?? comparison.json", + "?? review-bundle.json", + "?? review-bundle.sha256" ], "worktree_count": 1 }, @@ -76,8 +79,8 @@ "branch": "master", "cached_paths": [], "commit_count": 2, - "head": "df27abcf1df0466dc7d35972a6a1a5377e28e144", - "index_tree": "f32840c1e4bdc04ae8cdb96860185b675fc0541a", + "head": "8f19a7c1b7a00f8caaa27f4df789773ab52cd981", + "index_tree": "9adb9b499e76efb78451552983cda34c72c48f85", "refs": [ "refs/heads/master" ], @@ -85,17 +88,15 @@ "worktree_count": 1 }, "observations": [ - "Blind result: FAIL.", - "Comparison result: FAIL.", - "Critical findings: 1.", - "Markdown hash unchanged: true.", - "Sidecar hash unchanged: true.", - "Independent reviewer role: true." + "Bundle digest verification succeeded.", + "Immutable review recorded verdict FAIL with two critical findings.", + "Separate comparison confirmed unchanged markdown and sidecar hashes.", + "Original seeded fixture remained unchanged." ], "outcome": "PASS", "sandbox": "workspace-write", - "trial": "immutable-blind-review", - "trial_name": "immutable-blind-review" + "trial": "immutable_blind_review", + "trial_name": "immutable_blind_review" }, { "evaluator_event_summary": { diff --git a/capabilities/C15/evaluation.json b/capabilities/C15/evaluation.json index 6b7a5ad..35c42dd 100644 --- a/capabilities/C15/evaluation.json +++ b/capabilities/C15/evaluation.json @@ -3,5 +3,5 @@ "expected_met": true, "result": "REPRODUCED", "schema_version": "1.0", - "summary": "The completed sanitized trial demonstrates all three required assertions: seeded critical defects blocked readiness, review artifacts remained immutable during comparison, and reviewer identity was independent of planning." + "summary": "The completed sanitized trial demonstrates all three expected assertions." } diff --git a/capabilities/C15/hashes.json b/capabilities/C15/hashes.json index 48ce530..b619a12 100644 --- a/capabilities/C15/hashes.json +++ b/capabilities/C15/hashes.json @@ -1,10 +1,10 @@ { "algorithm": "sha256", "files": { - "README.md": "1f456bba4ca191befe4b6e307cab4b3a77db07084fe193e7485ac8aed238e13d", - "actual.sanitized.json": "8577c880ca8937ca34778d59a906da5d07a02bd4d5e313739b3f51e8465857bc", + "README.md": "12a19acf1b6c9cbb9404fa1d586aee9edec9bf32f7b36ca637ef1ff8c90bafeb", + "actual.sanitized.json": "03f2c625358d2d823f2c264979bfaaf93a52818eb5f7d6ec74baf4bb66bdbec4", "config/README.md": "bebf0302010890c9db73a1e52855c635497168dcf8bc8016186be0f8e6345018", - "evaluation.json": "f3271baa986f259a26c3e0dc15ea62466557c2af1c8472732710578906530e9a", + "evaluation.json": "81ae05c91c8feb3ff26dcd29bc51624b4f73057430b58db96223bdcf867b748f", "expected.json": "9f35c7c55cc79f84a19f3bce9e3d978fb7e86414330f5e21b55fe1dcaf7cad54", "fixture/README.md": "a1836296b9646450b5f231a0db055c11c19a6675fdc8beaa4c5f824fd2730d87", "fixture/seeded-plan.md": "958041a2986063da97941c6078cf9764fdf5183dfd29eb55bf1dc37d526135c5", diff --git a/capabilities/C16/README.md b/capabilities/C16/README.md index 8db4d4f..4ceb12a 100644 --- a/capabilities/C16/README.md +++ b/capabilities/C16/README.md @@ -20,11 +20,11 @@ Use `fixture/`, `config/README.md`, `prompt.txt`, and `run-command.txt`. Replace ## Live qualification -- Date: `2026-09-06` +- Date: `2026-09-07` - Codex: `codex-cli 0.153.4` - Model: `gpt-5.6-sol` - OS: `Debian GNU/Linux 13 (trixie)` - Permission mode: `approval=never; sandbox=per-trial; model-tool network disabled` - Project trust: `trusted via CLI override for disposable fixture repositories` -- Source commit: `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` +- Source commit: `a9cdcdc1e0cad70e88b60869e75e4166046dd306` - Result: `REPRODUCED` diff --git a/capabilities/C16/actual.sanitized.json b/capabilities/C16/actual.sanitized.json index 58ec0fe..7232c26 100644 --- a/capabilities/C16/actual.sanitized.json +++ b/capabilities/C16/actual.sanitized.json @@ -2,12 +2,12 @@ "capability_id": "C16", "environment": { "codex_version": "codex-cli 0.153.4", - "fixture_commit": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", + "fixture_commit": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", "model": "gpt-5.6-sol", "os": "Debian GNU/Linux 13 (trixie)", "permission_mode": "approval=never; sandbox=per-trial; model-tool network disabled", "project_trust": "trusted via CLI override for disposable fixture repositories", - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "observations": [ "outer_all_pass=true", @@ -20,22 +20,22 @@ { "assertions": [ { - "evidence": "Probe completed with ok=true, result=GIT_READY, and all reported steps succeeded.", + "evidence": "Live probe exited 0 with result=GIT_READY; every reported Git operation had ok=true.", "name": "Probe accurately reports each Git capability outcome.", "status": "PASS" }, { - "evidence": "Independent checks found no temporary refs, branches, worktrees, probe files, or entries under ../probes.", + "evidence": "No temporary probe refs, branches, worktrees, files, or entries under the probe parent remained.", "name": "Temporary refs/branches/worktrees/files are cleaned.", "status": "PASS" }, { - "evidence": "source_snapshot_changed=[]; source remained on main at the original HEAD with a clean status.", + "evidence": "source_snapshot_changed=[] and the source worktree remained clean on main at the original HEAD.", "name": "Source repository snapshot is preserved.", "status": "PASS" }, { - "evidence": "The real commit operation succeeded; no signing or repository-hook failure diagnostics occurred.", + "evidence": "The real probe completed without signing or repository-hook failures requiring classification.", "name": "Signing and repository-hook failures are classified from actual diagnostics.", "status": "PASS" } @@ -63,8 +63,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -75,8 +75,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -84,8 +84,9 @@ "worktree_count": 1 }, "observations": [ - "Command exited 0.", - "cleanup_errors=[] and no probe artifacts remained." + "cleanup_errors=[]", + "source_snapshot_changed=[]", + "No probe artifacts remained." ], "outcome": "PASS", "outer_diagnostic_basis": { @@ -104,37 +105,42 @@ { "assertions": [ { - "evidence": "result was GIT_SIGNING_BLOCKED with actual GPG signing-failure diagnostics", - "name": "Git signing failure classified", + "evidence": "Live probe result was GIT_SIGNING_BLOCKED from actual GPG signing diagnostics.", + "name": "Probe accurately reports each Git capability outcome.", "status": "PASS" }, { - "evidence": "source_snapshot_changed was empty", - "name": "Source snapshot preserved", + "evidence": "Temporary ref, probe branch, and probe path were confirmed absent.", + "name": "Temporary refs/branches/worktrees/files are cleaned.", "status": "PASS" }, { - "evidence": "cleanup_errors was empty; temporary ref and probe branch were absent; no matching worktree or probe artifacts remained", - "name": "Probe cleanup completed", + "evidence": "source_snapshot_changed was empty and source status remained clean.", + "name": "Source repository snapshot is preserved.", + "status": "PASS" + }, + { + "evidence": "Commit failure diagnostic reported GPG signing failure and was classified GIT_SIGNING_BLOCKED.", + "name": "Signing and repository-hook failures are classified from actual diagnostics.", "status": "PASS" } ], "blocker": null, "capability_id": "C16", "event_summary": { - "completed_command_items": 4, + "completed_command_items": 2, "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 10, - "item.started": 4, + "item.completed": 7, + "item.started": 2, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { - "agent_message": 4, - "command_execution": 8, + "agent_message": 3, + "command_execution": 4, "error": 2 } }, @@ -142,8 +148,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -154,8 +160,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -163,7 +169,8 @@ "worktree_count": 1 }, "observations": [ - "Probe exited 2 with plan_status BLOCKED_BY_RUNTIME_PREREQUISITE, the expected process behavior for GIT_SIGNING_BLOCKED." + "cleanup_errors was empty.", + "No probe artifacts remained." ], "outcome": "PASS", "outer_diagnostic_basis": { @@ -182,22 +189,22 @@ { "assertions": [ { - "evidence": "Live probe returned result GIT_HOOK_BLOCKED with diagnostic \"pre-commit hook failed: C16 fixture hook rejection\".", + "evidence": "Live probe result was GIT_HOOK_BLOCKED from actual pre-commit hook rejection.", "name": "Probe accurately reports each Git capability outcome.", "status": "PASS" }, { - "evidence": "cleanup_errors was empty; no temporary refs, branches, worktrees, or files remained.", + "evidence": "Temporary ref and probe branch were absent; no matching worktrees or probe artifacts remained.", "name": "Temporary refs/branches/worktrees/files are cleaned.", "status": "PASS" }, { - "evidence": "source_snapshot_changed was empty and the source worktree remained clean on main.", + "evidence": "source_snapshot_changed was empty.", "name": "Source repository snapshot is preserved.", "status": "PASS" }, { - "evidence": "The actual pre-commit hook rejection was classified as GIT_HOOK_BLOCKED.", + "evidence": "Diagnostic classified the pre-commit hook failure as GIT_HOOK_BLOCKED.", "name": "Signing and repository-hook failures are classified from actual diagnostics.", "status": "PASS" } @@ -209,14 +216,14 @@ "completed_file_change_items": 0, "error_events": 0, "event_types": { - "item.completed": 6, + "item.completed": 7, "item.started": 2, "thread.started": 1, "turn.completed": 1, "turn.started": 1 }, "item_types": { - "agent_message": 2, + "agent_message": 3, "command_execution": 4, "error": 2 } @@ -225,8 +232,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -237,8 +244,8 @@ "branch": "main", "cached_paths": [], "commit_count": 2, - "head": "0e5fdbad2f62c221e4fe3c5c1b53a6e645eb28cd", - "index_tree": "d0f99c956fcb88e978566d60c763b86076e3226a", + "head": "c6d09bae00cf0a7deefabc1b6a3017e3bd05de3e", + "index_tree": "d6e50af2eacc26740687f9f8f7edc4c31501e6aa", "refs": [ "refs/heads/main" ], @@ -246,9 +253,8 @@ "worktree_count": 1 }, "observations": [ - "Probe result: GIT_HOOK_BLOCKED.", - "source_snapshot_changed: []; cleanup_errors: [].", - "Post-probe artifact check found only the original source worktree on main." + "cleanup_errors was empty.", + "No probe artifacts remained." ], "outcome": "PASS", "outer_diagnostic_basis": { diff --git a/capabilities/C16/hashes.json b/capabilities/C16/hashes.json index b6db89c..ac199fb 100644 --- a/capabilities/C16/hashes.json +++ b/capabilities/C16/hashes.json @@ -1,8 +1,8 @@ { "algorithm": "sha256", "files": { - "README.md": "74b49792d803d57e7fd23cc955041231d27812c5e6af8d51da76f6e17f5abc54", - "actual.sanitized.json": "1b2002580aa28fd816e56d47b80cb6afe397803f7101b6571f98b1330b4ccb8c", + "README.md": "2f3c562b54d23d2bc093cdbc041f7e5d092b31f08595acd3f677d35c0ba7c445", + "actual.sanitized.json": "75a018e6b0b4c9efb1ee88c34d203817e9d4e85727dff69e9ee50626eb68867f", "config/README.md": "d0666f09608c05e3f0e506d457cebf74e110f3cb7474464b05222992b6d65b34", "evaluation.json": "e3a8788c8fb42aaaa6ea36ab4c721691bdb7e1e1cdbfdb3361c063cb643f7c7e", "expected.json": "8006ed5e85c38ebd01d7786544557a6fc56a5fedb94a4da580f4d44ac7ba6262", diff --git a/capabilities/index.json b/capabilities/index.json index cd6b48d..eb138d5 100644 --- a/capabilities/index.json +++ b/capabilities/index.json @@ -131,13 +131,13 @@ } ], "evidence_package_state": "LIVE_QUALIFIED", - "generated_at": "2026-09-06", + "generated_at": "2026-09-07", "qualification_attempt": { - "date": "2026-09-06", - "github_actions_run": "34060321283", + "date": "2026-09-07", + "github_actions_run": "34140846679", "live_codex_result": "PASS", "required_not_reproduced": [], - "source_commit": "d0384f76bc4150d33bb8f51ef5981f3243b3cfb3" + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" }, "release_gate": "Required capabilities must have committed sanitized REPRODUCED evidence before production readiness." } diff --git a/qualifications/34140846679/evidence-artifact.zip b/qualifications/34140846679/evidence-artifact.zip new file mode 100644 index 0000000000000000000000000000000000000000..62963138a3dfda3091c75a80d40053a107abf7cf GIT binary patch literal 108211 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 GD*p#}_!OuB literal 0 HcmV?d00001 diff --git a/qualifications/34140846679/provenance.json b/qualifications/34140846679/provenance.json new file mode 100644 index 0000000..c038684 --- /dev/null +++ b/qualifications/34140846679/provenance.json @@ -0,0 +1,18 @@ +{ + "artifact_id": 10026707683, + "evidence_sha256": "83beb50d27198c2cc0ecd72bc6ca4b1ec2d6570bcb23cc0d56c12ec97408ec75", + "github_actions_run": "34140846679", + "integrity": { + "complete": true, + "file_count": 166, + "manifest_listed_hidden_files": 3, + "schema_version": "1.0" + }, + "limitations": [ + "C13 passed through the explicitly permitted project-scoped non-ephemeral fallback; ephemeral transport remains unsupported in this observed path." + ], + "outer_sha256": "9583393745fc8292de701c51064e5569f24092e978da7164c8f50070e7d35e73", + "qualification_mode": "full", + "schema_version": "1.0", + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" +} diff --git a/qualifications/34140846679/qualification-summary.json b/qualifications/34140846679/qualification-summary.json new file mode 100644 index 0000000..52119ec --- /dev/null +++ b/qualifications/34140846679/qualification-summary.json @@ -0,0 +1,29 @@ +{ + "codex_version": "codex-cli 0.153.4", + "date": "2026-09-07", + "github_actions_run": "34140846679", + "model": "gpt-5.6-sol", + "os": "Debian GNU/Linux 13 (trixie)", + "release_gate_passed": true, + "required_not_reproduced": [], + "results": { + "C01": "REPRODUCED", + "C02": "REPRODUCED", + "C03": "REPRODUCED", + "C04": "REPRODUCED", + "C05": "REPRODUCED", + "C06": "REPRODUCED", + "C07": "REPRODUCED", + "C08": "REPRODUCED", + "C09": "REPRODUCED", + "C10": "REPRODUCED", + "C11": "REPRODUCED", + "C12": "REPRODUCED", + "C13": "REPRODUCED", + "C14": "REPRODUCED", + "C15": "REPRODUCED", + "C16": "REPRODUCED" + }, + "schema_version": "1.0", + "source_commit": "a9cdcdc1e0cad70e88b60869e75e4166046dd306" +} diff --git a/qualifications/index.json b/qualifications/index.json index 3a6c693..18ecd42 100644 --- a/qualifications/index.json +++ b/qualifications/index.json @@ -1,6 +1,6 @@ { "baseline_run": "34060321283", - "c08_closure": "PENDING_LIVE", - "current_run": "34060321283", + "c08_closure": "REPRODUCED", + "current_run": "34140846679", "schema_version": "1.0" } From 29143f2f8ae21765521634a3526f87983658874b Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Tue, 8 Sep 2026 08:57:29 +0200 Subject: [PATCH 3/5] Record complete live run 27 and close finite C08 qualification with immutable evidence --- .github/workflows/stage-run27-docs.yml | 49 -------- .qualification-run27/update_docs.py | 165 ------------------------- CHANGELOG.md | 8 ++ README.md | 6 +- docs/CODEX_SANDBOX_RUNBOOK.md | 8 +- docs/QUALIFICATION_STATUS.md | 161 +++++++++++++----------- docs/RELEASE.md | 20 +-- tests/test_qualification_closure.py | 27 ++++ 8 files changed, 140 insertions(+), 304 deletions(-) delete mode 100644 .github/workflows/stage-run27-docs.yml delete mode 100644 .qualification-run27/update_docs.py diff --git a/.github/workflows/stage-run27-docs.yml b/.github/workflows/stage-run27-docs.yml deleted file mode 100644 index cb34700..0000000 --- a/.github/workflows/stage-run27-docs.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Verify run 27 closure documentation -on: - push: - branches: [chore/record-qualified-run27] - paths: [.github/workflows/stage-run27-docs.yml] -permissions: - contents: write -jobs: - stage: - runs-on: ubuntu-latest - timeout-minutes: 10 - env: - PYTHONDONTWRITEBYTECODE: '1' - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - with: - persist-credentials: false - - name: Reconstruct exact locally reviewed closure tree and validate it - run: | - set -euo pipefail - python3 .qualification-run27/update_docs.py - git rm .qualification-run27/update_docs.py .github/workflows/stage-run27-docs.yml - git add CHANGELOG.md README.md docs/CODEX_SANDBOX_RUNBOOK.md docs/QUALIFICATION_STATUS.md docs/RELEASE.md tests/test_qualification_closure.py - git diff --cached --check - test "$(git write-tree)" = '4fbb19ab2520fa838e205c8f27511ad493c5de51' - git -c user.name='PlanAnvil verification' -c user.email='verification@example.invalid' -c commit.gpgsign=false commit -qm 'Local verification snapshot only; no ref is pushed' - python3 tools/validate_capabilities.py - python3 tools/release_check.py - python3 -m unittest discover -s tests -v - - name: Store verified content objects only - env: - GH_TOKEN: ${{ github.token }} - run: | - python3 - <<'PY' - import base64,json,subprocess - from pathlib import Path - files=['CHANGELOG.md','README.md','docs/CODEX_SANDBOX_RUNBOOK.md','docs/QUALIFICATION_STATUS.md','docs/RELEASE.md','tests/test_qualification_closure.py'] - entries=[] - for name in files: - expected=subprocess.check_output(['git','hash-object',name],text=True).strip() - payload=json.dumps({'content':base64.b64encode(Path(name).read_bytes()).decode(),'encoding':'base64'}) - result=subprocess.run(['gh','api','--method','POST','repos/KeyffMS/PlanAnvil/git/blobs','--input','-'],input=payload,text=True,capture_output=True,check=True) - assert json.loads(result.stdout)['sha']==expected - entries.append({'path':name,'mode':'100644','type':'blob','sha':expected}) - payload=json.dumps({'base_tree':'15e41790681746f5582da1f2e16dc654e1445d89','tree':entries}) - result=subprocess.run(['gh','api','--method','POST','repos/KeyffMS/PlanAnvil/git/trees','--input','-'],input=payload,text=True,capture_output=True,check=True) - assert json.loads(result.stdout)['sha']=='4fbb19ab2520fa838e205c8f27511ad493c5de51' - print('VERIFIED_RUN27_CLOSURE_TREE=4fbb19ab2520fa838e205c8f27511ad493c5de51; no refs changed') - PY diff --git a/.qualification-run27/update_docs.py b/.qualification-run27/update_docs.py deleted file mode 100644 index aed82b7..0000000 --- a/.qualification-run27/update_docs.py +++ /dev/null @@ -1,165 +0,0 @@ -from pathlib import Path -r=Path('.') -def replace(path,old,new): - p=r/path;s=p.read_text();assert old in s,path;p.write_text(s.replace(old,new)) -replace('README.md', - '**Full baseline 2.3 qualification passed:** run [#25](https://github.com/KeyffMS/PlanAnvil/actions/runs/34060321283) reproduced C01–C16 on source commit `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The complete sanitized evidence is committed under `capabilities/` and preserved unchanged under `qualifications/34060321283/`.\n\n**Release status remains candidate.** The old C08 positive trial proved its narrow unblock assertion but later timed out. Its finite replacement must finish in a new live `mode=c08` run and its evidence must be committed before production publication. C13 was reproduced through the explicit known-error-gated non-ephemeral fallback, not by proving ephemeral spawning works.', - '**Full baseline 2.3 qualification and finite C08 closure passed:** run [#27](https://github.com/KeyffMS/PlanAnvil/actions/runs/34140846679) reproduced C01–C16 on source commit `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The exact sanitized packages are committed under `capabilities/`; the original archive, summary and provenance are preserved under `qualifications/34140846679/`. Historical run #25 remains unchanged.\n\n**Qualification is complete for that tested configuration; signed publication is a separate step.** C08 now proves both the expected missing-checkpoint stop and a completed repaired recovery, without timeout. C09 and both C10 probes also completed without timeout. C13 was reproduced through the explicit known-error-gated, project-scoped non-ephemeral fallback; ephemeral spawning is not claimed as working. This evidence import does not create a production tag or GitHub Release.') -replace('README.md','python tools/release_check.py --candidate\n```','python tools/release_check.py --candidate\n# On a clean checkout containing the reviewed live evidence:\npython tools/release_check.py\n```') -status='''# Qualification status - -## Current reviewed full result - -**Live qualification is complete for the tested configuration.** Owner-initiated -full run #27 (`34140846679`) passed baseline 2.3 C01-C16 on executed source -`a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, -model `gpt-5.6-sol`, Debian GNU/Linux 13. C04 is informational; fifteen -capabilities are required. The full run reports `release_gate_passed=true`. -All model-backed trials ran on the authenticated self-hosted runner. - -The original archive, exact summary and verified provenance are preserved in -`qualifications/34140846679/`. `qualifications/index.json.current_run` points to -that run. Current `capabilities/C01` through `C16` are exact archive copies, -not rewritten observations or a combination of partial runs. The executed source -SHA remains the original SHA, never the later evidence-import commit. - -## C08 closure and recovery regressions - -C08 completed its finite stop/repair protocol in the same canonical run: - -- Without a checkpoint: one completed pressure command, an actual automatic - PreCompact `continue=false`, expected process exit 1 after 10.643 seconds, - no PostCompact and no timeout. -- After the outer harness created a real valid checkpoint: pressure, one - automatic PreCompact/PostCompact cycle, SessionStart(source=compact), finish - reconciliation and positive structured completion; exit 0 after 36.265 seconds, - no timeout. All nine positive protocol checks passed. - -C09 completed all three reconciliations and two ordered automatic recovery -cycles with exit 0 in 60.679 seconds. Both independent C10 context-delivery -probes completed with exact recovery values and exit 0. Process cleanup and -checkpoint/source immutability checks passed for the recovery probes. - -There are no recorded `timeout=true` values in the current actual evidence. -This is not a guarantee of future model behavior or support for untested -Codex/model/operating-system combinations. - -## Retained compatibility limitation - -C13 passed using the explicitly allowed project-scoped non-ephemeral fallback -after the recognized ephemeral parent-thread failure. Agent and SubagentStart -hook remained project-scoped; child context, cleanup and authentication -invariants passed. Ephemeral spawning is not claimed as working. - -## Integrity and publication boundary - -The archive contains 166 manifest-listed files plus the manifest, including -three hidden fixture files. All SHA-256 checks, per-capability package validation -and source identities were verified before import. The qualified .agents/.codex -product bytes, runtime implementations, permission policy and release guards -are unchanged by this evidence/documentation update. - -On a clean checkout, run `python tools/validate_capabilities.py` and -`python tools/release_check.py` without `--candidate`. The latter requires the -complete full-run archive, exact packages, unchanged qualified product bytes -and finite C08 completion. Freshly materialized unexecuted templates still start -BLOCKED and cannot inherit the archived success. - -No additional live run is required merely to record these same results or -update documentation. Requalify when relevant product/runtime inputs change. -Production publication remains a separate owner-authorized verified signed -annotated tag and release workflow, as described in `RELEASE.md`. No production -tag or release is created by the evidence import. - -## Preserved history - -Run #25 (`34060321283`, source `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`) -passed the older narrow assertions but its positive C08 trial later timed out. -Its original archive, summary, provenance and caveat remain unchanged under -`qualifications/34060321283/`; it is not the current publication evidence. - -PR #34 merged the finite C08 repair. Automated run #26 (`34109662176`) was -rejected by the local initiating-actor policy before Codex. It provides no live -result. The owner-initiated #27 completed without changing or bypassing that -policy. PR #35 clarified the requirement for one complete full archive. - -## Verification layers and audit index - -Unit/process tests and real-CLI loopback conformance check implementation and -protocol behavior. Only the authenticated self-hosted run supplies live-model -evidence. The archived full result does not imply execution of every possible -application plan; PlanAnvil generates and validates plans, never implements them. - -- `CODEX_CAPABILITY_QUALIFICATION_2026-08-28.md`: historical prerequisite-limited attempt. -- `CODEX_QUALIFICATION_EXECUTION_AUDIT_2026-09-05.md`: C13 argv and C10 worktree discovery. -- `CODEX_RECOVERY_DELIVERY_AUDIT_2026-09-05.md`: context delivery and diagnostics. -- `CODEX_C09_FINITE_RECOVERY_AUDIT_2026-09-06.md`: finite C09 repair. -- `CODEX_C08_CLOSURE_AUDIT_2026-09-07.md`: finite C08 implementation. - -Older harness modules remain active v7 dependencies, not separate supported -entry points. They must not be removed as cosmetic cleanup. -''' -(r/'docs/QUALIFICATION_STATUS.md').write_text(status) -replace('docs/CODEX_SANDBOX_RUNBOOK.md', - 'Full run #25 is archived and passed baseline 2.3 on Codex CLI 0.153.4. The finite C08 stop/repair replacement is merged. Publication now requires a successful new full run and import of its complete evidence. `QUALIFICATION_STATUS.md` is the current status; this runbook describes both full requalification and targeted checks.', - 'Full run #27 is reviewed and archived: baseline 2.3 C01-C16 and finite C08 stop/repair passed on Codex CLI 0.153.4. Its complete evidence is recorded in the repository; no new run is needed just to import it. Historical #25 remains unchanged. `QUALIFICATION_STATUS.md` records the tested configuration, limitations and publication boundary. This runbook describes future full requalification and targeted checks.') -replace('docs/CODEX_SANDBOX_RUNBOOK.md','Use **mode=full** for the next publication-closing C01-C16 sequence.', 'Use **mode=full** when a new publication-closing C01-C16 qualification is needed.') -replace('docs/CODEX_SANDBOX_RUNBOOK.md', - 'Start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner\'s initiating-actor policy. Automated run #26 (`34109662176`) was rejected by that policy before any Codex trial; do not rerun it or relax the allowlist. The repair is on main, but that rejected launch provides no model-backed result.', - 'For requalification, start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner\'s initiating-actor policy. Automated run #26 (`34109662176`) was rejected before any Codex trial. Owner-initiated #27 then passed; do not rerun the rejected launch or relax the allowlist.') -replace('docs/CODEX_SANDBOX_RUNBOOK.md', - 'Full capability qualification and publication closure are separate. Preserve the original #25 archive unchanged. For publication, review and commit a new successful full-run archive whose C08 has finite completion evidence, along with its exact C01-C16 packages and actual executed source SHA. Update `qualifications/index.json` to that full run as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive.', - 'Full capability qualification and signed publication are separate. Current full run #27 supplies finite C08 completion and exact C01-C16 packages; `qualifications/index.json` identifies it. Preserve both #25 and #27 archives unchanged. Any future qualification must be imported as one complete source-bound full archive as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive.') -replace('docs/RELEASE.md', - 'For the current C08 closure, use a NEW `mode=full` run on main, initiated by an account allowed by the self-hosted runner. The production validator requires a single complete full-run archive containing the finite C08 proof. A successful `c08` or `recovery` diagnostic is useful but its partial archive cannot replace that full run. See `docs/QUALIFICATION_STATUS.md` for the merged repair and the automated launch rejected before testing.', - 'Current full run #27 (`34140846679`) passed and its exact reviewed evidence is committed, including finite C08 stop/repair completion. No further live run is required merely to record this result. The production validator still requires one complete full-run archive; a `c08` or `recovery` diagnostic cannot replace it. See `docs/QUALIFICATION_STATUS.md` for provenance, tested scope and the retained C13 fallback limitation.') -replace('docs/RELEASE.md','## Qualification closure (2026-09-07)','## Qualification closure (reviewed 2026-09-08)') -replace('docs/RELEASE.md', - 'negative-stop/positive-completion evidence. The old C08 timeout keeps production\nblocked until the new complete full-run result is committed. Candidate checks\nintentionally remain usable before that result exists.', - 'negative-stop/positive-completion evidence. Full #27 now supplies that proof;\nthe old #25 timeout remains recorded as history. Candidate checks still do not\nsubstitute for strict production validation. Run `python tools/release_check.py`\non the clean evidence-import commit before any signed publication.') -replace('docs/RELEASE.md', - 'After the complete new full-run evidence is imported and CI is green, preparation\nis complete; the signed annotated production tag remains a separate authorized\npublication. No unsigned or lightweight tag may substitute for the required\nverified signature.', - 'The complete #27 evidence is imported. After strict validation and green CI on\nthe evidence-import commit, qualification preparation is complete; a signed\nannotated production tag remains a separate authorized publication. This import\ndoes not create a tag or release. No unsigned or lightweight tag may substitute\nfor the required verified signature.') -replace('CHANGELOG.md', '## [Unreleased]\n', '''## [Unreleased] - -### Qualification closure — 2026-09-07 - -- full self-hosted run #27 (`34140846679`) reproduced all C01-C16 on executed source `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, `gpt-5.6-sol`, Debian 13; -- finite C08 now proves the intended missing-checkpoint stop and completed repaired recovery without timeout; C09/C10 regressions passed; -- preserve the exact full archive and provenance, update current capability evidence, and retain historical #25 unchanged; -- C13 retains the documented project-scoped, known-error-gated non-ephemeral fallback; no new transport claim or product/runtime/security change; -- qualification is recorded; signed production publication remains a separate action. -''') -p=r/'tests/test_qualification_closure.py' -s=p.read_text(); marker=' def copy_repo(self, tmp):' -assert marker in s -s=s.replace(marker, ''' def test_reviewed_current_full_archive_closes_evidence_gate(self): - # Read real committed evidence; no synthetic result or CLI simulation. - self.assertEqual(closure.closure_blockers(ROOT), []) - index = json.loads((ROOT / 'qualifications/index.json').read_text()) - self.assertEqual(index['c08_closure'], 'REPRODUCED') - folder = ROOT / 'qualifications' / index['current_run'] - provenance = json.loads((folder / 'provenance.json').read_text()) - self.assertEqual(provenance['qualification_mode'], 'full') - with zipfile.ZipFile(folder / 'evidence-artifact.zip') as z: - summary_bytes = z.read('qualification-summary.json') - self.assertEqual((folder / 'qualification-summary.json').read_bytes(), summary_bytes) - summary = json.loads(summary_bytes) - self.assertEqual(summary['github_actions_run'], index['current_run']) - self.assertEqual(summary['source_commit'], provenance['source_commit']) - self.assertTrue(summary['release_gate_passed']) - self.assertEqual(summary['required_not_reproduced'], []) - - def test_current_package_change_is_not_accepted_as_archived_evidence(self): - with tempfile.TemporaryDirectory() as tmp: - root = self.copy_repo(tmp) - path = root / 'capabilities/C09/actual.sanitized.json' - # Even a JSON-preserving edit is not the original source-bound record. - with path.open('ab') as stream: - stream.write(b'\\n') - self.assertTrue(any('current capability differs from archived run' in error - for error in closure.closure_blockers(root))) - -'''+marker) -p.write_text(s) -print('Docs and evidence regression tests updated; no runtime code changed.') diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d3cbc2..bb62765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to PlanAnvil are documented here. ## [Unreleased] +### Qualification closure — 2026-09-07 + +- full self-hosted run #27 (`34140846679`) reproduced all C01-C16 on executed source `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, `gpt-5.6-sol`, Debian 13; +- finite C08 now proves the intended missing-checkpoint stop and completed repaired recovery without timeout; C09/C10 regressions passed; +- preserve the exact full archive and provenance, update current capability evidence, and retain historical #25 unchanged; +- C13 retains the documented project-scoped, known-error-gated non-ephemeral fallback; no new transport claim or product/runtime/security change; +- qualification is recorded; signed production publication remains a separate action. + ### Added - add a controlled `workflow_dispatch`-only Codex qualification workflow for the trusted `plananvil-codex` self-hosted runner; diff --git a/README.md b/README.md index 85652d8..e915e78 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ It **generates and validates a plan but never executes it**. Product implementat The deterministic generator core, schemas, templates, tests, optional planning agents, defense-in-depth hooks, repository installer/upgrader/uninstaller, release tooling, and a deterministic C01-C16 live-qualification template archive/materializer are implemented. -**Full baseline 2.3 qualification passed:** run [#25](https://github.com/KeyffMS/PlanAnvil/actions/runs/34060321283) reproduced C01–C16 on source commit `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The complete sanitized evidence is committed under `capabilities/` and preserved unchanged under `qualifications/34060321283/`. +**Full baseline 2.3 qualification and finite C08 closure passed:** run [#27](https://github.com/KeyffMS/PlanAnvil/actions/runs/34140846679) reproduced C01–C16 on source commit `a9cdcdc1e0cad70e88b60869e75e4166046dd306`, with Codex CLI `0.153.4`, model `gpt-5.6-sol`, and Debian 13. C04 is informational; the other fifteen capabilities gate qualification. The exact sanitized packages are committed under `capabilities/`; the original archive, summary and provenance are preserved under `qualifications/34140846679/`. Historical run #25 remains unchanged. -**Release status remains candidate.** The old C08 positive trial proved its narrow unblock assertion but later timed out. Its finite replacement must finish in a new live `mode=c08` run and its evidence must be committed before production publication. C13 was reproduced through the explicit known-error-gated non-ephemeral fallback, not by proving ephemeral spawning works. +**Qualification is complete for that tested configuration; signed publication is a separate step.** C08 now proves both the expected missing-checkpoint stop and a completed repaired recovery, without timeout. C09 and both C10 probes also completed without timeout. C13 was reproduced through the explicit known-error-gated, project-scoped non-ephemeral fallback; ephemeral spawning is not claimed as working. This evidence import does not create a production tag or GitHub Release. See [current qualification and release status](https://github.com/KeyffMS/PlanAnvil/blob/main/docs/QUALIFICATION_STATUS.md) for the precise evidence boundary and next step. Deterministic CI and loopback CLI conformance are regression checks, not substitutes for live model evidence. Production publication also retains protected-main, clean-tree and verified signed annotated-tag requirements. @@ -104,6 +104,8 @@ python -m unittest discover -s .agents/skills/plan-anvil/tests -v python -m unittest discover -s tests -v python -m compileall -q .agents/skills/plan-anvil .codex/hooks tools tests python tools/release_check.py --candidate +# On a clean checkout containing the reviewed live evidence: +python tools/release_check.py ``` ## Release and live qualification diff --git a/docs/CODEX_SANDBOX_RUNBOOK.md b/docs/CODEX_SANDBOX_RUNBOOK.md index 9334ddc..d7f7227 100644 --- a/docs/CODEX_SANDBOX_RUNBOOK.md +++ b/docs/CODEX_SANDBOX_RUNBOOK.md @@ -1,6 +1,6 @@ # Codex sandbox qualification runbook -Full run #25 is archived and passed baseline 2.3 on Codex CLI 0.153.4. The finite C08 stop/repair replacement is merged. Publication now requires a successful new full run and import of its complete evidence. `QUALIFICATION_STATUS.md` is the current status; this runbook describes both full requalification and targeted checks. +Full run #27 is reviewed and archived: baseline 2.3 C01-C16 and finite C08 stop/repair passed on Codex CLI 0.153.4. Its complete evidence is recorded in the repository; no new run is needed just to import it. Historical #25 remains unchanged. `QUALIFICATION_STATUS.md` records the tested configuration, limitations and publication boundary. This runbook describes future full requalification and targeted checks. ## Sandbox prerequisites @@ -27,9 +27,9 @@ If the probe fails with `setting up uid map: Operation not permitted`, fix the P The preferred qualification path is `.github/workflows/plananvil-codex-qualification.yml`. The workflow is intentionally `workflow_dispatch`-only, accepts execution only from `main`, uses Environment `plananvil-codex`, and targets `[self-hosted, linux, x64, plananvil, codex]`. -Use **mode=full** for the next publication-closing C01-C16 sequence. The production validator requires one complete source-bound full-run archive with the finite C08 result, not a combination of partial archives. `mode=c08` is available to diagnose only the finite stop/repair replacement. `mode=recovery` retains C09/C10/C13; `mode=c13` selects C13 only. `mode=smoke` verifies basic runtime/authentication. The precision/variant matrices are diagnostics, not release evidence. All targeted modes keep `release_gate_passed=false`, even when their selected checks pass. +Use **mode=full** when a new publication-closing C01-C16 qualification is needed. The production validator requires one complete source-bound full-run archive with the finite C08 result, not a combination of partial archives. `mode=c08` is available to diagnose only the finite stop/repair replacement. `mode=recovery` retains C09/C10/C13; `mode=c13` selects C13 only. `mode=smoke` verifies basic runtime/authentication. The precision/variant matrices are diagnostics, not release evidence. All targeted modes keep `release_gate_passed=false`, even when their selected checks pass. -Start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner's initiating-actor policy. Automated run #26 (`34109662176`) was rejected by that policy before any Codex trial; do not rerun it or relax the allowlist. The repair is on main, but that rejected launch provides no model-backed result. +For requalification, start a NEW **PlanAnvil Codex qualification -> Run workflow -> main -> full** from an account allowed by the local runner's initiating-actor policy. Automated run #26 (`34109662176`) was rejected before any Codex trial. Owner-initiated #27 then passed; do not rerun the rejected launch or relax the allowlist. Both `full` and `c08` use the same active v7 C08 runtime with real live model inference. The outer harness deliberately starts without a checkpoint, observes the actual PreCompact stop and termination, creates/validates a real checkpoint, then requires one pressure -> compaction -> SessionStart(compact) -> finish sequence and a completed positive result. The disposable fixture excludes ordinary startup recovery only; product files and C10 startup coverage remain unchanged. @@ -117,7 +117,7 @@ C04 is informational/non-gating in baseline 2.3 but should still be observed if ## Final gate -Full capability qualification and publication closure are separate. Preserve the original #25 archive unchanged. For publication, review and commit a new successful full-run archive whose C08 has finite completion evidence, along with its exact C01-C16 packages and actual executed source SHA. Update `qualifications/index.json` to that full run as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive. +Full capability qualification and signed publication are separate. Current full run #27 supplies finite C08 completion and exact C01-C16 packages; `qualifications/index.json` identifies it. Preserve both #25 and #27 archives unchanged. Any future qualification must be imported as one complete source-bound full archive as described in `RELEASE.md`. Never replace the full-run index with a partial-mode index or splice a targeted result into an older archive. When the complete current full-run evidence is committed: diff --git a/docs/QUALIFICATION_STATUS.md b/docs/QUALIFICATION_STATUS.md index 4d04c04..624b758 100644 --- a/docs/QUALIFICATION_STATUS.md +++ b/docs/QUALIFICATION_STATUS.md @@ -1,81 +1,92 @@ # Qualification status -## Recorded live result - -Full run #25 (`34060321283`) passed baseline 2.3 C01-C16 on product source -`d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`, Codex CLI 0.153.4, -`gpt-5.6-sol`, Debian 13. C04 is informational. The immutable original archive, -summary, checksums and caveats are in `qualifications/34060321283/`. - -## Implemented closure - -PR #34 merged the finite C08 repair and the reviewed evidence into main at -`ba3f56a644a385c8aa2e8e5c9c934999184cc282`. PR CI #118 and post-merge CI #119 -passed all eight jobs, including actual Codex CLI loopback conformance. These -are implementation/integration checks, not a new live-model result. - -The historical positive C08 trial timed out after meeting its narrow unblock -assertion. It remains unchanged in the archive. The finite replacement requires -the same canonical run to stop at PreCompact without a checkpoint, then, after -outer checkpoint repair, complete pressure -> compact recovery -> finish with -exit zero. Timeout or incomplete telemetry cannot pass. - -C13 passed in the explicitly allowed project-scoped non-ephemeral fallback. -Ephemeral spawning is not claimed as working. The product .agents/.codex payload -and the C09/C10/C13 runtime paths are unchanged by this closure. - -## Required operator action - -The automated full launch #26 (`34109662176`) used the repaired main commit, -but the self-hosted runner's job-start policy rejected its initiating actor: - -```text -PlanAnvil runner policy denied this job: initiating actor is not allowed -``` - -The hook exited 77 before runner preflight, fixture preparation or any Codex -trial. This run has no new capability evidence and is not a C08 test failure. -Do not change the runner allowlist, spoof the actor or relax the trusted-workflow -policy to make an automated launch pass. - -An operator whose account is allowed by the runner policy must start a NEW run: - -**Actions -> PlanAnvil Codex qualification -> Run workflow -> main -> full**. - -Use Run workflow, not Re-run of the denied automated run. GitHub Actions -orchestrates the job; all model-backed trials run on the existing authenticated -self-hosted runner, not on a GitHub-hosted machine. - -## Evidence required for publication - -The current production validator requires ONE complete, source-bound full-run -archive, exact matching current capability packages, unchanged qualified product -bytes, and finite C08 stop/repair proof in that same archive. Therefore the next -publication proof must be a successful new `full` run. The `c08` mode remains a -useful targeted diagnostic, but its partial archive alone cannot close the -production gate. Do not splice it into or relabel the immutable #25 archive. - -After success, review and verify the new sanitized archive, preserve it under -`qualifications//`, import its exact C01-C16 packages, and update -`qualifications/index.json` through a protected PR. Keep #25 unchanged as history. -Record the actually executed source SHA, not the later import commit. Run the -strict release check on a clean tree after import. No production tag or release -has been created by these preparation steps. - -## Verification layers - -Unit/process tests and pinned real-CLI loopback tests check implementation and -protocol behavior. Only the authenticated self-hosted qualification workflow -provides live-model evidence. Newly materialized templates always start BLOCKED; -archived evidence cannot silently qualify a fresh fixture or changed product. - -## Audit index +## Current reviewed full result + +**Live qualification is complete for the tested configuration.** Owner-initiated +full run #27 (`34140846679`) passed baseline 2.3 C01-C16 on executed source +`a9cdcdc1e0cad70e88b60869e75e4166046dd306`, Codex CLI 0.153.4, +model `gpt-5.6-sol`, Debian GNU/Linux 13. C04 is informational; fifteen +capabilities are required. The full run reports `release_gate_passed=true`. +All model-backed trials ran on the authenticated self-hosted runner. + +The original archive, exact summary and verified provenance are preserved in +`qualifications/34140846679/`. `qualifications/index.json.current_run` points to +that run. Current `capabilities/C01` through `C16` are exact archive copies, +not rewritten observations or a combination of partial runs. The executed source +SHA remains the original SHA, never the later evidence-import commit. + +## C08 closure and recovery regressions + +C08 completed its finite stop/repair protocol in the same canonical run: + +- Without a checkpoint: one completed pressure command, an actual automatic + PreCompact `continue=false`, expected process exit 1 after 10.643 seconds, + no PostCompact and no timeout. +- After the outer harness created a real valid checkpoint: pressure, one + automatic PreCompact/PostCompact cycle, SessionStart(source=compact), finish + reconciliation and positive structured completion; exit 0 after 36.265 seconds, + no timeout. All nine positive protocol checks passed. + +C09 completed all three reconciliations and two ordered automatic recovery +cycles with exit 0 in 60.679 seconds. Both independent C10 context-delivery +probes completed with exact recovery values and exit 0. Process cleanup and +checkpoint/source immutability checks passed for the recovery probes. + +There are no recorded `timeout=true` values in the current actual evidence. +This is not a guarantee of future model behavior or support for untested +Codex/model/operating-system combinations. + +## Retained compatibility limitation + +C13 passed using the explicitly allowed project-scoped non-ephemeral fallback +after the recognized ephemeral parent-thread failure. Agent and SubagentStart +hook remained project-scoped; child context, cleanup and authentication +invariants passed. Ephemeral spawning is not claimed as working. + +## Integrity and publication boundary + +The archive contains 166 manifest-listed files plus the manifest, including +three hidden fixture files. All SHA-256 checks, per-capability package validation +and source identities were verified before import. The qualified .agents/.codex +product bytes, runtime implementations, permission policy and release guards +are unchanged by this evidence/documentation update. + +On a clean checkout, run `python tools/validate_capabilities.py` and +`python tools/release_check.py` without `--candidate`. The latter requires the +complete full-run archive, exact packages, unchanged qualified product bytes +and finite C08 completion. Freshly materialized unexecuted templates still start +BLOCKED and cannot inherit the archived success. + +No additional live run is required merely to record these same results or +update documentation. Requalify when relevant product/runtime inputs change. +Production publication remains a separate owner-authorized verified signed +annotated tag and release workflow, as described in `RELEASE.md`. No production +tag or release is created by the evidence import. + +## Preserved history + +Run #25 (`34060321283`, source `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3`) +passed the older narrow assertions but its positive C08 trial later timed out. +Its original archive, summary, provenance and caveat remain unchanged under +`qualifications/34060321283/`; it is not the current publication evidence. + +PR #34 merged the finite C08 repair. Automated run #26 (`34109662176`) was +rejected by the local initiating-actor policy before Codex. It provides no live +result. The owner-initiated #27 completed without changing or bypassing that +policy. PR #35 clarified the requirement for one complete full archive. + +## Verification layers and audit index + +Unit/process tests and real-CLI loopback conformance check implementation and +protocol behavior. Only the authenticated self-hosted run supplies live-model +evidence. The archived full result does not imply execution of every possible +application plan; PlanAnvil generates and validates plans, never implements them. - `CODEX_CAPABILITY_QUALIFICATION_2026-08-28.md`: historical prerequisite-limited attempt. - `CODEX_QUALIFICATION_EXECUTION_AUDIT_2026-09-05.md`: C13 argv and C10 worktree discovery. -- `CODEX_RECOVERY_DELIVERY_AUDIT_2026-09-05.md`: supported context delivery and diagnostics. -- `CODEX_C09_FINITE_RECOVERY_AUDIT_2026-09-06.md`: completed finite C09 repair. -- `CODEX_C08_CLOSURE_AUDIT_2026-09-07.md`: finite C08 and evidence closure. +- `CODEX_RECOVERY_DELIVERY_AUDIT_2026-09-05.md`: context delivery and diagnostics. +- `CODEX_C09_FINITE_RECOVERY_AUDIT_2026-09-06.md`: finite C09 repair. +- `CODEX_C08_CLOSURE_AUDIT_2026-09-07.md`: finite C08 implementation. -Older harness modules are retained because v7 still imports them. They are not -independent supported entry points. Do not delete imported layers as cosmetic cleanup. +Older harness modules remain active v7 dependencies, not separate supported +entry points. They must not be removed as cosmetic cleanup. diff --git a/docs/RELEASE.md b/docs/RELEASE.md index a750ae4..1de947a 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -25,7 +25,7 @@ python tools/build_release.py --output dist Before a production tag, execute `docs/CODEX_SANDBOX_RUNBOOK.md`. Required entries in `capabilities/index.json` must be changed from `BLOCKED` to `REPRODUCED` only after their complete sanitized evidence package is committed and `python tools/validate_capabilities.py` passes. -For the current C08 closure, use a NEW `mode=full` run on main, initiated by an account allowed by the self-hosted runner. The production validator requires a single complete full-run archive containing the finite C08 proof. A successful `c08` or `recovery` diagnostic is useful but its partial archive cannot replace that full run. See `docs/QUALIFICATION_STATUS.md` for the merged repair and the automated launch rejected before testing. +Current full run #27 (`34140846679`) passed and its exact reviewed evidence is committed, including finite C08 stop/repair completion. No further live run is required merely to record this result. The production validator still requires one complete full-run archive; a `c08` or `recovery` diagnostic cannot replace it. See `docs/QUALIFICATION_STATUS.md` for provenance, tested scope and the retained C13 fallback limitation. ## Publish @@ -54,16 +54,17 @@ The production `release_check.py` enforces clean-tree state in addition to versi Before production release, protect `main` as tracked in issue #6: PR-only changes, required CI, up-to-date branch, conversation resolution, and no force push/delete. -## Qualification closure (2026-09-07) +## Qualification closure (reviewed 2026-09-08) The baseline #25 evidence is preserved immutably. `qualifications/index.json` identifies the current reviewed full run; its source SHA always remains the actually executed commit, never the later evidence-import commit. `release_check.py` also validates the original archive digest/manifest, exact current capability packages, qualified .agents/.codex bytes, and finite C08 -negative-stop/positive-completion evidence. The old C08 timeout keeps production -blocked until the new complete full-run result is committed. Candidate checks -intentionally remain usable before that result exists. +negative-stop/positive-completion evidence. Full #27 now supplies that proof; +the old #25 timeout remains recorded as history. Candidate checks still do not +substitute for strict production validation. Run `python tools/release_check.py` +on the clean evidence-import commit before any signed publication. To import a successful new full result, preserve its exact archive, summary and verified provenance under `qualifications//`, import its exact C01-C16 @@ -78,7 +79,8 @@ seven required status checks, strict up-to-date branch, conversation resolution, no deletion or force push, no bypass actors. The protected distribution job now also requires real-CLI conformance to succeed. No policy is loosened for closure. -After the complete new full-run evidence is imported and CI is green, preparation -is complete; the signed annotated production tag remains a separate authorized -publication. No unsigned or lightweight tag may substitute for the required -verified signature. +The complete #27 evidence is imported. After strict validation and green CI on +the evidence-import commit, qualification preparation is complete; a signed +annotated production tag remains a separate authorized publication. This import +does not create a tag or release. No unsigned or lightweight tag may substitute +for the required verified signature. diff --git a/tests/test_qualification_closure.py b/tests/test_qualification_closure.py index cf27474..7abda53 100644 --- a/tests/test_qualification_closure.py +++ b/tests/test_qualification_closure.py @@ -15,6 +15,33 @@ class ClosureTests(unittest.TestCase): + def test_reviewed_current_full_archive_closes_evidence_gate(self): + # Read real committed evidence; no synthetic result or CLI simulation. + self.assertEqual(closure.closure_blockers(ROOT), []) + index = json.loads((ROOT / 'qualifications/index.json').read_text()) + self.assertEqual(index['c08_closure'], 'REPRODUCED') + folder = ROOT / 'qualifications' / index['current_run'] + provenance = json.loads((folder / 'provenance.json').read_text()) + self.assertEqual(provenance['qualification_mode'], 'full') + with zipfile.ZipFile(folder / 'evidence-artifact.zip') as z: + summary_bytes = z.read('qualification-summary.json') + self.assertEqual((folder / 'qualification-summary.json').read_bytes(), summary_bytes) + summary = json.loads(summary_bytes) + self.assertEqual(summary['github_actions_run'], index['current_run']) + self.assertEqual(summary['source_commit'], provenance['source_commit']) + self.assertTrue(summary['release_gate_passed']) + self.assertEqual(summary['required_not_reproduced'], []) + + def test_current_package_change_is_not_accepted_as_archived_evidence(self): + with tempfile.TemporaryDirectory() as tmp: + root = self.copy_repo(tmp) + path = root / 'capabilities/C09/actual.sanitized.json' + # Even a JSON-preserving edit is not the original source-bound record. + with path.open('ab') as stream: + stream.write(b'\n') + self.assertTrue(any('current capability differs from archived run' in error + for error in closure.closure_blockers(root))) + def copy_repo(self, tmp): target = Path(tmp)/'repo' shutil.copytree(ROOT, target, ignore=shutil.ignore_patterns('.git', '__pycache__')) From 2a801958d42d15ec03a658a9cd5f5e69d0f68ea8 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Tue, 8 Sep 2026 09:00:56 +0200 Subject: [PATCH 4/5] Keep archived evidence checks distinct from candidate PR product eligibility --- tests/test_qualification_closure.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_qualification_closure.py b/tests/test_qualification_closure.py index 7abda53..638335a 100644 --- a/tests/test_qualification_closure.py +++ b/tests/test_qualification_closure.py @@ -11,18 +11,20 @@ sys.path.insert(0, str(ROOT/'tools')) import prepare_capabilities as prepare import qualification_closure as closure -from qualification_artifact import build_archive +import release_check +from qualification_artifact import build_archive, verify_archive class ClosureTests(unittest.TestCase): - def test_reviewed_current_full_archive_closes_evidence_gate(self): - # Read real committed evidence; no synthetic result or CLI simulation. - self.assertEqual(closure.closure_blockers(ROOT), []) + def test_reviewed_current_full_archive_and_summary_are_consistent(self): + # Verify archived evidence, not production eligibility of a development PR. + # Current product binding remains the responsibility of release_check.py. index = json.loads((ROOT / 'qualifications/index.json').read_text()) self.assertEqual(index['c08_closure'], 'REPRODUCED') folder = ROOT / 'qualifications' / index['current_run'] provenance = json.loads((folder / 'provenance.json').read_text()) self.assertEqual(provenance['qualification_mode'], 'full') + verify_archive(folder / 'evidence-artifact.zip') with zipfile.ZipFile(folder / 'evidence-artifact.zip') as z: summary_bytes = z.read('qualification-summary.json') self.assertEqual((folder / 'qualification-summary.json').read_bytes(), summary_bytes) @@ -67,6 +69,8 @@ def test_product_change_is_rejected_independently_of_git_status(self): root=self.copy_repo(tmp) (root/'.agents/skills/plan-anvil/SKILL.md').write_text('changed') self.assertIn('product bytes changed since recorded live qualification', closure.closure_blockers(root)) + # Ordinary candidate PRs stay usable before new main-only live qualification. + self.assertEqual(release_check.release_blockers(root, require_reproduced=False), []) def test_archive_digest_corruption_is_rejected(self): with tempfile.TemporaryDirectory() as tmp: From 5bc127f6029f72e3079837b40108783ce2e8d836 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Tue, 8 Sep 2026 09:04:56 +0200 Subject: [PATCH 5/5] Synchronize 0.2.0 release notes with verified full run 27 --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb62765..26c84dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,14 +67,14 @@ All notable changes to PlanAnvil are documented here. - preserve complete baseline 2.3 live evidence from full run #25, `34060321283`, tested at `d0384f76bc4150d33bb8f51ef5981f3243b3cfb3` with Codex CLI 0.153.4, `gpt-5.6-sol`, Debian 13; all C01–C16 were reproduced; - retain the exact source-bound archive, hashes and original limitations; C13 passed via the permitted project-native non-ephemeral fallback; -- replace the old C08 repaired-path workload with a finite pressure/finish scenario and strict termination checks; the old positive timeout remains in historical evidence and the replacement still requires live confirmation; +- replace the old C08 repaired-path workload with a finite pressure/finish scenario and strict termination checks; the old positive timeout remains in historical evidence; full run #27 subsequently confirmed the replacement live; - add C08-only qualification and real-CLI loopback conformance without changing C09/C10/C13 runtime behavior, product payload or live runner security; - reset newly materialized template indices to unexecuted package results instead of inheriting historical success labels; - validate qualification archive integrity and qualified product identity, and require committed finite C08 completion evidence before production publication. ### Release status -0.2.0 remains a release candidate. Full baseline qualification is recorded; production publication awaits the finite C08 live follow-up, strict release validation and a verified signed annotated tag. No tag or release has been published by the qualification-closure change. +0.2.0 is qualified for the recorded configuration. Full run #27 (`34140846679`) confirmed C01-C16 and finite C08 stop/repair on source `a9cdcdc1e0cad70e88b60869e75e4166046dd306`; its complete source-bound evidence is committed and #25 remains unchanged. Production publication remains a separate verified signed annotated-tag action after strict release validation. No tag or release has been published by this evidence import. ## [0.1.0] - 2026-07-12