Skip to content

fix(OMN-14988): bash-3.2-safe slash normalization in check_no_infra_inmemory_import.sh - #2498

Merged
jonahgabriel merged 1 commit into
devfrom
jonah/omn-14988-slash-normalization
Jul 27, 2026
Merged

jonahgabriel merged 1 commit into
devfrom
jonah/omn-14988-slash-normalization

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Jul 27, 2026 •

Copy link
Copy Markdown
Collaborator

OMN-14988 — check_no_infra_inmemory_import.sh false-positives on a clean tree

Ticket: OMN-14988
OCC companion: OmniNode-ai/onex_change_control#5133 (autobind) — lands first

Evidence-Ticket: OMN-14988
Evidence-Source: OCC#5133

The defect

The no-infra-inmemory-import gate (OMN-7077 / OMN-13419) — a pre-commit hook and a
required CI Lint step — reported 8 violations on an unmodified dev tree, and all 8
were entries in the script's own ALLOWLIST. Zero true positives; signal-to-noise 0/8.

Reproduced on .200 at clean dev, by direct invocation (not via pre-commit run, so
the failure is in the script itself, independent of the framework or core.hooksPath):

$ env bash scripts/validation/check_no_infra_inmemory_import.sh ; echo $?
  src//omnibase_infra/backends/auto_configure.py:38: ...
  src//omnibase_infra/runtime/runtime_host_process.py:91: ...
  ... 6 more, every one allowlisted ...
Single-canonical in-memory bus (OMN-13419) — 8 violation(s)
1

Root cause — two platform facts that only fail together

  1. BSD grep (macOS) doubles the root separator. grep -rn ... src/ reports
    src//omnibase_infra/.... GNU grep on Linux CI reports src/omnibase_infra/....

  2. The normalization was bash-version-dependent. file="${file//\/\//\/}" collapses
    correctly under bash >= 4.3, but under bash 3.2 — which is /usr/bin/env bash on
    stock macOS, and therefore the interpreter this hook actually runs under locally
    — the
    backslash in the replacement word is retained literally:

    $ /bin/bash -c 'f="src//x.py"; f="${f//\/\//\/}"; echo "$f"'
    src\/x.py        # bash 3.2 — matches no ALLOWLIST entry
    $ /opt/homebrew/bin/bash -c 'f="src//x.py"; f="${f//\/\//\/}"; echo "$f"'
    src/x.py         # bash 5.3 — correct
    

The gate only fails when BSD grep and bash 3.2 are both in play, which is why Linux CI
never saw it and macOS contributors always did.

Fix

