Skip to content

feat(OMN-18135): the closer joins readbacks to state-shaped criteria, and names the bar - #3409

Merged
jonahgabriel merged 1 commit into
devfrom
jonah/omn-18135-readback-closer
Sep 10, 2026
Merged

jonahgabriel merged 1 commit into
devfrom
jonah/omn-18135-readback-closer

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Evidence-Source: OCC#8985
Evidence-Ticket: OMN-18135

OMN-18135 AC3 + AC4 — the closer's half

Implements the ruling at docs/tracking/ROLLING_WORK_LEDGER.md:6148, 2026-09-10T17:50:03Z. Provenance stated as it is: an orchestrator ruling under the deterministic-truth doctrine, not an operator ruling.

omnimarket#2460 carries the proof class. This carries the join, because deciding whether a criterion is state-shaped needs the ticket's acceptance text, and node_dod_verify has no Linear access and never sees it. That is why AC4 could not be a single omnimarket change.

It moves in both directions

Looser. A ticket whose every parsed criterion asserts live state, each discharged by a verified readback, no longer dies on behavior_proving_count <= 0. This is the case the ruling exists to admit. It is bounded to all criteria: one behaviour-shaped criterion, or a body whose criteria cannot be read at all, and the behaviour proof is still required. A ticket is judged by its strictest criterion, never on average.

Stricter. A behaviour-shaped criterion whose only verified checks are readbacks now holds. Binding used to key on check status alone and never looked at proof class, so a readback silently discharged a criterion asserting what the code does. That hole is invisible to every test that has no behaviour proof at all, because the behaviour conjunct catches those first — so it has its own test with a real behaviour proof sitting beside it, and a positive control where the same shape with a state-shaped criterion does release.

Untouched, deliberately. A criterion proved by a merge-state, surrogate or indeterminate check binds exactly as before. Narrowing those is a different argument nobody has made, and making it here would retroactively un-close tickets that have already flipped on that basis.

AC3: the hold names the bar

The gap_no_behavior_proof comment now says what would clear it:

  • which command shapes prove behaviour — the test runners and the ONEX CLI, named individually;
  • which prefixes are transparent, so an author does not lose the class to env -u or cd;
  • that a live probe through ssh, aws, kubectl, curl, psql or a shell loop is not behaviour-proving, however real the thing it exercised;
  • that an asserted readback is the admissible route for a criterion asserting live state, and that the command must be able to go red on what it read.

Three lanes spent a night rediscovering this rule by measurement because the comment stated a verdict and no remedy.

The honest limit, in the code and not only here

Criterion shape is read from prose. It is a heuristic and it is tight on purpose: state-shaped requires a positive state marker and no behaviour marker, and everything else falls to behaviour and holds. The asymmetry is chosen rather than incidental — reading a criterion as behaviour-shaped costs a comment, while reading one as state-shaped releases a flip on a readback. So the vocabulary earns its way in one phrase at a time, every entry is drawn from a criterion that exists in the corpus, and the veto wins ties. test_anything_else_falls_to_behaviour_and_holds pins the ambiguous cases, including a state marker vetoed by behaviour language.

RED first

At parent 0a704957c, verbatim: 13 failed, 4 passed. After: 19 passed in the new module and 416 passed across the closer suite.

Verification

  • Governed pre-push green on 9fddfcc8b8e82b0ba524dfeb7d3125d72d895041. The selector escalated and placed the run off-box: REMOTE LAB RUN PASS accepted ... h201.3 ran 27597 tests green ... (suite log sha256 6009ab599f801d9e003e31d15728e586fe718b2cbd590d0409772d33f68c6151, 285s). No override variable set, no escalation bypassed.
  • uv run mypy --strict on the node: clean. ruff format --check, ruff check: clean.
  • node_version 1.11.0 to 1.12.0, so the gap-comment fingerprint moves with the rule it describes.
  • Lab coverage, honestly: this node runs only inside the scheduled evidence-autoclose-sweep workflow, not on the .201 compose dev lane or the onex-lab overlay. No lab pass exercises it and none is claimed. Its proof surface is the next scheduled closer tick after merge.

Landing order

omnimarket#2460 should land first. It is inert on its own — binding already keyed on status and never on proof class, and behavior_proving_count does not change — so nothing moves until this PR teaches the closer the join. Landing this one first would be the harmless order too, since readback_proving_count reads 0 from a verifier that does not emit it and 0 releases nothing.

… and names the bar

