Skip to content

feat: ternary partition routing for LatticeIndex - #49

Merged
discreteds merged 11 commits into
developfrom
feature/ternary-partition-routing
Jul 19, 2026
Merged

feat: ternary partition routing for LatticeIndex#49
discreteds merged 11 commits into
developfrom
feature/ternary-partition-routing

Conversation

@discreteds

Copy link
Copy Markdown
Member

Summary

Generalises LatticeIndex partition routing from exact dict lookup to ternary + specificity semantics, so a lattice suite can declare wildcard/default partitions and route missing-field contexts correctly. Built on a new MatchStrategy.EXACT_KEY evaluated by an embedded ExpressionRulesEngine over a meta rules-table — routing now reuses the exact same ternary machinery as the constraint layer, so the two cannot drift.

Spec: docs/superpowers/specs/2026-07-19-ternary-partition-routing-design.md · Plan: docs/superpowers/plans/2026-07-19-ternary-partition-routing.md

What changed

  • MatchStrategy.EXACT_KEY (core/constants.py, core/compiler.py) — rule-side-wildcard-only exact match: rule UNKNOWN sentinel → 0, rule == context → 1, context-side sentinel/UNKNOWN/null vs a specific key → −1 (the asymmetry vs stock EXACT, which scores 0). Bool: rule null is the wildcard.
  • Missing/null/NaN context keys (accumulator/engine.py) — _extract_partition_key fills the typed NOT_SET sentinel (None for bool) instead of raising; _normalize_partition_key treats None and float NaN as missing (spec §1: backend null/NaN ≡ absent).
  • Ternary routing (accumulator/lattice.py) — exact dict hit keeps the O(1) fast path; on a miss _route runs the meta-engine (unique top-specificity winner; 0 survivors → KeyError "No lattice…"; tie → AmbiguousPartitionError, a KeyError subclass so the service's partition-miss→422 handler is unchanged). Structural checks at construction: empty / duplicate / NOT_SET-bearing / keyless → ValueError.
  • Batch routingapply_batch normalises key columns up front (absent columns filled; null/NaN coalesced to the typed sentinel; bool keeps null) so it routes identically to single apply, with no row silently dropped or double-counted.
  • Load-time ambiguity validationindex(lattices, validate=True, max_witnesses=1_000_000) runs an exhaustive witness-matrix check (equivalence classes = specific values + one OTHER per dim), chunked at 100k, ValueError on cap overflow (no silent sampling). apply_auto uses validate=False so the matrix isn't rerun per call.
  • Persistence round-trip tests (str/int/bool wildcard sentinels survive Lattice.save/load) and CLAUDE.md docs.

Testing

804 passed, 36 skipped, 31 pre-registered xfailed · ruff clean · mypy unchanged (94, none new) · backend purity enforced (no new # allow: tag — count stays at three).

Review trail

Executed via subagent-driven development: per-task spec+quality review on every task, an Opus whole-branch review, and an independent Codex adversarial post-implementation review. Real defects found and fixed before this PR:

  • Opus review: sorted(self._map) raised TypeError on a bool-keyed partition miss, masking the KeyError and breaking the KeyError→422 contract (→ key=repr).
  • Codex review: apply_auto reran the full witness matrix every call; float NaN keys weren't normalised; apply_batch errored on an absent key column where single apply tolerates it. (A fourth finding — bool NOT_SET structural skip — was adjudicated as a non-issue: bool has no NOT_SET sentinel.)

🤖 Generated with Claude Code

discreteds and others added 11 commits July 19, 2026 18:44
…ementation plan

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…c coverage

- sorted(self._map, key=repr) so a bool wildcard (None) in served keys can't
  raise TypeError and mask the KeyError (breaks the KeyError->422 contract)
- persistence round-trip tests for numeric + bool wildcard sentinels
- document bool EXACT_KEY string-coalesce reliance
- _normalize_partition_key treats float NaN as missing (spec: null/NaN == absent)
- apply_batch normalises key columns up front: absent columns filled, null/NaN
  coalesced to typed NOT_SET (bool keeps null); routing now mirrors single apply
  and no missing/NaN row is silently dropped
- apply_auto uses validate=False so the witness matrix isn't rerun per call
Closes the final-review coverage gap on the provided-id branch (Codex-fix
review). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

@discreteds
discreteds merged commit dd1a939 into develop Jul 19, 2026
5 of 6 checks passed
@discreteds
discreteds deleted the feature/ternary-partition-routing branch July 19, 2026 10:56
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