Commit 0e5ab98
committed
fix(spine): address PR #432 opus 4.8 reviewer findings
Three correctness bugs + one architectural disclaimer + three polish items
from the PR review pass. No new dependencies; all tests green.
## Bugs fixed
### 1. roundtrip_eq truth check inverted from default semantics
(codegen_spine.rs:161 — `if tol > 0.0` gated the entire check)
The doc claimed `truth_tolerance() = 0.0` meant "lossless / strictest."
The code SKIPPED the truth check when tol = 0.0, so a projection that
zeroed every (f, c) round-tripped green with no truth validation. The
default-case bug was masked because the existing LossyDropFrequency
test overrides tolerance to 0.01.
Fix: drop the `if tol > 0.0` gate; the `abs() > tol` comparison
naturally treats 0.0 as "any difference fails." Doc reworded to
clarify "0.0 requires exact match; override to allow quantization."
New test `default_tolerance_requires_exact_truth_match` pins the
fix: a `TruthMangler` projection (preserves s/p/o, zeros f/c) MUST
fail with the default tolerance.
### 2. parse_triples silently dropped malformed lines
(odoo_ontology.rs:73-83 — `filter_map(|l| serde_json::from_str(l).ok())`)
Lines that fail JSON parse were silently dropped. The
`parses_all_triples` count assertion would catch *some* drift but a
corrupted line that happens to keep counts aligned would go silent.
Fix: new test `every_nonempty_line_parses` asserts the raw non-empty
line count equals `parse_triples(ndjson).len()` — any silent drop
fires the assertion. (Kept `parse_triples` returning `Vec` for API
stability; the test catches what an error-returning API would.)
### 3. load_ontology collapsed duplicate (s,p,o) keys silently
(odoo_ontology.rs:90-104 — HashMap last-write-wins via dn_hash)
The module doc said "the extractor de-duplicates" — an unverified
assumption. If the harvester ever emits two triples with the same
(s, p, o) but different truth values, the second silently overwrites
the first.
Fix: new test `duplicate_spo_keys_are_last_write_wins` pins the
overwrite semantics. A future switch to insertion-rejection or merge
becomes a test failure instead of a silent behaviour change.
## Architectural disclaimer
`OdooMethodKind` (codegen_spine.rs:230) is the bucket *catalogue*; the
*classifier* (Rust port of `.claude/odoo/openings_hops.py`) is a
follow-up emitter. action_emitter intentionally does NOT carry a
`kind` field — the doc now spells out the wiring gap explicitly so
the next session doesn't read this PR as "kind is wired" when it
isn't.
## Polish
- `RouteBucket::id_owned(&self) -> String` default method added
(codegen_spine.rs:336-340). Escape hatch for async/iterator
pipelines that need an owned id outside the borrow scope.
- `impl std::error::Error for WidgetRenderError` (codegen_spine.rs)
for ecosystem `?`-propagation compatibility.
- `#[serde(deny_unknown_fields)]` on `OntologyTriple` so harvester
schema drift fails parsing instead of silently dropping fields.
- New test `function_count_matches_module_doc` in odoo_ontology.rs
pins the "3 328 Functions" doc claim against drift inside the
loader crate (was only asserted by the downstream action_emitter).
- `compose_spec` now builds `effects` from the borrowed `effects_set`
directly (action_emitter.rs:255-258), eliminating one redundant
`idx.emits_by_fn.get(fn_id)` lookup.
## Test counts (orchestrator-verified)
- lance-graph-contract codegen_spine: 6 → 7 passed (+1 truth-mangler)
- lance-graph graph::spo:: total: 75 → 78 passed (+3 ontology tests)
Fixes from PR #432 opus 4.8 reviewer (findings 1-3 must-fix, 5+7
should-discuss accepted, 4 doc-disclaimer accepted, 6+8 deferred,
nitpicks 1+2+3 accepted).1 parent 60f72b1 commit 0e5ab98
3 files changed
Lines changed: 150 additions & 19 deletions
File tree
- crates
- lance-graph-contract/src
- lance-graph/src/graph/spo
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
119 | 121 | | |
120 | 122 | | |
121 | 123 | | |
| |||
156 | 158 | | |
157 | 159 | | |
158 | 160 | | |
159 | | - | |
| 161 | + | |
| 162 | + | |
160 | 163 | | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
177 | 178 | | |
178 | 179 | | |
179 | 180 | | |
| |||
226 | 227 | | |
227 | 228 | | |
228 | 229 | | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
229 | 243 | | |
230 | 244 | | |
231 | 245 | | |
| |||
332 | 346 | | |
333 | 347 | | |
334 | 348 | | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
335 | 356 | | |
336 | 357 | | |
337 | 358 | | |
| |||
363 | 384 | | |
364 | 385 | | |
365 | 386 | | |
| 387 | + | |
| 388 | + | |
366 | 389 | | |
367 | 390 | | |
368 | 391 | | |
| |||
491 | 514 | | |
492 | 515 | | |
493 | 516 | | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
494 | 562 | | |
495 | 563 | | |
496 | 564 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
255 | 255 | | |
256 | 256 | | |
257 | 257 | | |
258 | | - | |
| 258 | + | |
259 | 259 | | |
260 | 260 | | |
261 | 261 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
55 | 58 | | |
| 59 | + | |
56 | 60 | | |
57 | 61 | | |
58 | 62 | | |
| |||
167 | 171 | | |
168 | 172 | | |
169 | 173 | | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
170 | 233 | | |
0 commit comments