Implements AC3 and the closer half of AC4 from the ruling recorded at
docs/tracking/ROLLING_WORK_LEDGER.md:6148 (orchestrator, under the
deterministic-truth doctrine; not an operator ruling). omnimarket#2460
carries the proof class. This carries the JOIN, because deciding whether a
criterion is state-shaped needs the ticket's acceptance text and
node_dod_verify never sees it.

It moves in BOTH directions, deliberately.

LOOSER: a ticket whose every parsed criterion asserts live state, each
discharged by a verified readback, no longer dies on
behavior_proving_count <= 0. That is the case the ruling exists to admit.
Bounded to ALL criteria: one behaviour-shaped criterion, or a body whose
criteria cannot be read, and the behaviour proof is still required. A ticket
is judged by its strictest criterion, never on average.

STRICTER: a behaviour-shaped criterion whose only verified checks are
readbacks now HOLDS. Binding used to key on status alone and never on proof
class, so a readback silently discharged a criterion asserting what the code
does. That hole is invisible to every test that has no behaviour proof at
all, so it has its own test with a real proof beside it.

Deliberately untouched: merge-state, surrogate and indeterminate checks bind
exactly as before. Narrowing those is a different argument nobody has made,
and making it here would retroactively un-close tickets that flipped on that
basis.

AC3: the gap_no_behavior_proof comment now names the bar -- which command
shapes prove behaviour, which prefixes are transparent, that a live probe
through ssh/aws/kubectl/curl/a shell loop is not behaviour-proving, and that
an asserted readback is the admissible route for live state. A hold that
states a verdict without a remedy teaches nobody anything, which is what
three lanes spent a night rediscovering by measurement.

HONEST LIMIT, in the code and not only in the PR: criterion shape is read
from prose and is a heuristic. State-shaped requires a positive state marker
AND no behaviour marker; everything else falls to behaviour and holds. The
asymmetry is chosen -- reading a criterion as behaviour-shaped costs a
comment, reading one as state-shaped RELEASES a flip on a readback -- so the
vocabulary earns its way in one phrase at a time and the veto wins ties.

node_version 1.11.0 -> 1.12.0, so the gap-comment fingerprint moves with the
rule it describes.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hostile Reviewer — adversarial findings (OMN-17492)

Models succeeded: glm-review
Models failed: codex
New finding threads: 1
Deduped (already posted on this PR): 0
Nit-level findings suppressed: 1

The model is the FINDER, never the gate: merge is gated only by the
deterministic Hostile Review Thread Gate, which blocks while
hostile-reviewer threads are unresolved. Resolve each thread after
addressing (or rejecting, with a reply) its finding.

