0.7.1 — unreleased
0.7.x stabilization — diff-maps robustness + layout consumers + ISSUE-2.
Added
- Same-file-only tier (ISSUE-2) —
cook --allow-non-uniquenow stamps recipes with non-unique anchors asmetadata.portability = "same_file_only".tunerefuses to apply such a recipe to any binary whose sha256 differs from the source (ecu.sha256), unless the new--forceflag is passed (loud warning; Phase 1/2/3 mechanical checks still run and can still abort).validate beforereports the mismatch (same_file_onlyblock;safe_to_patchforced false). Unblocks ~25% of real tunes whose edits sit in non-unique regions, without weakening the portability promise: strict default unchanged, the exception is machine-enforced. diff-mapsnear-match pre-index —_near_match_passindexes remaining stock tables by shape, turning the worst-case O(unmatched × remaining) into O(unmatched × same-shape candidates) — a tune that rescales many axes no longer blows up quadratically (audit follow-up item 3).cook/cook-volatileregion tags — every recipe instruction now carries aregionfield (calibration / code / erased / mixed / unknown) from the flash-layout segmenter; edits outside a calibration region get aCODE_AREAflag and a prominent portability warning ("may not apply to other revisions of this ECU"). Advisory only: never filters, never blocks,tuneignores the tags. No calibration signal →unknown, nothing flagged. The layout scan is shared with--annotate-maps(one scan for both map annotation and region tags) — default cook adds ~0.2 s on a 4 MB pair;--no-annotate-mapsadds the full scan (~2.5–3 s).scan-maps/diff-mapscalibration-region default — both commands now scan the detected calibration region by default instead of the whole file: junk tables from code / erased sectors are hidden and counted (layout_filtered/tables_hiddenin JSON, a note in human output).--whole-filerestores the full scan;--regionoverrides; no calibration signal falls back to whole-file behaviour automatically. A wrong layout estimate can only change what the report shows — never recipe or patch output.diff-mapscorrelation near-match — tables whose axis breakpoints changed between stock and tuned are now paired up instead of silently dropping into the only-in-* lists: same shape + close axes (edited breakpoints, within ~15% of the axis range) + strongly correlating cell grids (Pearsonr ≥ 0.95) → reported as a match flagged↺ axes changed, with the old/new axis values in JSON (axis_stock/axis_tuned).- Correlation on every match — each match now carries a
correlationvalue in JSON and drives a refined⚠ suspiciousflag: near-total cell change is suspicious only when the grids do NOT correlate (lowr= two different maps sharing axes); a heavily retuned map (all cells changed,r ≈ 1.0) is recognised as a legitimate retune. - "Changed but not identified" report — changed byte regions no matched
table covers and that are not table-shaped are listed explicitly (human
section +
unidentified_changed_count/unidentified_changedin JSON + Markdown export section). Every changed byte in the binary is now accounted for: matched map, promoted table, or listed here.
Changed
attach_maps()/tag_instruction_regions()accept a precomputed table scan;cook/cook-volatileshare one stock scan between map annotation and region tags instead of scanning twice (default cook on a 4 MB pair: 8.05 s → 5.70 s).
Fixed
diff-mapsno longer silently misses an entire rewritten map when the tuner re-scaled its axis breakpoints (previously documented as "intentional" — now reported as an axis-changed near-match).diff-mapsstrided near-match mis-diff — compound (interleaved) tables with rescaled axes were diffed with contiguous cell reads, mixing the two halves (audit 2026-08-24:0x23C0A8reported 25/25 changed vs correct 20/25). The near-match shape guard now comparesstrideand strided tables are read with their stride, mirroring the exact-match path.diff-maps"changed but not identified" is now per-byte: blocks straddling a matched table's edge report their uncovered sub-ranges (previously dropped by any-overlap); matched spans carry the ±4 pad alignment slack so a table's own alignment drift never produces false unidentified tails.