From 08eae5c4c8be44d0cb0917375f1ce51c58878d68 Mon Sep 17 00:00:00 2001 From: Val Alexander Date: Tue, 21 Jul 2026 10:57:08 -0500 Subject: [PATCH] =?UTF-8?q?test(phase-5):=20corpus=20verifier=20follow-ups?= =?UTF-8?q?=20=E2=80=94=20veto-less=20auto=20case,=20registry-derived=20re?= =?UTF-8?q?gion=20assertion,=20documented=20digest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Non-blocking follow-ups from the threads-uqx.13 verified-loop iteration-2 report (PR #21): 1. Add an AutoRegression { veto: null } valid corpus case — a legal configuration the harness supported but the corpus never exercised; pins the hardened wire shape (veto key present, null resolves to no window). 2. Derive the all-regions coverage assertion from SurfaceRegionRegistry::default_registry().descriptors() so a future built-in region flags corpus staleness instead of passing silently. 3. Document the pinned canonical SHA-256 next to the generation command in specs/PHASE-5-APPROVAL-SEMANTICS.md, including the trailing-newline nuance. Corpus digest moves once: 4ebe9d63398e6b14f2a097ce66197c96a577559984515ce03ce4297c0b0c7e10. Validation: corpus tests 4/4, full crate suite 176+17+4+14 green, fmt clean, clippy -D warnings clean; emitted-artifact digest reproduced via tr -d '\n' | shasum. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../tests/phase5_retired_ward_corpus.rs | 28 ++++++++++++++----- .../support/phase5_retired_ward_corpus.rs | 18 ++++++++++++ specs/PHASE-5-APPROVAL-SEMANTICS.md | 7 ++++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/crates/coven-threads-core/tests/phase5_retired_ward_corpus.rs b/crates/coven-threads-core/tests/phase5_retired_ward_corpus.rs index ca695c2..9c95ff5 100644 --- a/crates/coven-threads-core/tests/phase5_retired_ward_corpus.rs +++ b/crates/coven-threads-core/tests/phase5_retired_ward_corpus.rs @@ -93,7 +93,7 @@ fn corpus_documents_synthetic_provenance_without_historical_data() { #[test] fn valid_cases_cover_identity_approval_veto_and_region_fidelity() { let cases = valid_cases(); - assert_eq!(cases.len(), 4); + assert_eq!(cases.len(), 5); let labels: Vec<_> = cases .iter() @@ -101,8 +101,17 @@ fn valid_cases_cover_identity_approval_veto_and_region_fidelity() { .collect(); assert_eq!( labels, - ["auto", "familiar_review", "human_review", "human_required"] + [ + "auto", + "auto", + "familiar_review", + "human_review", + "human_required" + ] ); + // The explicit `veto: null` case pins the hardened wire shape: the key is + // required for auto_regression, and a null value resolves to no window. + assert!(cases[1]["approval"]["veto"].is_null()); let mut covered_regions = Vec::new(); for case in cases { @@ -170,10 +179,15 @@ fn valid_cases_cover_identity_approval_veto_and_region_fidelity() { covered_regions.sort(); covered_regions.dedup(); - assert_eq!( - covered_regions, - ["execution_prompt", "heartbeat_behavior", "tool_defaults"] - ); + // Derived from the registry so a new built-in region flags corpus + // staleness instead of passing silently. + let mut built_in_regions: Vec<_> = SurfaceRegionRegistry::default_registry() + .descriptors() + .iter() + .map(|descriptor| descriptor.region_id.as_str().to_string()) + .collect(); + built_in_regions.sort(); + assert_eq!(covered_regions, built_in_regions); } #[test] @@ -234,6 +248,6 @@ fn canonical_generator_output_has_a_pinned_sha256_digest() { let digest = Sha256::digest(corpus::canonical_corpus_json().as_bytes()); assert_eq!( format!("{digest:x}"), - "b3c5f156896ed4ef03b3f57bb8e65a33a5cf6fe52582ccd8403972a20299db44" + "4ebe9d63398e6b14f2a097ce66197c96a577559984515ce03ce4297c0b0c7e10" ); } diff --git a/crates/coven-threads-core/tests/support/phase5_retired_ward_corpus.rs b/crates/coven-threads-core/tests/support/phase5_retired_ward_corpus.rs index 63968c8..fcbe0f2 100644 --- a/crates/coven-threads-core/tests/support/phase5_retired_ward_corpus.rs +++ b/crates/coven-threads-core/tests/support/phase5_retired_ward_corpus.rs @@ -77,6 +77,24 @@ pub fn synthetic_retired_ward_corpus() -> Value { json!([]), u8::MAX ), + valid_case( + "auto-no-veto", + 0x55, + json!({ + "kind": "auto_regression", + "label": "auto", + "veto": null + }), + json!([ + { + "path": "MEMORY.md", + "before": "synthetic memory v2", + "after": "synthetic memory v3" + } + ]), + json!([]), + u8::MAX + ), valid_case( "familiar-review", 0x22, diff --git a/specs/PHASE-5-APPROVAL-SEMANTICS.md b/specs/PHASE-5-APPROVAL-SEMANTICS.md index b823926..ff63e93 100644 --- a/specs/PHASE-5-APPROVAL-SEMANTICS.md +++ b/specs/PHASE-5-APPROVAL-SEMANTICS.md @@ -402,7 +402,12 @@ Phase 5 opened 2026-07-18 (Val + Nova decision). Beads are live. approval labels, veto settings, built-in harness regions, and fail-closed unsupported cases without using historical or private Ward data. Generate it with `cargo run -q -p coven-threads-core --example - generate_phase5_retired_ward_corpus`. + generate_phase5_retired_ward_corpus`. The pinned SHA-256 of the canonical + corpus JSON is + `4ebe9d63398e6b14f2a097ce66197c96a577559984515ce03ce4297c0b0c7e10`; the + digest covers the single JSON line only, excluding the trailing newline the + example's `println!` appends (so `shasum` over the emitted file differs — + strip the final newline first, e.g. `... | tr -d '\n' | shasum -a 256`). - `threads-uqx.9` — Nova sign-off: RFC round-trip, Gate-4 fail-closed proof, descriptor-not-authority review. - `threads-uqx.10` — Val freeze: Phase-5 design frozen or rejected.