diff --git a/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/contract.yaml b/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/contract.yaml index 0c1539281f..d9b984a4c0 100644 --- a/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/contract.yaml +++ b/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/contract.yaml @@ -340,7 +340,7 @@ contract_version: major: 1 minor: 7 patch: 0 -node_version: "1.12.0" +node_version: "1.12.1" description: > Scheduled sweep wiring companion-merge -> dod_verify -> governed Done flip. Enumerates merged onex_change_control evidence companions, extracts their Evidence-Ticket binding, re-runs dod_verify, and flips Done or posts a gap comment via the Linear API. DRY-RUN by default; ONEX_AUTOCLOSE_DISABLED kill switch checked first. diff --git a/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/handlers/handler_evidence_autoclose_sweep.py b/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/handlers/handler_evidence_autoclose_sweep.py index 7542ecd45c..bde8af5b27 100644 --- a/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/handlers/handler_evidence_autoclose_sweep.py +++ b/src/omnibase_infra/nodes/node_evidence_autoclose_sweep_effect/handlers/handler_evidence_autoclose_sweep.py @@ -605,7 +605,7 @@ def _dod_verify_argv(ticket_id: str) -> list[str]: #: fingerprint (see `_gap_fingerprint_parts`). Pinned against the contract by #: `test_the_pinned_contract_version_is_the_node_contract_version`, so it #: cannot drift into describing a rule the closer no longer applies. -_GAP_FINGERPRINT_CONTRACT_VERSION = "1.12.0" +_GAP_FINGERPRINT_CONTRACT_VERSION = "1.12.1" # OMN-16106. Linear transient-failure retry policy defaults. See # ``_LinearClient``'s class docstring for the live measurement these exist to @@ -2034,6 +2034,17 @@ def _coverage_corpus_counts( | \brows?\s+carrying\b | \b\d+\s+occurrences?\b | \bno\s+occurrences?\b + # OMN-18135 follow-up, measured against OMN-17771's REAL criteria: the + # first cut recognised only 2 of its 5, so the ticket the ruling names as + # its worked example would still have held. Every phrase below is lifted + # from one of those criteria, which is the standing rule for this set -- + # a marker earns its way in by appearing in a criterion that exists, not + # by seeming plausible. + | \bzero\b[^.]{0,80}\boccurrences?\b # "Zero `client_id=x` ... occurrences" + | \bcheckers?\b[^.]{0,24}\bgreen\b # "`beta-layout` checkers green" + | \bexists\s+on\s+the\b # "a client that exists on the plane" + | \bmerged\s+to\s+`?\w # "Merged to `main` and read back" + | \bHTTP\s+\d{3}\b # "returns HTTP 200 with a form" | \bis\s+(running|ready|healthy|present|absent|enabled|disabled)\b | \breaches\s+(running|ready)\b | \b\d+\s+restarts?\b diff --git a/tests/unit/nodes/node_evidence_autoclose_sweep_effect/test_omn_18135_readback_join.py b/tests/unit/nodes/node_evidence_autoclose_sweep_effect/test_omn_18135_readback_join.py index e74f5efe51..cb0becb23e 100644 --- a/tests/unit/nodes/node_evidence_autoclose_sweep_effect/test_omn_18135_readback_join.py +++ b/tests/unit/nodes/node_evidence_autoclose_sweep_effect/test_omn_18135_readback_join.py @@ -511,3 +511,71 @@ async def test_a_readback_does_discharge_a_state_criterion_beside_a_real_proof() _seed_redraw(linear, checks) result = await _handler(_skill_result(checks), linear).handle(_request()) assert result.outcomes[0].decision is EnumEvidenceAutocloseDecision.FLIPPED + + +# -------------------------------------------------------------------------- +# The vocabulary, measured against the criteria it has to read. +# -------------------------------------------------------------------------- + +#: OMN-17771's acceptance section, verbatim from the ticket. The ruling names +#: this ticket as its worked example, and the first cut of the marker set +#: recognised only 2 of these 5 — so the example would still have held. Each +#: phrase added afterwards is lifted from a criterion below rather than +#: invented, which is the standing rule for this set. +_OMN_17771_ACCEPTANCE = ( + "## Acceptance\n" + "\n" + "AC1. Zero `client_id=omnidash-spa` and zero `client_id=omniweb` " + "occurrences in any customer-facing guide, proven by grep at the merged " + "tip.\n" + "AC2. The Step 1a registration URL, pasted verbatim, returns HTTP 200 " + "with a registration form — probed from a machine with no source checkout " + "and no org credential, not asserted by inspection.\n" + "AC3. The Step 1b token command names a client that exists on the plane " + "the guide names, proven by an `invalid_grant` (user rejected) rather " + "than `unauthorized_client` / `Client not found` (client rejected) " + "response against a deliberately invalid user.\n" + "AC4. `no-private-repo-links` and `beta-layout` checkers green.\n" + "AC5. Merged to `main` and read back from `origin/main`.\n" +) + + +def test_the_worked_example_reads_as_state_shaped_end_to_end() -> None: + """Every one of OMN-17771's five real criteria, not a paraphrase. + + This is the assertion that would have caught the first cut shipping a + predicate too tight to admit the ticket the ruling names. + """ + from omnibase_infra.nodes.node_evidence_autoclose_sweep_effect.handlers.handler_evidence_autoclose_sweep import ( + _acceptance_criteria_items, + _criterion_is_state_shaped, + _every_criterion_is_state_shaped, + ) + + items = _acceptance_criteria_items(_OMN_17771_ACCEPTANCE) + assert len(items) == 5 + assert all(_criterion_is_state_shaped(item) for item in items) + assert _every_criterion_is_state_shaped(_OMN_17771_ACCEPTANCE) is True + + +@pytest.mark.parametrize( + "criterion", + [ + # The widened phrases must not drag behaviour criteria with them. + "AC1 the handler exists on the plane and refuses a bad envelope", + "AC1 a test asserts zero occurrences of the old symbol", + "AC1 merged to `main`, and the retry path stops after 3 attempts", + "AC1 the suite is green", + ], +) +def test_the_widened_vocabulary_did_not_drag_behaviour_along(criterion: str) -> None: + """Each of these carries a widened state phrase AND behaviour language. + + The veto still wins, which is the property that keeps the widening from + becoming a general loosening. + """ + from omnibase_infra.nodes.node_evidence_autoclose_sweep_effect.handlers.handler_evidence_autoclose_sweep import ( + _criterion_is_state_shaped, + ) + + assert _criterion_is_state_shaped(criterion) is False