Skip to content

feat(OMN-14694): broaden WS8 canary → no-io-outside-effects archetype-purity gate - #1449

Merged
jonahgabriel merged 3 commits into
devfrom
jonahgabriel/omn-14694-no-db-in-orchestrator
Jul 16, 2026
Merged

jonahgabriel merged 3 commits into
devfrom
jonahgabriel/omn-14694-no-db-in-orchestrator

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Ticket

Closes OMN-14694 (WS8 canary — no-db-in-orchestrator ValidatorNode COMPUTE), first Class-A rule under parent OMN-14662, epic OMN-2362 (Generic Validator Node Architecture). Operator resolved WS8 HOME = omnibase_core.

What

The first WS8 archetype-specific layering rule converted to a canonical ValidatorNode COMPUTE. Unlike the universal 4 rules shipped in OMN-14659 / #1447 (which AST-scan every file blindly), this rule keys off each node's declared archetype and only flags DB-driver imports inside ORCHESTRATOR node packages.

Mirrors the OMN-14659 / #1447 shape exactly, reusing the OMN-14656 / #1446 sync file-gather EFFECT + canonical ModelValidationReport/ModelValidationFinding (no forked models):

  • node_no_db_in_orchestrator_check_compute — def-B handle(request) -> response, pure / deterministic / no I/O, no event-envelope import.
    • archetype_resolver.py parses each contract.yaml to find orchestrator node directories.
    • visitor_db_io.py AST-scans the co-located .py modules for imports of sqlite3, aiosqlite, psycopg, psycopg2, asyncpg, sqlalchemy.
    • runtime_no_db_in_orchestrator_check.py CLI backs both the pre-commit hook and the CI gate (DRY, OMN-13305). The filesystem walk is delegated to the paired EFFECT (node_source_file_gather_effect); the COMPUTE stays pure over in-memory strings.

The seam (field it keys on)

Top-level node_type and descriptor.node_archetype in each node's contract.yaml. A node directory is an ORCHESTRATOR package when either equals orchestrator (sourced from EnumNodeArchetype.ORCHESTRATOR, so a vocabulary rename breaks loudly). Only .py files whose parent directory equals such a contract's directory are DB-scanned — the archetype fact, not a blind every-file scan, decides scope.