Hold the pattern and replacement in variables (_normalize_path), which removes the
backslash-escaping ambiguity entirely and behaves identically on 3.2 and 5.x, and loop so
runs longer than two slashes collapse fully instead of partially (src///a.py -> src/a.py,
not src//a.py). The call site keeps a TRAP comment naming the one-liner and why it must
not come back.

A --print-normalized-path entry point is added so the normalization can be asserted per
interpreter without depending on the local grep flavor.

Seams

Sole boundary is grep stdout line -> ALLOWLIST string comparison. Contract: the path
segment left of the first : normalizes to a single-slash, src/-rooted, repo-relative
path, compared by exact string equality against ALLOWLIST entries in the same form. That
seam is now driven directly by the regression tests via a grep stub, not inferred.
ALLOWLIST contents, the match PATTERN, exit codes, and output text are unchanged.

Test evidence — RED before, GREEN after

Same test file both runs:

Run Result
Against the pre-fix script 13 failed, 6 passed
Against the fixed script 19 passed

The RED is "exists but wrong", not "missing": test_gate_exits_zero_on_bsd_grep_doubled_slash_hits
and test_gate_still_flags_non_allowlisted_doubled_slash_hit fail on /bin/bash (3.2)
and pass on bash 5.3
against the pre-fix script — that split is the defect signature.

Coverage added:

  • Normalization unit assertions per bash interpreter present on the host (so 3.2 is
    covered where it exists), including the exact reported src//omnibase_infra/backends/auto_configure.py
    case and an explicit "no backslash in output" assertion.
  • End-to-end gate runs with a grep stub pinning BSD-style src// hits, so the
    doubled-slash input is deterministic on every platform rather than dependent on the local
    grep.
  • Anti-neutering test: a non-allowlisted import arriving with the same src// prefix
    must still be reported and still exit 1. A naive "fix" that allowlisted everything would
    fail here.
  • Clean-tree run of the real script under every bash — the exact reported symptom.
  • Static ratchet rejecting reintroduction of the fragile substitution in executable
    lines. This one is RED on every platform including Linux CI, where the bash 3.2
    behavior cannot be reproduced behaviorally.

Gate results

Heavy gates ran on .200 (stickybeatz-studio) per rule 11a, via patch-transfer with
sha256 verified identical on both hosts (f8f98289… script, d6f483a8… test):

  • Governed selector (scripts/ci/detect_test_paths.py) resolved this change to
    tests/unit/scripts/ — no hand-typed -k.
  • uv run pytest tests/unit/scripts/ -q -n auto on .200: 840 passed, 0 failed.
  • Clean-dev baseline for the same selection on .200 was 8 failed — 7 shell-hygiene
    (see deviations) and 1 test_gate_allows_allowlisted_adapter_import, which was this
    defect
    already failing the pre-existing gate test on .200. This PR takes that
    selection to zero failures and introduces none.
  • shellcheck -x on the modified script: clean.
  • ruff check / ruff format --check / mypy --strict on the test file: clean.
  • Full local pre-commit run --files on both changed files: all hooks pass, including
    Block infra-path EventBusInmemory imports (OMN-7077) -> Passed.

The blocker this retires

OMN-14988 was escalated because an empty git commit --allow-empty (zero content change)
could not clear this hook, forcing a documented --no-verify bypass against rule 10 — a
gate that cannot be satisfied by a zero-diff commit trains bypass behavior directly.

The commit in this PR was created with the full pre-commit suite running and the OMN-7077
hook passing. No --no-verify, no skip token, no allowlist addition.

Deviations from standing process (stated, not hidden)

  1. Push ran from this Mac, not .200. All heavy gates (test suite, shellcheck,
    ruff, mypy, pre-commit) ran on .200. The push itself could not: the local PreToolUse
    worktree guard blocks creating a worktree for a remote path over ssh (it resolves
    the remote path against the local canonical root), and .200's canonical-clone guard
    blocks pushing from the canonical clone. Both guards were left intact —
    ONEX_WORKTREES_ROOT, onex hooks disable, and ALLOW_CANONICAL_CLONE_COMMIT=1 were
    all deliberately not used. A push is a network op, not the contended-CPU path rule
    11a exists to move off this Mac.
  2. .200 gate runs used the canonical clone's working tree (patch applied, gates run,
    git checkout -- restored, porcelain verified 0) — CLAUDE.md permits running there;
    nothing was branched, staged, or committed in it. The authoritative worktree is
    $OMNI_HOME/omni_worktrees/OMN-14988/omnibase_infra.

Incidental findings on .200 (not fixed here, not mine to land)

  • The 7 baseline test_shell_hygiene_gate.py failures were not a missing shellcheck —
    shellcheck 0.11.0 is installed at /opt/homebrew/bin, which a non-interactive ssh
    PATH does not include
    . With the PATH corrected the gate is green. Any automation that
    ssh's into .200 and runs these gates without /opt/homebrew/bin on PATH gets a
    fail-closed red that looks like a real failure.
  • ~/omni_home/omnibase_infra on .200 contains a stale empty validation/ directory
    (dated Jun 12) that trips the ONEX Root Directory Cleanliness hook. Being empty and
    untracked it is invisible to git status --porcelain. Absent from the worktree; harmless
    to this PR, but it makes that hook permanently red in .200's canonical clone.

Merge

Codex lands. No --auto, not a draft. Companion #5133 first.

