fix(inference): remove ghost bridge and unowned KB rule loading - #232
Merged
Conversation
engine/inference_bridge.py was a tombstone that raised ImportError while directing callers to engine.inference_bridge_v2.DerivationGraph and docs/migration/inference_bridge_v2.md. Neither exists in this repository, so the module advertised a successor protocol that was never implemented. Reverse-import verification at this base found no live consumer: the only references were the module's own text and a stale comment in engine/startup_wiring.py. The tombstone is deleted rather than replaced — no successor bridge is introduced for compatibility alone. Task: CEG-001 Claude-Session: https://claude.ai/code/session_01Fc1ayR9FNiXRQ22HxMSRsh
engine/startup_wiring.py attempted `load_domain_rules(spec.kb)` for every domain, but DomainSpec does not declare a `kb` field and the production GraphLifecycle boot path never invokes apply_all_gap_fixes(). The path was dead and, had it run, would have raised AttributeError. Removes the dead recipe block, the raw-dictionary rule loader (load_domain_rules / _register_condition_rule), and the stale bridge comment. The typed DomainSpec / DomainPackLoader boundary stays the single owner of domain configuration; no second rule-configuration surface and no `kb` field are added. All built-in @register_inference_rule functions and the execute_rule() registry boundary are preserved unchanged. InferenceContext.domain_kb is retained as optional caller-supplied tuning context — infer_material_grade_from_mfi still reads it — but it is no longer documented as populated by domain-spec injection. Task: CEG-002 Claude-Session: https://claude.ai/code/session_01Fc1ayR9FNiXRQ22HxMSRsh
Adds tests/gap_fixes/test_gap9_inference_authority.py alongside the existing gap-fix test owners. It asserts that the bridge module stays deleted, that the startup recipe does not reintroduce spec.kb / load_domain_rules, that the registry exposes no raw-KB or n-ary symbols, that no engine/ source references the nonexistent v2 successor or its migration guide, and that execute_rule() still returns the canonical InferenceResult for a registered built-in rule. Task: CEG-003 (regression portion) Claude-Session: https://claude.ai/code/session_01Fc1ayR9FNiXRQ22HxMSRsh
|
✅ PR reviewable size is within recommended limits |
L9 Audit Harness Report
Step Results
Architecture Audit Findings
See Spec Coverage
See Next StepsAll checks passed. Safe to merge. |
github-code-quality flagged tests/gap_fixes/test_gap9_inference_authority.py for importing engine.inference_rule_registry with both `import ... as` and `from ... import ...`. Keeps the module alias only, and reaches InferenceContext, InferenceResult and execute_rule through it. The module-surface hasattr() assertions stay exactly as they were; no test behaviour changes. Claude-Session: https://claude.ai/code/session_01Fc1ayR9FNiXRQ22HxMSRsh
|
cryptoxdog
pushed a commit
that referenced
this pull request
Aug 23, 2026
Evidence-only repair of four factual defects in the audit record. The seven-module cleanup, its classifications, and all runtime code are unchanged. 1. Predecessor attribution. The record identified the inference-ownership closure contract as having merged as PR #232. False: PR #232 is "fix(inference): remove ghost bridge and unowned KB rule loading" (merge commit 5868bc4, this PR's base). It deliberately RETAINED engine/inference_rule_registry.py and explicitly recorded that the module has no verified production edge. The ownership-closure contract is a separate, unexecuted program. All "predecessor" wording now names PR #232 and its actual scope. 2. Inference registry classification. HISTORICAL_REFERENCE was wrong — the module is executable, current, and reachable only from tests/gap_fixes/test_gap3_inference_registry.py and test_gap9. Reclassified TEST_ONLY_IMPLEMENTATION (CONFIRMED, runtime_callers: [], production_reachability: NONE_VERIFIED). KEEP stands, restated as what it is: a scope decision deferring inference ownership, not a canonicality claim. 3. GateRegistry mechanics. The record said all_gates.py holds "decorator-registered gate classes". There is no decorator registration anywhere in engine/gates/ — GateRegistry._REGISTRY is a static dictionary mapping GateType values to classes imported from all_gates.py. 4. Gate finding upgraded from speculation to GATE-001. "May be a real defect because GateCompiler bypasses it" understated the evidence. Recorded facts: GateCompiler is the production-reachable compiler with its own per-GateType handlers and composite recursion (_compile_composite); GateRegistry + all_gates form a production-unreachable ALTERNATE implementation surface in which CompositeGate recurses via GateRegistry.get_gate_class; tests (test_boot_and_registry.py::TestGateRegistry) and the active gate-development skill both maintain that alternate surface. Whether it carries semantics that must be preserved before consolidation is UNKNOWN — deferred to a dedicated gate-by-gate parity audit. No conclusion (wire it / delete it / keep both) is authorized by this record, and engine/gates/** is untouched. DEF-001's full-tree reachability-gate deferral, the 59-module UNKNOWN classification, the no-large-baseline decision, and every deletion conclusion are preserved verbatim.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Problem
engine/inference_bridge.pywas a tombstone module that raisedImportErroronimport while directing every caller to
engine.inference_bridge_v2.DerivationGraphand
docs/migration/inference_bridge_v2.md. Neither exists in this repository —verified at base
e155f873: noengine/inference_bridge_v2.py, nodocs/migration/directory at all. The module advertised a successor protocol that was never built.
Separately,
engine/startup_wiring.pyexecutedload_domain_rules(spec.kb)for everydomain, but
DomainSpec(engine/config/schema.py) declares nokbfield. Had thatrecipe ever run it would have raised
AttributeError.Root cause
A historical gap-fix bundle left authoritative-looking compatibility and raw-KB
integration artifacts behind. Neither was ever incorporated into the canonical
GraphLifecycle/DomainPackLoaderruntime, so both survived as false authorityrather than as working code.
Fix
spec.kb/load_domain_rulesrecipe block and the stale bridge commentload_domain_rules,_register_condition_rule)All built-in
@register_inference_rulefunctions and theexecute_rule()registryboundary are preserved unchanged.
InferenceContext.domain_kbis retained asoptional caller-supplied tuning context (
infer_material_grade_from_mfistill readsit); only the claim that a domain spec injects it is removed.
Architecture
DomainSpec+DomainPackLoaderremain the single typed owner of domainconfiguration.
engine.inference_rule_registry.InferenceResultremains the supportedregistry result contract. No successor bridge,
NaryFactschema, YAML-to-fact adapter,generic result type, or parallel inference engine is introduced — this PR only removes
dead code and false authority.
Verification performed on this branch
Reverse-import trace at base
e155f873:engine.inference_bridge— no live consumer. Only self-references plus a stalecomment in
engine/startup_wiring.pyand a generatedartifacts/audit_report.mdentry.load_domain_rules— referenced only byengine/startup_wiring.py, which itself hasno caller anywhere in the tree (it is a documented "recipe" file, not a runtime entrypoint).
engine/inference_rule_registryis imported only bytests/gap_fixes/; it is notexported from
engine/__init__.pyand defines no__all__. No public API surface changes.docs/orcontracts/file referencesload_domain_rulesorinference_bridge.Post-change exact-symbol scan: no
inference_bridge,inference_bridge_v2,docs/migration/inference_bridge_v2.md,spec.kb,load_domain_rules,DerivationGraph,NaryFact,to_rule_engine_format, orload_kb_factsremainsoutside the new regression test that asserts their absence.
Commands run locally (Python 3.13 poetry env):
make agent-check-unit— passed (action refs, contract wiring, contract scanner,payload compiler,
ruff check+ruff format --check,mypy engine/, unit tests,contract coverage, audit harness "HARNESS PASSED"). Also run green on unmodified
mainfirst to establish the baseline.PYTHONPATH=. pytest tests/gap_fixes/test_gap3_inference_registry.py tests/gap_fixes/test_gap9_inference_authority.py— 11 passed
PYTHONPATH=. pytest tests/ --ignore=tests/e2e --ignore=tests/integration --ignore=tests/performance— 1914 passed, 14 skipped, 56 xfailed, 0 failed
Not verified locally
tests/integration/andtests/performance/could not run in this container: no Dockersocket is available, so the
testcontainers-neo4j fixture errors at setup(
FileNotFoundErroron the docker socket). This is environmental and pre-existing —those suites error identically on unmodified
main, and none of them import the modulestouched here. CI is the authority for them.
Known limitation (deliberately not fixed here)
There is no verified production edge from
DomainPackLoader/DomainSpecintoengine.inference_rule_registry.engine/startup_wiring.pyremains a recipe file withno caller, and the registry remains reachable only from tests. This PR does not invent
that integration. If domain-configured inference is wanted, it needs a separate program
that first establishes the producer, the consumer, the typed configuration contract, and
the runtime owner — not a
kbfield bolted ontoDomainSpec.Risk
Low. The change deletes dead code and a module that could only ever raise on import.
The one residual risk is an unindexed external consumer importing
engine.inference_bridge— such a consumer already fails at import on currentmain.Rollback
Revert the PR if a real consumer surfaces. Do not restore the ghost v2 target; re-plan
against the actual consumer contract.
Files changed
engine/inference_bridge.pyengine/inference_rule_registry.pyengine/startup_wiring.pytests/gap_fixes/test_gap9_inference_authority.py4 files changed, 60 insertions(+), 127 deletions(-)
Generated by Claude Code