Findings not anchored to a changed file

  • [MAJOR] hostile-reviewer (glm-review)

    Overly broad state markers ('returns', 'responds', 'serves', 'contains') can release behaviour criteria | _STATE_MARKER_RE admits \breturns?\b, \bresponds?\b, \bserves?\b, and \bcontains?\b as positive evidence of live-state shape. These verbs are equally at home in behaviour assertions, e.g. 'the API returns 404 when the token is expired', 'the parser serves the malformed case', 'the CLI contains a retry loop'. None of these examples carry a veto word from _BEHAVIOUR_MARKER_RE (no 'test', 'handler', 'suite

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MAJOR] hostile-reviewer (glm-review)

    State-shaped gate trusts parsed criteria only; criteria outside the parser are unchecked | _every_criterion_is_state_shaped gates the behavior_proving_count conjunct on _acceptance_criteria_items(description). If the parser extracts a subset of the ticket's real acceptance criteria (e.g. criteria listed without a recognised heading, nested lists, or a body over a truncation limit), the join is computed over a partial view. A ticket with one state-shaped parseable criterion and one unparseable behaviour crit

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (glm-review)

    Readback-blocked note truncates without an overflow indicator | readback_note joins readback_blocked[:_MAX_UNCOVERED_LISTED] with no 'and N more' suffix. The unbound list elsewhere in the same function tracks unlabelled counts and appends summary text; the new note can silently under-report when more criteria than _MAX_UNCOVERED_LISTED are readback-blocked, which understates the scope of the hold the author is being asked to fix. | Evidence: " OMN-18135: "
    + ", ".join(readback_blocked[:_MAX_UNCO

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

  • [MINOR] hostile-reviewer (glm-review)

    Admissible-command list duplicated as prose in the hold comment will drift | The gap_no_behavior_proof reason enumerates test runners, transparent prefixes, and readback-capable tools as a hardcoded English sentence. The classifier that actually decides proof class lives elsewhere (omnimarket / the verifier). When the verifier adds a runner or prefix, the comment becomes false, and nothing in this repo pins the two together. The diff bumps _GAP_FINGERPRINT_CONTRACT_VERSION for the gap fingerprint but no tes

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

Findings demoted from threads (anchor rejected)

  • [MAJOR] hostile-reviewer (glm-review)

    No test for readback release with a description lacking any criteria | The comment on the new conjunct claims a body with no parseable criteria is held by the OMN-18056 binding gate 'a conjunct later'. This dependency is asserted in prose but untested in the diff. If _ac_binding_gap permits a description with no AC heading through some other leg (for example when bindings exist for labels a human added to the companion contract rather than the ticket body), a readback_proving_count > 0 combined with an empt

    Resolve this thread when addressed — the Hostile Review Thread Gate blocks while hostile-reviewer threads are unresolved (OMN-17492).

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Hostile Reviewer — DEGRADED (informational)

Critical findings: 0
Major findings: 3
Total findings: 6
Models succeeded: glm-review

Note: Fewer than 2 reviewer models succeeded. Degraded results are informational (OMN-8468/OMN-8524) and do not block merge. Error: cli_review exit 2 (fewer than 2 models succeeded — partial/total outage)


Semantics (OMN-17492 — the model finds, thread resolution gates)

Surface Meaning Blocks merge?
Review threads Per-finding, posted by the reviewer No (informational)
Hostile Review Thread Gate Deterministic: unresolved hostile-reviewer threads exist Fails until resolved (not yet a required context)
degraded verdict Fewer than 2 models succeeded (infra) No

Powered by omniintelligence.review_pairing.cli_review — multi-model adversarial review: qwen3-review, qwen3-review-b, glm-review (OMN-8468/OMN-8524/OMN-17492)

jonahgabriel added a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 10, 2026
#8985)

* evidence: OCC companion pass 1 for OmniNode-ai/omnibase_infra#3409

* evidence: OCC companion self-bind for #8985

---------

Co-authored-by: node-occ-companion-effect <occ-companion-effect@omninode.ai>
Co-authored-by: jonahgabriel <jonah@omninode.ai>
@jonahgabriel
jonahgabriel merged commit f1f72cc into dev Sep 10, 2026
201 of 221 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-18135-readback-closer branch September 10, 2026 20:59
Patel230 pushed a commit that referenced this pull request Sep 16, 2026
… and names the bar (#3409)

Implements AC3 and the closer half of AC4 from the ruling recorded at
docs/tracking/ROLLING_WORK_LEDGER.md:6148 (orchestrator, under the
deterministic-truth doctrine; not an operator ruling). omnimarket#2460
carries the proof class. This carries the JOIN, because deciding whether a
criterion is state-shaped needs the ticket's acceptance text and
node_dod_verify never sees it.

It moves in BOTH directions, deliberately.

LOOSER: a ticket whose every parsed criterion asserts live state, each
discharged by a verified readback, no longer dies on
behavior_proving_count <= 0. That is the case the ruling exists to admit.
Bounded to ALL criteria: one behaviour-shaped criterion, or a body whose
criteria cannot be read, and the behaviour proof is still required. A ticket
is judged by its strictest criterion, never on average.

STRICTER: a behaviour-shaped criterion whose only verified checks are
readbacks now HOLDS. Binding used to key on status alone and never on proof
class, so a readback silently discharged a criterion asserting what the code
does. That hole is invisible to every test that has no behaviour proof at
all, so it has its own test with a real proof beside it.

Deliberately untouched: merge-state, surrogate and indeterminate checks bind
exactly as before. Narrowing those is a different argument nobody has made,
and making it here would retroactively un-close tickets that flipped on that
basis.

AC3: the gap_no_behavior_proof comment now names the bar -- which command
shapes prove behaviour, which prefixes are transparent, that a live probe
through ssh/aws/kubectl/curl/a shell loop is not behaviour-proving, and that
an asserted readback is the admissible route for live state. A hold that
states a verdict without a remedy teaches nobody anything, which is what
three lanes spent a night rediscovering by measurement.

HONEST LIMIT, in the code and not only in the PR: criterion shape is read
from prose and is a heuristic. State-shaped requires a positive state marker
AND no behaviour marker; everything else falls to behaviour and holds. The
asymmetry is chosen -- reading a criterion as behaviour-shaped costs a
comment, reading one as state-shaped RELEASES a flip on a readback -- so the
vocabulary earns its way in one phrase at a time and the veto wins ties.

node_version 1.11.0 -> 1.12.0, so the gap-comment fingerprint moves with the
rule it describes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant