Skip to content

fix(OMN-19375): the rebuild classifier counts all installed source and exempts an inert version bump - #4057

Merged
jonahgabriel merged 2 commits into
devfrom
jonah/omn-19375-classifier-installed-source-inert-bump
Sep 24, 2026
Merged

jonahgabriel merged 2 commits into
devfrom
jonah/omn-19375-classifier-installed-source-inert-bump

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The runtime-affecting predicate that the rebuild trigger and the release train share was wrong in both directions. This PR fixes both. Tickets: OMN-19375 (the over-count) and OMN-19378 (the under-count).

Under-count (OMN-19378). The canonical deploy-gate list names a fixed set of subtrees. OMN-19383 (#4053) added src/omnimarket/events/**, but the list still misses models/, enums/, adapters/, delegation/, routing/, inference/ and configs/. Before #4053, the real classifier replayed over both dev branches missed 939 of 4393 files under src/omnimarket and 1162 of 3322 under src/omnibase_infra. Those directories have the same handler fan-in that #4053 measured for events/: models/ has 25 handler importers, enums/ 19, inference/ 38 and routing/ 6. The lane installs both trees whole. The running omninode-runtime container reads omnimarket @ file:///workspace/sibling-repos/omnimarket from its direct_url.json, and omnibase_infra is the image's own project. So src/omnimarket/** and src/omnibase_infra/** are now lane state. The miss still measurable on dev is omnimarket#2817, which merged as No rebuild with a file under delegation/. Replayed over the last 60 dev merges, this adds 9 omnimarket rebuilds and 1 omnibase_infra rebuild.

Over-count (OMN-19375). After every omnimarket release, a bot PR changes only [project].version and omnimarket's own uv.lock entry. Each of those PRs rebuilt the dev lane: jobs 0805d076, e4d36317 and ff4dc5de, and the last of these was followed by the C15 failure at 07:51Z. The premise that the bump is inert was verified before changing anything:

  • The lane installs omnimarket --no-deps from the staged tree (docker/Dockerfile.runtime, workspace mode, confirmed on the live container), so no registry version is resolved.
  • omnimarket.__version__ is the literal 0.1.0. The one runtime reader of the distribution version, version_handshake.check_plugin_compat, has no caller, and no plugin-compat.yaml exists.
  • The deploy agent's runtime_omnimarket_version check compares two lanes built from one image.
  • The sibling-pin preflight compares the lock entry with pyproject.toml, and the bump moves both together.

A root-manifest change that is only omnimarket's own version is therefore no longer lane state. omnibase-infra is deliberately not exempt, because service_kernel.KERNEL_VERSION, overlay_config_resolver and version_compatibility read its version at runtime.

Changes

  • scripts/runtime_change_classifier.py:
    • Adds src/omnimarket/** and src/omnibase_infra/** to LANE_STATE_PATH_PATTERNS.
    • Adds VERSION_INERT_PACKAGES = {"omnimarket"}, inert_version_bump_paths, which compares tomllib-parsed documents with only the package's own version blanked, and git_manifest_reader.
    • classify_runtime_paths takes an optional manifest_reader. The canonical half is never narrowed, and every read or parse failure keeps the manifest runtime.
  • scripts/trigger_rebuild_on_merge.py: adds --source-checkout and logs the exempted manifests. Without the flag, nothing is exempt.
  • .github/workflows/runtime-rebuild-trigger-reusable.yml: a sparse checkout of the caller's merge commit and its first parent (the two root manifests only), passed as --source-checkout.
  • scripts/ci/release_train.py: load_runtime_affecting reads the same commit pair from its clone. Without this, the proof-subject walk would stop at bump commits that no lab pass ever ran for.
  • Tests:
    • test_trigger_packaged_source_omn19378.py and test_trigger_inert_version_bump_omn19375.py are new.
    • One assertion in test_trigger_events_package_omn19383.py is inverted on purpose: it said routing/ must not be lane state, which the fan-in measurement above contradicts.
    • One example path in test_trigger_dependency_manifests_omn18671.py moves outside the two packages.

Test plan

The change reaches omnimarket's trigger only when omnimarket advances its pinned reusable to this merge. That follow-up PR is omnimarket's to land.

Runtime startup gate

  • N/A — this PR does not touch any of the above

Type safety checklist

  • No new metadata["key"] or metadata.get("key") string literal access on Pydantic model fields
  • No new metadata: dict[str, Any] fields without TypedDict or # ONEX_EXCLUDE: comment
  • No new bare except Exception — must use narrowed type, or minimal-scope boundary with logger.exception(...) + degrade comment, or typed wrap/re-raise
  • If adding a key to a metadata dict, the key is defined in the relevant TypedDict
  • If adding a service to docker-compose.infra.yml with required (:?) env vars, update tests/integration/docker/test_docker_integration.py fixture dict in test_compose_config_valid

Strict-gate ordering

  • No — not a gate PR, skip this section.

Related issues

OMN-19375, OMN-19378. Goal OMN-17427.

Evidence-Ticket: OMN-19375
Evidence-Source: OCC#11065

…d exempts an inert version bump

Two errors in the runtime-affecting predicate the rebuild trigger and the
release train share, one in each direction.

Under-count (OMN-19378). The canonical deploy-gate list names fixed subtrees.
OMN-19383 added src/omnimarket/events/**, but the list still misses models/,
enums/, adapters/, delegation/, routing/ and configs/: 939 of 4393 files under
src/omnimarket and 1162 of 3322 under src/omnibase_infra before OMN-19383.
Handler fan-in is the same as events/ (models/ 25 handler importers, enums/
19, inference/ 38, routing/ 6). The lane installs both trees whole, so both
are now lane state. omnimarket#2817 (delegation/, merged as No rebuild) is the
measured case. Replayed over the last 60 dev merges: +9 omnimarket rebuilds,
+1 omnibase_infra.

Over-count (OMN-19375). omnimarket's post-release bot PR changes only
[project].version and its own uv.lock entry, and each one rebuilt the dev lane
(jobs 0805d076, e4d36317, ff4dc5de). omnimarket's version string is inert on
the lane: it installs --no-deps from the staged tree (file:// direct_url on the
running container), __version__ is a literal 0.1.0, and the one reader of the
distribution version has no caller. A root manifest change that is only that
package's own version is no longer lane state. omnibase-infra is not exempt
because its runtime reads its own version.

The reusable workflow checks out the merged commit and its parent and passes
--source-checkout; the train reads the same pair from its clone, so the walk
and the trigger agree. Every read failure keeps the manifest runtime.

Live replay with the real canonical validator: the three bump commits read No
rebuild; #2813, #2817 and all ten AC7 runtime PRs read runtime; the real
dependency bump #2691 reads runtime.

Onex-Lane: classifier-fix
Onex-Session: 9e9904cc395d4ded885852026251341d
@onexbot-occ-writer

Copy link
Copy Markdown
Contributor

No OCC evidence companion was minted for this PR.

product PR is a draft; companion suppressed (F-17)

Matched in the state: draft

To clear this: Mark the PR ready for review. The ready_for_review trigger re-fires the born path and the companion mints then.

Reported by node_occ_companion_effect (decline code pr_draft, OMN-16665). This decision was made against the PR's LIVE state at compute time, not at publish time — a green publisher job only means the command reached the broker.

@jonahgabriel
jonahgabriel marked this pull request as ready for review September 24, 2026 11:38
@jonahgabriel
jonahgabriel enabled auto-merge (squash) September 24, 2026 11:39
jonahgabriel pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Sep 24, 2026
…ibase_infra#4057 (#11065)

* evidence(OMN-19375): author OCC companion for OmniNode-ai/omnibase_infra#4057

OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head d9892660214ab447dff223f46919bd0a1c22cef3.

* evidence(OMN-19375): self-bind OCC#11065 + rebind contract_sha256

---------

Co-authored-by: omnimarket-bot <bot@omninode.ai>
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Hostile Reviewer — DEGRADED (informational)

Critical findings: 0
Major findings: 1
Total findings: 9
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)

…gate row

Onex-Lane: classifier-fix
Onex-Session: 9e9904cc395d4ded885852026251341d

@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: 0
Deduped (already posted on this PR): 0
Below quorum (one model only, reported not threaded): 7
Nit-level findings suppressed: 2

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.

Below quorum: 7 finding(s) raised by one model only (OMN-18479)

These are reported and NOT dropped, but they get no thread and do not block: a single model's finding no other model reproduced is not evidence enough to stop a merge. Read them; act on them if they are right.

  • [MAJOR] scripts/runtime_change_classifier.py, _without_own_lock_version / inert_version_bump_paths (glm-review) — Lock's own-entry dependency changes can be silently exempted | _without_own_lock_version blanks only the root package's version, so any other change inside that entry, including edits to its dependenc
  • [MINOR] scripts/runtime_change_classifier.py, _without_project_version (glm-review) — Adding or removing the version key qualifies as inert | Setting "version": None rather than deleting the key makes an absent version and a present version compare equal after normalization. A change t
  • [MINOR] scripts/trigger_rebuild_on_merge.py, main (glm-review) — Manifests are read and parsed twice per invocation | trigger_rebuild_on_merge.main calls inert_version_bump_paths purely for an informational echo, then classify_runtime_paths calls it again, each cal
  • [MINOR] scripts/runtime_change_classifier.py, VERSION_INERT_PACKAGES (glm-review) — VERSION_INERT_PACKAGES proof has no drift guard | omnimarket's exemption rests on the lane installing it --no-deps from a file:// URL and on check_plugin_compat having no caller. Neither fact is asser
  • [MINOR] scripts/runtime_change_classifier.py, _without_own_lock_version (glm-review) — Workspace-style locks fail the exemption permanently | _without_own_lock_version only accepts source = {editable: "."} or {virtual: "."}. uv also emits {directory: "."} and workspace-sourced root entr
  • [MINOR] .github/workflows/runtime-rebuild-trigger-reusable.yml, new checkout step (glm-review) — No test covers the workflow checkout path mismatch | The new workflow step checks out inputs.source_sha with fetch-depth 2 into .source-manifests. If checkout fetches fewer than two commits for an unu
  • [MINOR] scripts/trigger_rebuild_on_merge.py, main (glm-review) — Exemption message printed before the decision is known | main echoes 'Version-only manifest change, not lane state (OMN-19375)' before classify_runtime_paths runs. If the canonical classifier independ

@jonahgabriel
jonahgabriel merged commit 89d4dd6 into dev Sep 24, 2026
132 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-19375-classifier-installed-source-inert-bump branch September 24, 2026 12:12
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