← Về thư mục
scripts/test_check_v3_6_7_pattern_protection.py
- _archive_repo · function · L26-L40 — def _archive_repo(dest: Path) -> None
- _run_lint · function · L43-L52 — def _run_lint(repo_dir: Path) -> tuple[int, str, str]
- _mutate · function · L55-L66 — def _mutate(repo_dir: Path, rel_path: str, old: str, new: str) -> None
- _MutationTestBase · class · L69-L86 — class _MutationTestBase(unittest.TestCase)
- setUp · method · L72-L75 — def setUp(self) -> None
- tearDown · method · L77-L78 — def tearDown(self) -> None
- assert_baseline_passes · method · L80-L82 — def assert_baseline_passes(self) -> None
- assert_mutation_fails · method · L84-L86 — def assert_mutation_fails(self) -> None
- BaselineTest · class · L89-L91 — class BaselineTest(_MutationTestBase)
- test_unmutated_repo_passes · method · L90-L91 — def test_unmutated_repo_passes(self) -> None
- R2MutationTests · class · L94-L119 — class R2MutationTests(_MutationTestBase)
- test_c1_inverted_must_not_preserve_fails · method · L98-L105 — def test_c1_inverted_must_not_preserve_fails(self) -> None
- test_c3_audit_passed_sentence_deleted_fails · method · L107-L119 — def test_c3_audit_passed_sentence_deleted_fails(self) -> None: # Phase 6.7 merged line 178 into the canonical Clause 1 line # bullet. The "audit-passed state" segment is now part of a single # whole-line bullet, so the mutation deletes that segment from # within the canonical line and asserts the now-incomplete bullet # fails the C3 + INV-1 regex pair.
- R3MutationTests · class · L122-L160 — class R3MutationTests(_MutationTestBase)
- test_r3_001_trailing_must_not_be_enforced_fails · method · L126-L133 — def test_r3_001_trailing_must_not_be_enforced_fails(self) -> None
- test_r3_002_a2_pending_verification_optional_fails · method · L135-L142 — def test_r3_002_a2_pending_verification_optional_fails(self) -> None
- test_r3_002_c2_may_use_year_range_fails · method · L144-L151 — def test_r3_002_c2_may_use_year_range_fails(self) -> None
- test_r3_003_no_subsetting_except_when_concise_fails · method · L153-L160 — def test_r3_003_no_subsetting_except_when_concise_fails(self) -> None
- R4MutationTests · class · L163-L245 — class R4MutationTests(_MutationTestBase)
- test_r4_001_a2_may_wrap_fails · method · L166-L173 — def test_r4_001_a2_may_wrap_fails(self) -> None
- test_r4_001_a3_may_include_fails · method · L175-L182 — def test_r4_001_a3_may_include_fails(self) -> None
- test_r4_001_a1_recommended_fails · method · L184-L191 — def test_r4_001_a1_recommended_fails(self) -> None
- test_r4_002_a4_may_be_quoted_fails · method · L193-L200 — def test_r4_002_a4_may_be_quoted_fails(self) -> None
- test_r4_002_a5_drop_conditional_fails · method · L202-L209 — def test_r4_002_a5_drop_conditional_fails(self) -> None
- test_r4_002_b4_allow_chapter_vocab_fails · method · L211-L218 — def test_r4_002_b4_allow_chapter_vocab_fails(self) -> None
- test_r4_002_b5_allow_overset_fails · method · L220-L227 — def test_r4_002_b5_allow_overset_fails(self) -> None
- test_r4_002_c1_drop_buffer_fails · method · L229-L236 — def test_r4_002_c1_drop_buffer_fails(self) -> None
- test_r4_002_c2_drop_past_tense_form_fails · method · L238-L245 — def test_r4_002_c2_drop_past_tense_form_fails(self) -> None
- R5MutationTests · class · L248-L303 — class R5MutationTests(_MutationTestBase)
- test_r5_001_a2_should_wrap_fails · method · L251-L258 — def test_r5_001_a2_should_wrap_fails(self) -> None
- test_r5_001_a3_should_include_fails · method · L260-L267 — def test_r5_001_a3_should_include_fails(self) -> None
- test_r5_001_a4_can_be_quoted_tail_fails · method · L269-L276 — def test_r5_001_a4_can_be_quoted_tail_fails(self) -> None
- test_r5_001_b5_overset_permitted_fails · method · L278-L285 — def test_r5_001_b5_overset_permitted_fails(self) -> None
- test_r5_001_b5_should_declare_fails · method · L287-L294 — def test_r5_001_b5_should_declare_fails(self) -> None
- test_r5_001_c1_should_preserve_fails · method · L296-L303 — def test_r5_001_c1_should_preserve_fails(self) -> None
- R6MutationTests · class · L306-L361 — class R6MutationTests(_MutationTestBase)
- test_r6_001_c1_will_not_preserve_fails · method · L309-L316 — def test_r6_001_c1_will_not_preserve_fails(self) -> None
- test_r6_001_c1_would_preserve_fails · method · L318-L325 — def test_r6_001_c1_would_preserve_fails(self) -> None
- test_r6_001_a2_ought_to_wrap_fails · method · L327-L334 — def test_r6_001_a2_ought_to_wrap_fails(self) -> None
- test_r6_001_a3_ideally_include_fails · method · L336-L343 — def test_r6_001_a3_ideally_include_fails(self) -> None
- test_r6_001_b5_preferably_enumerate_fails · method · L345-L352 — def test_r6_001_b5_preferably_enumerate_fails(self) -> None
- test_r6_001_a3_we_recommend_that_fails · method · L354-L361 — def test_r6_001_a3_we_recommend_that_fails(self) -> None
- INV1MutationTests · class · L364-L411 — class INV1MutationTests(_MutationTestBase)
- test_inv1_synthesis_canonical_line_deleted_fails · method · L375-L382 — def test_inv1_synthesis_canonical_line_deleted_fails(self) -> None
- test_inv1_architect_canonical_line_deleted_fails · method · L384-L391 — def test_inv1_architect_canonical_line_deleted_fails(self) -> None
- test_inv1_compiler_canonical_line_deleted_fails · method · L393-L400 — def test_inv1_compiler_canonical_line_deleted_fails(self) -> None
- test_inv1_synthesis_canonical_line_duplicated_fails · method · L402-L411 — def test_inv1_synthesis_canonical_line_duplicated_fails(self) -> None: # Duplicating the bullet trips INV-1 uniqueness (
hits == 1) # without breaking the per-file C-style positive regex.
- INV2MutationTests · class · L414-L471 — class INV2MutationTests(_MutationTestBase)
- _inject_violation · method · L422-L430 — def _inject_violation(self, file_rel: str, violation: str) -> None
- test_inv2_a_orchestrator_audit_fails · method · L432-L438 — def test_inv2_a_orchestrator_audit_fails(self) -> None: # Pattern (a): \bthe orchestrator\b.*\baudit\b
- test_inv2_b_cross_model_audit_template_fails · method · L440-L447 — def test_inv2_b_cross_model_audit_template_fails(self) -> None: # Pattern (b): \bcross-model audit (?:follows|covers)\b.*codex_audit_multifile_template
- test_inv2_c_audit_will_be_run_fails · method · L449-L455 — def test_inv2_c_audit_will_be_run_fails(self) -> None: # Pattern (c): \baudit (?:afterwards?|will be run|is dispatched)\b
- test_inv2_d_downstream_audit_fails · method · L457-L463 — def test_inv2_d_downstream_audit_fails(self) -> None: # Pattern (d): \bdownstream audit\b
- test_inv2_d_this_output_will_be_audited_fails · method · L465-L471 — def test_inv2_d_this_output_will_be_audited_fails(self) -> None: # Pattern (d) second alternative: \bthis output (?:is|will be) audited\b
- INV3MutationTests · class · L474-L519 — class INV3MutationTests(_MutationTestBase)
- test_inv3_canonical_in_non_manifest_agent_fails · method · L482-L495 — def test_inv3_canonical_in_non_manifest_agent_fails(self) -> None: # Add the canonical line to bibliography_agent (which is NOT in # the v3.6.7 inversion manifest). The §6 sweep is v3.6.7-only; # widening to a fourth file is the §9 L2 deferred question and # MUST fail lint as a guard against accidental sweep widening.
- test_inv3_manifest_shrunk_to_two_files_fails · method · L497-L507 — def test_inv3_manifest_shrunk_to_two_files_fails(self) -> None: # Drop one entry from the manifest. The dropped file's canonical # line is now "outside" the manifest from INV-3's perspective and # must be flagged.
- test_inv3_manifest_extra_nonexistent_entry_fails · method · L509-L519 — def test_inv3_manifest_extra_nonexistent_entry_fails(self) -> None: # Adding a fourth file to the manifest that does not carry the # canonical line must fail INV-1 (the manifest claims a file that # is not actually swept). This guards against drift where someone # widens the manifest without doing the corresponding prompt edit.
- CodexR1MutationTests · class · L522-L601 — class CodexR1MutationTests(_MutationTestBase)
- test_r1_p2_inv2_wrapped_disclosure_fails · method · L529-L546 — def test_r1_p2_inv2_wrapped_disclosure_fails(self) -> None: # Codex R1 P2: INV-2 patterns compiled without re.DOTALL allow a # forbidden Clause 2 sentence to be Markdown-soft-wrapped across # newlines and slip past the regex. Inject a wrapped (a) violation # ("the orchestrator" on one line, "audit" on the next) and # assert lint fails. Phase 6.7 R1 closure compiles INV-2 with # IGNORECASE | DOTALL so
. crosses newlines.
- test_r1_p2_inv1_canonical_with_tail_weakener_fails · method · L548-L563 — def test_r1_p2_inv1_canonical_with_tail_weakener_fails(self) -> None: # Codex R1 P2: the prior CANONICAL_CLAUSE_1_RE stopped at #
state\b so a manifest prompt could keep the canonical # sentence yet append if feasible. and INV-1 still passed. # Phase 6.7 R1 closure anchors the regex to state\.\s*$ with # re.MULTILINE so any tail content on the same bullet line # breaks the match. Both INV-1 and the C3 regex must reject this # mutation (defense in depth — the C3 negation post-filter also # catches if feasible via _ALWAYS_NEGATION_PATTERNS).
- test_r1_p2_manifest_widening_with_canonical_copy_fails · method · L565-L590 — def test_r1_p2_manifest_widening_with_canonical_copy_fails(self) -> None: # Codex R1 P2: a copy-paste widening attack — add a fourth file # to the manifest AND copy the canonical bullet into that file's # PATTERN PROTECTION block. Pre-fix INV-1 passed for all four # (canonical line present everywhere) and INV-3 silently skipped # the new file because it was now in
manifest_set. Phase 6.7 # R1 closure validates manifest['files'] against the frozen # EXPECTED_MANIFEST_FILES set (exact match, no superset / no # drift); widening triggers L2 resolution per spec §6.3 line # 1807, which requires landing a v3.6.8+ manifest, not editing # the v3.6.7 one. Construct the attack and assert lint fails.
- test_r1_p2_manifest_duplicate_entry_fails · method · L592-L601 — def test_r1_p2_manifest_duplicate_entry_fails(self) -> None: # Defense in depth on the same closure: a duplicate file path in #
files should also fail (per uniqueness check added in the # R1 fix), even if the path is otherwise valid.
- CodexR2MutationTests · class · L604-L685 — class CodexR2MutationTests(_MutationTestBase)
- test_r2_p2_inv1_bullet_prefix_weakener_fails · method · L611-L625 — def test_r2_p2_inv1_bullet_prefix_weakener_fails(self) -> None: # Codex R2 P2: a bullet of the form
- When feasible, DO NOT # simulate ... carries the canonical sentences as a substring # but is NOT a verbatim canonical bullet. The pre-fix INV-1 # regex search-anywhere accepted this; the bullet-extraction + # exact-match contract rejects it.
- test_r2_p2_inv1_softwrap_canonical_passes · method · L627-L646 — def test_r2_p2_inv1_softwrap_canonical_passes(self) -> None: # Codex R2 P2 dual: a soft-wrapped canonical bullet (line break # between
run and codex/external) MUST still pass INV-1. # This is the false-negative side of the regex anchor problem # that the bullet-extraction + whitespace-normalization fix # closes. Asserts that this specific Markdown reflow does not # break baseline lint.
- test_r2_p2_inv2_cross_bullet_no_false_positive · method · L648-L673 — def test_r2_p2_inv2_cross_bullet_no_false_positive(self) -> None: # Codex R2 P2: prior INV-2(a)
\bthe orchestrator\b.*\baudit\b # with re.DOTALL applied to raw block text would match across # bullets — a benign the orchestrator mention in one bullet # plus the canonical bullet's audit step mention would # false-positive even though no single bullet expresses the # forbidden disclosure. Insert a benign orchestrator mention as # a NEW bullet near the canonical bullet and assert lint still # passes (no false positive).
- test_r2_p2_inv2_in_bullet_violation_still_fails · method · L675-L685 — def test_r2_p2_inv2_in_bullet_violation_still_fails(self) -> None: # Defense in depth on R2-002: the per-bullet INV-2 must STILL # catch a real violation that lives inside a single bullet.
- CodexR3MutationTests · class · L688-L715 — class CodexR3MutationTests(_MutationTestBase)
- test_r3_p2_inv2_intro_paragraph_disclosure_fails · method · L695-L715 — def test_r3_p2_inv2_intro_paragraph_disclosure_fails(self) -> None: # Codex R3 P2: the Phase 6.7 sweep removed Clause 2 disclosure # sentences that lived in the intro paragraph of each PATTERN # PROTECTION block (e.g. "Cross-model audit follows ... # codex_audit_multifile_template.md ..." in synthesis_agent.md # line 164). After R2's per-bullet refactor, INV-2 only # iterated bullets and the original disclosure could be # silently re-added to the intro paragraph. Phase 6.7 R3 # closure adds prose-paragraph segments to INV-2's iteration # via
_iter_block_segments. Re-introduce the original # Cross-model audit follows ... sentence into synthesis's # intro paragraph and assert lint catches it as a prose # violation.
- CodexR4MutationTests · class · L718-L742 — class CodexR4MutationTests(_MutationTestBase)
- test_r4_p2_inv2_post_bullet_prose_disclosure_fails · method · L724-L742 — def test_r4_p2_inv2_post_bullet_prose_disclosure_fails(self) -> None: # Codex R4 P2: R3's
_iter_block_segments only iterated prose # paragraphs in block[:first_bullet] — pre-first-bullet # only. A Clause 2 disclosure appended as a paragraph AFTER # the canonical bullet (or anywhere after the bullet list) # was outside the segmentation window and silently passed # lint. R4 closure rewrites segmentation to paragraph-split # the entire block, distinguishing bullet groups (- ... # paragraphs) from prose paragraphs uniformly. Append a # forbidden disclosure as a trailing prose paragraph and # assert lint catches it.
- CodexR5MutationTests · class · L745-L770 — class CodexR5MutationTests(_MutationTestBase)
- test_r5_p2_compiler_softwrap_canonical_passes · method · L751-L770 — def test_r5_p2_compiler_softwrap_canonical_passes(self) -> None: # Codex R5 P2: C3 regex used literal spaces inside sentences, # so a soft-wrap between
run and codex/external (the same # benign Markdown reflow R2's INV-1 test verifies for synthesis) # caused CI to fail on report_compiler. Phase 6.7 R5 closure # rewrites every inter-token space inside the canonical regex # to \s+ so soft-wrap tolerance is uniform across INV-1 and # the C3 Check regex. Mutation should leave lint passing.
- CodexR6MutationTests · class · L773-L820 — class CodexR6MutationTests(_MutationTestBase)
- test_r6_p2_inv1_weakened_duplicate_alongside_canonical_fails · method · L781-L803 — def test_r6_p2_inv1_weakened_duplicate_alongside_canonical_fails(self) -> None: # Codex R6 P2: an attacker keeps the exact canonical bullet # AND adds a second, weakened variant # (
- When feasible, DO NOT simulate ...). Pre-fix INV-1 used # count(exact) == 1 which stayed at 1; lint passed and the # block was left in a state where the agent reads two # contradictory bullets. Phase 6.7 R6 closure introduces # _is_clause_1_like that flags any bullet carrying canonical # fragment markers (do not simulate, do not claim to have # run, audit-passed state); each flagged bullet must equal # the canonical text byte-for-byte or lint fails.
- test_r6_p2_inv1_tail_weakened_duplicate_fails · method · L805-L820 — def test_r6_p2_inv1_tail_weakened_duplicate_fails(self) -> None: # Defense in depth on R6: tail-weakener variant of the same # attack (
... audit-passed state if feasible.) — preserves # canonical, adds a near-duplicate with a tail weakener.
- CodexR7R9MutationTests · class · L823-L854 — class CodexR7R9MutationTests(_MutationTestBase)
- test_r9_inv3_weakened_clause_1_in_non_manifest_passes · method · L833-L854 — def test_r9_inv3_weakened_clause_1_in_non_manifest_passes(self) -> None: # Codex R9 P2 architectural rewind: a weakened canonical # variant outside the manifest is NOT a v3.6.7 INV-3 violation. # Only the exact canonical sentence (whitespace-normalized # equal to CANONICAL_CLAUSE_1_TEXT) widens the scope. Variants # are a v3.6.8+ concern if/when L2 is reopened.
- CodexR8MutationTests · class · L857-L908 — class CodexR8MutationTests(_MutationTestBase)
- test_r8_p2_generic_do_not_simulate_in_non_manifest_passes · method · L865-L888 — def test_r8_p2_generic_do_not_simulate_in_non_manifest_passes(self) -> None: # Codex R8 P2 (a): the prior
_is_clause_1_like flagged any # bullet containing do not simulate, which is common # anti-fabrication language. A legitimate non-manifest bullet # like - Do not simulate data or sources. would # false-positive INV-3 even though it has no audit-prohibition # semantics. Phase 6.7 R8 closure narrows the heuristic to # require an audit-specific fragment (audit step, # audit-passed state, or codex/external review). Inject # the generic bullet into bibliography_agent and assert lint # passes (no false positive).
- test_r8_p2_inv3_canonical_as_prose_in_non_manifest_fails · method · L890-L908 — def test_r8_p2_inv3_canonical_as_prose_in_non_manifest_fails(self) -> None: # Codex R8 P2 (b): the prior INV-3 only walked Markdown bullets. # A non-manifest agent prompt that pasted the exact canonical # sentence as a normal paragraph (not a
- bullet) silently # passed lint, even though the v3.6.7 prohibition was now # widened beyond the frozen manifest. Phase 6.7 R8 closure adds # a paragraph-level scan that compares whitespace-normalized # prose paragraphs against CANONICAL_CLAUSE_1_TEXT exactly. # Inject the canonical sentence as a prose paragraph in # bibliography_agent and assert lint fails.
- CodexR9MutationTests · class · L911-L956 — class CodexR9MutationTests(_MutationTestBase)
- test_r9_p2_inv3_audit_fragment_unrelated_bullet_passes · method · L918-L937 — def test_r9_p2_inv3_audit_fragment_unrelated_bullet_passes(self) -> None: # Codex R9 P2 (a): a non-manifest agent prompt may legitimately # discuss audit steps in process-flow guidance, e.g. #
- Review each audit step before finalizing.. R8's # heuristic flagged this as Clause 1-like even though the # bullet has no prohibition semantics. R9 closure scopes INV-3 # to exact canonical sentence only.
- test_r9_p2_inv3_canonical_after_heading_no_blank_line_fails · method · L939-L956 — def test_r9_p2_inv3_canonical_after_heading_no_blank_line_fails(self) -> None: # Codex R9 P2 (b): when the canonical sentence is pasted as # prose immediately after a Markdown heading with no blank # line, R8's
re.split(r"\n\s*\n", text) kept the heading and # sentence in one paragraph, and the startswith("## ") # filter skipped the whole thing. R9 closure switches to # line-level heading-strip + whitespace-collapse so heading # adjacency does not bypass the prose scan.