A hand-authored companion (#5132) was opened companion-first three minutes before OCC
autobind produced #5133 for this PR; per standing precedent autobind wins the companion
slot and #5132 was closed as the duplicate. #5133 is the thin autobind shape — its three
dod_evidence items prove only that this PR exists and has files, none of them falsifiable
against the fix. The falsifiable probes (clean-tree exit-0 under bash 3.2, the RED/GREEN
counts, the anti-neutering check, governed-selection 840/0, shellcheck, and the OMN-7077
hook passing without --no-verify) are recorded in this body and as a dod_evidence
comment on OMN-14988, and should be re-landed onto contracts/OMN-14988.yaml after #5133
merges — the same repair pattern as onex_change_control#5129 and #5117.

…nmemory_import.sh

The no-infra-inmemory-import gate (OMN-7077/OMN-13419) false-positived on a
clean tree on macOS: 8 violations reported, all 8 in the script's own
ALLOWLIST, zero true positives.

Root cause is two platform facts compounding:
  * BSD grep (macOS) reports the search root "src/" as "src//" in every hit,
    so paths arrive as src//omnibase_infra/... GNU grep on Linux CI does not.
  * The normalization ${file//\/\//\/} is bash-version-dependent. Under bash
    >= 4.3 it collapses correctly; under bash 3.2 -- which IS /usr/bin/env bash
    on stock macOS, and therefore the interpreter this hook runs under locally
    -- the backslash in the replacement word is retained literally, producing
    src\/omnibase_infra/... which matches no ALLOWLIST entry.

Fix: hold the pattern and replacement in variables (_normalize_path), removing
the escaping ambiguity entirely; loop so runs longer than two slashes collapse
fully rather than partially.

Adds regression coverage in tests/unit/scripts/validation/:
  * normalization asserted per bash interpreter present on the machine, so
    bash 3.2 is covered where it exists;
  * end-to-end gate runs with a grep stub pinning BSD-style src// hits, both
    for the allowlisted set (must exit 0) and for a non-allowlisted violation
    (must still exit 1 -- the fix must not neuter the gate);
  * a clean-tree run of the real script under every bash;
  * a static ratchet rejecting reintroduction of the fragile substitution in
    executable lines, which is RED on every platform including Linux CI where
    the bash 3.2 behavior cannot be reproduced.

RED/GREEN: 13 failed against the pre-fix script, 19 passed after.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba4ce4a2-79e5-46f3-a97c-aba6790353c2

📥 Commits

Reviewing files that changed from the base of the PR and between d91fbcc and c9ca7eb.

📒 Files selected for processing (2)
  • scripts/validation/check_no_infra_inmemory_import.sh
  • tests/unit/scripts/validation/test_check_no_infra_inmemory_import.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-14988-slash-normalization

Comment @coderabbitai help to get the list of available commands.

jonahgabriel added a commit to OmniNode-ai/onex_change_control that referenced this pull request Jul 27, 2026
…ibase_infra#2498 (#5133)

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

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

* evidence(OMN-14988): self-bind OCC#5133 + rebind contract_sha256

---------

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

Copy link
Copy Markdown
Contributor

⚠️ Hostile Reviewer — DEGRADED (informational)

Blocking findings (critical): 0
Total findings: 0
Models succeeded: none

Note: All reviewer models failed or were unavailable. Degraded results are informational during the pilot phase (OMN-8468/OMN-8524) and do not block merge. Error: all review endpoints [192.168.86.201:8000 192.168.86.201:8001 ] unreachable — preflight short-circuit (no models available)


Gate semantics (pilot phase)

Verdict Meaning Blocks merge?
passed No critical findings No
blocked CRITICAL findings found Yes
degraded All models unavailable (infra) No (pilot)

Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8468/OMN-8524)

@jonahgabriel
jonahgabriel merged commit a7c3039 into dev Jul 27, 2026
149 of 156 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-14988-slash-normalization branch July 27, 2026 14:55
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