Enforcement, not detection (Rule #5) — all in this PR

  • Remote pre-commit hook: .pre-commit-hooks.yaml → check-no-db-in-orchestrator (for consuming repos).
  • Self-wired pre-commit hook: .pre-commit-config.yaml (repo src/ is clean — the sole orchestrator, node_compliance_orchestrator, imports no DB driver; verified full-tree scan = PASS).
  • CI gate: .github/workflows/validator-no-db-in-orchestrator.yml — standalone, no needs: (per the OMN-14666/14668 skip-then-vacuous-green lesson), runs the unit suite + a blocking src/ self-scan. Same COMPUTE node backs hook + gate, so local and CI verdicts cannot drift. Suggested required-status context: No DB In Orchestrator Validator / validate.

RED-against-exists-but-wrong proof

tests/unit/nodes/node_no_db_in_orchestrator_check_compute/test_node_no_db_in_orchestrator_check_compute.py — the load-bearing test_red_* triad drives the same DB-importing handler source through three placements and asserts the gate discriminates on archetype, not on the mere presence of DB code:

  1. test_red_orchestrator_handler_with_db_io_fails — orchestrator contract + a handler that does import sqlite3; sqlite3.connect(...) → FAIL, one finding at handler.py:1, message names sqlite3 and "DB access in ORCHESTRATOR node". (exists-but-wrong is caught, not silently green.)
  2. test_red_compute_handler_with_db_io_passes — the identical DB-importing handler in a COMPUTE package → PASS. Proves the FAIL above is real archetype-keying, not an artefact of the DB source existing.
  3. test_red_clean_orchestrator_passes — orchestrator + clean handler → PASS (not a blanket "orchestrator == fail").

Plus: both-seam-field coverage, every forbidden module (incl. dotted sqlalchemy.orm / psycopg.rows), # db-io-ok suppression, relative-import non-trip, dir-scoping (DB import in a sibling non-orchestrator package passes), and ERROR findings for unparseable contract YAML / handler SyntaxError. 34 node tests + 131 across the whole WS8 family all pass.

dod_evidence

  • uv run pytest tests/unit/nodes/node_no_db_in_orchestrator_check_compute/ -q → 34 passed; whole WS8 family → 131 passed.
  • uv run mypy on the WS8 node handlers → Success, no issues (25 files).
  • ruff format + ruff check → clean.
  • Self-scan: python -m ...runtime_no_db_in_orchestrator_check --root src → exit 0, "OK: No database I/O found in ORCHESTRATOR node packages".
  • pre-commit on all changed files → green (committed with no --no-verify).

Ratchet hygiene (side fixes, no gate loosened)

  • Converted the 5 WS8-family handlers (OMN-14656/14659) + this one to model_dump(mode="json") — behaviour-identical (all ModelValidationFinding fields are JSON-safe; severity is Literal[str], not an enum) — removing 5 pre-existing bare-model_dump() violations that feat(OMN-14659): WS8 fan-out — 4 canonical arch-* ValidatorNode COMPUTE nodes #1447 left above the ceiling (314 → 309) and lowering --max-violations 310 → 309.
  • Allowlisted archetype_resolver.py in .yaml-validation-allowlist.yaml (structural read of heterogeneous contract.yaml; same pattern as operation_match_requires_operation.py / node_compliance_scan_compute); test_yaml_allowlist.py → 10 passed.

Not in this PR

  • The other 8 Class-A rules fan out after this canary lands + verifies (per task scope).
  • OCC evidence companion is authored by a non-implementer (no self-authored evidence).

Evidence-Ticket: OMN-14694
Evidence-Source: OCC#4285

…PUTE

First WS8 Class-A archetype-specific layering rule (epic OMN-2362), HOME =
omnibase_core. Unlike the universal OMN-14659 lints that scan every file
blindly, this COMPUTE keys off each node's declared archetype (the seam) and
only flags DB-driver imports inside ORCHESTRATOR node packages.

New node (mirrors OMN-14659 / #1447 exactly):
- node_no_db_in_orchestrator_check_compute — def-B handle(request)->response,
  pure/deterministic/no-I/O. archetype_resolver.py parses each contract.yaml
  (node_type / descriptor.node_archetype) to find orchestrator node dirs;
  visitor_db_io.py AST-scans co-located .py modules for imports of sqlite3,
  aiosqlite, psycopg, psycopg2, asyncpg, sqlalchemy. Reuses the OMN-14656
  sync file-gather EFFECT + canonical ModelValidationReport/Finding (no fork).
- runtime CLI backs BOTH the pre-commit hook and the CI gate (DRY, OMN-13305):
  pre-commit resolves each staged file's node-package dir + sibling contract;
  full-tree mode delegates the walk to node_source_file_gather_effect.

Enforcement, not detection (Rule #5), all in this PR:
- .pre-commit-hooks.yaml remote hook (check-no-db-in-orchestrator) for peers.
- .pre-commit-config.yaml self-wired hook (repo src/ is clean — the sole
  orchestrator, node_compliance_orchestrator, imports no DB driver).
- .github/workflows/validator-no-db-in-orchestrator.yml — standalone blocking
  CI gate (no needs:, per OMN-14666/14668) running the unit suite + a blocking
  src/ self-scan; same COMPUTE node so local and CI verdicts cannot drift.

RED-against-exists-but-wrong proof (test_red_* triad): the same DB-importing
handler source FAILS in an ORCHESTRATOR package, PASSES in a COMPUTE package,
and the clean orchestrator PASSES — proving the gate catches the real
archetype-specific violation, not green-on-absence and not a blind scan.

Ratchet hygiene (side fixes, no gate loosened):
- Converted the 5 WS8-family handlers (OMN-14656/14659) + this one to
  model_dump(mode="json") — behaviour-identical (all finding fields are
  JSON-safe; severity is Literal[str], not an enum) — removing 5 pre-existing
  bare-model_dump violations (314->309) and lowering the ratchet ceiling to 309.
- Allowlisted archetype_resolver.py in .yaml-validation-allowlist.yaml
  (structural read of heterogeneous contract.yaml; same pattern as
  operation_match_requires_operation.py).

Closes OMN-14694
@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

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: 19 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: 3a9f5168-ab6e-4bc7-87a7-09c618f121fe

📥 Commits

Reviewing files that changed from the base of the PR and between f22c53c and 1559758.

📒 Files selected for processing (21)
  • .github/workflows/validator-no-io-outside-effects.yml
  • .pre-commit-config.yaml
  • .pre-commit-hooks.yaml
  • .yaml-validation-allowlist.yaml
  • pyproject.toml
  • src/omnibase_core/models/nodes/no_io_outside_effects_check/__init__.py
  • src/omnibase_core/models/nodes/no_io_outside_effects_check/model_no_io_outside_effects_check_input.py
  • src/omnibase_core/nodes/node_no_direct_kafka_producer_check_compute/handler.py
  • src/omnibase_core/nodes/node_no_env_fallbacks_check_compute/handler.py
  • src/omnibase_core/nodes/node_no_hardcoded_ip_check_compute/handler.py
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/__init__.py
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/archetype_resolver.py
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/contract.yaml
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/handler.py
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/runtime_no_io_outside_effects_check.py
  • src/omnibase_core/nodes/node_no_io_outside_effects_check_compute/visitor_io.py
  • src/omnibase_core/nodes/node_no_raw_sqlite3_check_compute/handler.py
  • src/omnibase_core/nodes/node_no_utcnow_check_compute/handler.py
  • tests/unit/nodes/node_no_io_outside_effects_check_compute/__init__.py
  • tests/unit/nodes/node_no_io_outside_effects_check_compute/test_node_no_io_outside_effects_check_compute.py
  • tests/unit/nodes/node_no_io_outside_effects_check_compute/test_runtime_no_io_outside_effects_check.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonahgabriel/omn-14694-no-db-in-orchestrator

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

…ype-purity gate

Reframe per OMN-14662 (operator decision 2026-07-16, "architectural purity
always"): the DB-only ORCHESTRATOR seed becomes the single archetype-purity
invariant `no-io-outside-effects` (validator_id `arch-no-io-outside-effects`).
EFFECT is the only I/O-permitted archetype; every .py module co-located with a
non-EFFECT contract (COMPUTE / REDUCER / ORCHESTRATOR) must be pure.

Rename + broaden (same COMPUTE, same def-B handle(request)->ModelValidationReport,
same paired EFFECT file-gather, canonical ModelValidationReport/Finding — no fork):
- node_no_db_in_orchestrator_check_compute -> node_no_io_outside_effects_check_compute
- archetype_resolver: contract_declares_orchestrator -> resolve_archetype() ->
  EnumNodeArchetype | None; seam generalized _orchestrator_dirs -> _non_effect_dirs
  (fail-closed: only a positively-declared EFFECT contract is exempt).
- visitor_db_io (DB imports only) -> visitor_io (IoSurfaceVisitor), FULL forbidden
  surface set: database (sqlite3/aiosqlite/psycopg/psycopg2/asyncpg/sqlalchemy),
  network/HTTP (httpx/requests/aiohttp/urllib3/socket/urllib.request), subprocess,
  git (git/pygit2 import OR subprocess argv[0]==git, ALL verbs), Linear (SDK import
  OR linear.app URL literal), filesystem WRITES (open write-mode, os/shutil mutators,
  pathlib.Path write methods), direct event-bus instantiation (KafkaProducer/AIOKafka*/
  confluent_kafka.*/*EventBus), direct infra-adapter instantiation (*Adapter).
  `# db-io-ok` -> `# io-ok:` suppression.

RED-against-exists-but-wrong per surface: the SAME I/O source is FLAGGED in a
non-EFFECT package and PASSES verbatim inside an EFFECT package (archetype
discriminator), plus clean non-EFFECT PASS. Reads, str.replace, urllib.parse are
correctly not flagged (false-positive traps closed). 138 unit tests pass.

Enforcement (rule #5): pre-commit hook check-no-io-outside-effects + standalone
blocking CI gate validator-no-io-outside-effects.yml (unit suite + green full-tree
src/ self-scan; same COMPUTE node so local and CI cannot drift). Blast-radius
measured before landing: broadened self-scan on omnibase_core/src is clean (0 hits).

Closes OMN-14694
@jonahgabriel jonahgabriel changed the title feat(OMN-14694): WS8 canary — no-db-in-orchestrator ValidatorNode COMPUTE feat(OMN-14694): broaden WS8 canary → no-io-outside-effects archetype-purity gate Jul 16, 2026
… docstring (AI-slop md_separator strict gate)
jonahgabriel added a commit to OmniNode-ai/onex_change_control that referenced this pull request Jul 16, 2026
* evidence(OMN-14694): author OCC companion for OmniNode-ai/omnibase_core#1449

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

* evidence(OMN-14694): self-bind OCC#4285 + rebind contract_sha256

* evidence(OMN-14694): repair core 1449 OCC companion

* evidence(OMN-14694): add deploy scope for core 1449

---------

Co-authored-by: codex-gpt-5 <codex@omninode.ai>
@jonahgabriel
jonahgabriel merged commit f311524 into dev Jul 16, 2026
164 of 166 checks passed
@jonahgabriel
jonahgabriel deleted the jonahgabriel/omn-14694-no-db-in-orchestrator branch July 16, 2026 17:07
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