Repository navigation
fix(OMN-19375): the rebuild classifier counts all installed source and exempts an inert version bump - #4057
Conversation
…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
|
No OCC evidence companion was minted for this PR. product PR is a draft; companion suppressed (F-17) Matched in the state: 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 |
…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>
|
| 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
There was a problem hiding this comment.
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
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 missesmodels/,enums/,adapters/,delegation/,routing/,inference/andconfigs/. Before #4053, the real classifier replayed over both dev branches missed 939 of 4393 files undersrc/omnimarketand 1162 of 3322 undersrc/omnibase_infra. Those directories have the same handler fan-in that #4053 measured forevents/:models/has 25 handler importers,enums/19,inference/38 androuting/6. The lane installs both trees whole. The runningomninode-runtimecontainer readsomnimarket @ file:///workspace/sibling-repos/omnimarketfrom itsdirect_url.json, andomnibase_infrais the image's own project. Sosrc/omnimarket/**andsrc/omnibase_infra/**are now lane state. The miss still measurable on dev is omnimarket#2817, which merged as No rebuild with a file underdelegation/. 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].versionand omnimarket's ownuv.lockentry. Each of those PRs rebuilt the dev lane: jobs0805d076,e4d36317andff4dc5de, 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:--no-depsfrom the staged tree (docker/Dockerfile.runtime, workspace mode, confirmed on the live container), so no registry version is resolved.omnimarket.__version__is the literal0.1.0. The one runtime reader of the distribution version,version_handshake.check_plugin_compat, has no caller, and noplugin-compat.yamlexists.runtime_omnimarket_versioncheck compares two lanes built from one image.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-infrais deliberately not exempt, becauseservice_kernel.KERNEL_VERSION,overlay_config_resolverandversion_compatibilityread its version at runtime.Changes
scripts/runtime_change_classifier.py:src/omnimarket/**andsrc/omnibase_infra/**toLANE_STATE_PATH_PATTERNS.VERSION_INERT_PACKAGES = {"omnimarket"},inert_version_bump_paths, which compares tomllib-parsed documents with only the package's own version blanked, andgit_manifest_reader.classify_runtime_pathstakes an optionalmanifest_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-checkoutand 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_affectingreads 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.test_trigger_packaged_source_omn19378.pyandtest_trigger_inert_version_bump_omn19375.pyare new.test_trigger_events_package_omn19383.pyis inverted on purpose: it saidrouting/must not be lane state, which the fan-in measurement above contradicts.test_trigger_dependency_manifests_omn18671.pymoves outside the two packages.Test plan
origin/devscripts give 24 failed and 8 controls passed. With the scripts restored, all 32 pass.trigger_rebuild_on_merge.py --dry-run, using the real omniclaudemaindeploy-gate validator and a real omnimarket clone:pyproject.toml+uv.lock) reads runtime (AC6).scripts/,tests/and one workflow, and no lane-state path.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
Type safety checklist
metadata["key"]ormetadata.get("key")string literal access on Pydantic model fieldsmetadata: dict[str, Any]fields without TypedDict or# ONEX_EXCLUDE:commentexcept Exception— must use narrowed type, or minimal-scope boundary withlogger.exception(...)+ degrade comment, or typed wrap/re-raisedocker-compose.infra.ymlwith required (:?) env vars, updatetests/integration/docker/test_docker_integration.pyfixture dict intest_compose_config_validStrict-gate ordering
Related issues
OMN-19375, OMN-19378. Goal OMN-17427.
Evidence-Ticket: OMN-19375
Evidence-Source: OCC#11065