Jerlshin's picture
premature code. analysis later
0b9860d
|
Raw
History Blame Contribute Delete
4.24 kB
# `engines/` β€” The Domain Services
Eleven physical modules, stateless and (with one exception) pure. Each engine takes a `CandidateRepresentation` plus typed configuration (or, for `semantic.py`, an injected port) and returns an enriched copy or a verdict. **Engines never call each other** β€” the dependency graph between them is a forest of data dependencies, not direct imports; only the pipeline threads the growing representation from one engine to the next. This package may import `domain/`, `ports/` (by injection), `features/`, and `config.schema` β€” never `adapters/`, `pipelines/`, `observability/` IO, or any other engine. See [`/ARCHITECTURE.md` Β§6](../../../ARCHITECTURE.md#6-the-engines) and [`docs/specs/REDSTACK_ENGINE_LAYER.md`](../../../docs/specs/REDSTACK_ENGINE_LAYER.md).
## File inventory
| File | Engine | Online stage | Reads | Produces | Pure? |
|---|---|---|---|---|---|
| [`integrity.py`](integrity.py) | `IntegrityEngine` | R4 | `CareerProfile`, raw record, calibrated thresholds, the `hp.*` feature cells | `IntegrityReport` (honeypot verdict) | Yes |
| [`eligibility.py`](eligibility.py) | `EligibilityEngine` | R4 | representation + `JobDescriptionSpec` + gate rules | `EligibilityReport` (hard blocks, soft penalties) | Yes |
| [`lexicon.py`](lexicon.py) | `LexiconEngine` | R2 | normalized tokens, descriptions, the compiled lexicon | competency/credibility support (lexical corroboration) | Yes |
| [`semantic.py`](semantic.py) | `SemanticEngine` | R3 | candidate id, the vector store, anchor vectors, archetype centroids | `SemanticProfile`, `ArchetypeAssignment` | Pure *given its ports* β€” the only engine that touches a port |
| [`cqv.py`](cqv.py) | `CQVAssembler` | R5 | the fully populated representation | `CandidateQualityVector` | Yes |
| [`behavioral.py`](behavioral.py) | `BehavioralEngine` | R2 | `BehavioralProfile` inputs | bounded behavioral multiplier | Yes |
| [`logistics.py`](logistics.py) | `LogisticsEngine` | R2 | `LogisticsProfile` inputs | bounded logistics multiplier | Yes |
| [`scoring.py`](scoring.py) | `ScoringEngine` | R5 | folded CQV, gate verdicts, multipliers, the locked weights | `ScoredCandidate` + `ScoreBreakdown` | Yes |
| [`ranking.py`](ranking.py) | `RankingEngine` | R6 | `ScoredCandidate[]` | `Ranking` (invariant-checked at construction) | Yes |
| [`reasoning.py`](reasoning.py) | `ReasoningEngine` | R7 | `RankedCandidate` + the re-hydrated top-K representation | `CandidateReasoning`, attached via `Ranking.with_reasoning` | Yes |
| [`validation.py`](validation.py) | `ValidationEngine` | R8/R9 (defense-in-depth) | a finished `Ranking` | `ValidationReport` | Yes |
## Why this is a forest, not a web
The pipeline (`pipelines/online/stages.py`) is the only thing that calls more than one engine. Each engine's signature only ever names domain types and ports β€” never another engine. This means any single engine can be unit-tested with nothing but domain fixtures (and, for `semantic.py`, a fake port) β€” no mocking framework needed anywhere in this package, because nothing here calls out to infrastructure directly.
## The gating contract
`IntegrityEngine` and `EligibilityEngine` run independently at R4 and are joined into a single floor mask before R5. A candidate that is a detected honeypot **or** ineligible has `final_score` forced to a fixed floor sentinel at scoring time β€” no partial penalty, no chance of slipping into the ranked top by a strong semantic match alone. `BehavioralEngine` and `LogisticsEngine` produce *multipliers* that modulate an already-computed relevance score; neither can be a source of relevance on its own β€” a behaviorally inactive but otherwise perfect-on-paper candidate is down-weighted, never disqualified outright.
## Performance
Every engine here operates on either a single representation (called per-candidate during reasoning, which only ever covers the top-100) or a vectorized columnar batch (`integrity`, `eligibility`, `cqv`, `behavioral`, `logistics`, `scoring`, `ranking` over the full pool) β€” there is no per-candidate Python object churn in the hot path. See [`/ARCHITECTURE.md` Β§5.2](../../../ARCHITECTURE.md#52-online-pipeline--r0-through-r9) for the per-stage compute budget.