Skip to content

chore(absence): serialization hardening, renderer DRY, hygiene#407

Merged
HumanBean17 merged 1 commit into
masterfrom
chore/absence-followups
Jul 8, 2026
Merged

chore(absence): serialization hardening, renderer DRY, hygiene#407
HumanBean17 merged 1 commit into
masterfrom
chore/absence-followups

Conversation

@HumanBean17

Copy link
Copy Markdown
Owner

Applies the deferred follow-up backlog from the absence-diagnosis review. No change to the diagnosis logic itself — full suite green (1261 passed).

Changes

absence_vocab.py — serialization hardening

  • FORMAT_VERSION constant + load() validation: a sidecar with an unknown/changed JSON shape now raises VocabIndexStale (→ rebuild) instead of being misread. format_version was written but never checked.
  • Atomic save(): dump to a temp sibling + os.replace, so a crash mid-write leaves the previous complete file or the new one — never a truncated sidecar. Explicit utf-8 / ensure_ascii=False.
  • Drop _name_index from the sidecar: derivable from records, rebuilt in __init__ on load (single source of truth, no bloat). Backward-compatible — old sidecars with name_index load fine (field ignored).
  • Collapse the redundant except (VocabIndexStale, FileNotFoundError, Exception) tuple (Exception subsumes the others).

jrag_render.py — DRY + message rendering

  • Extract _ABSENCE_VERDICT_TEXT + _verdict_line() — the verdict→label mapping was triplicated across not-found / listing / traversal empty.
  • Render absence.message in the not-found block (the authored per-cause help was being dropped on the CLI surface).
  • Remove unreachable else branches (verdict is a closed Literal).

absence_diagnosis.py — correct the _threshold_verdict docstring (only absence_absent_floor decides; close_threshold is transparency-only here, decides the find path).

Hygiene — stop tracking the generated vocab_index.json (+ its atomic-write .tmp); it dirtied every tree on a test/build run via a regenerated built_at. Rebuilt on demand.

Deliberately NOT done (would not improve correctness)

  • Live-graph version compare: comparing the sidecar to the live graph's ontology version (instead of the code constant) would weaken staleness detection — it could accept an index built under an older ontology. The code-constant compare is the safer, correct choice for schema incompatibility.
  • SymbolRecord.resolved default: leaving it required is safer (explicit > implicit); _row_to_symbol_record already defaults missing→True.

🤖 Generated with Claude Code

…ygiene

Applies the deferred follow-up backlog from the absence-diagnosis review.
No change to the diagnosis logic itself; full suite green (1261 passed).

absence_vocab.py
- FORMAT_VERSION constant + load() validation: a sidecar with an unknown/
  changed JSON shape now raises VocabIndexStale (-> rebuild) instead of being
  misread. format_version was written but never checked.
- Atomic save(): dump to a temp sibling + os.replace, so a crash mid-write
  leaves the previous complete file or the new one -- never a truncated sidecar.
  Explicit utf-8 / ensure_ascii=False.
- Drop _name_index from the sidecar: it is derivable from records and is
  rebuilt in __init__ on load (single source of truth, no bloat). Backward
  compatible (old sidecars with name_index load fine; the field is ignored).
- Collapse the redundant except-tuple in get_vocabulary_index (Exception
  subsumes VocabIndexStale/FileNotFoundError).

jrag_render.py
- Extract _ABSENCE_VERDICT_TEXT + _verdict_line() to DRY the verdict->label
  mapping that was triplicated across not-found / listing / traversal empty.
- Render absence.message in the not-found block (the authored per-cause help
  was being dropped on the CLI surface).
- Remove unreachable else branches (verdict is a closed Literal).

absence_diagnosis.py
- Correct the _threshold_verdict docstring: only absence_absent_floor decides;
  absence_close_threshold is transparency-only on this path (it decides the
  find path). The old "two-band" framing implied otherwise.

Hygiene
- Stop tracking the generated vocab_index.json (it dirtied every tree on a
  test/build run via a regenerated built_at). gitignore'd + untracked; the file
  is rebuilt on demand.

Deliberately NOT done (would not improve correctness)
- Compare sidecar ontology_version to the live graph version vs the code
  constant: the code-constant compare is the safer/correct choice for schema
  incompatibility; the live-graph variant could accept an index built under an
  older ontology.
- Add a default to SymbolRecord.resolved: leaving it required is safer
  (explicit > implicit); _row_to_symbol_record already defaults missing->True.

Co-Authored-By: Claude <noreply@anthropic.com>
@HumanBean17 HumanBean17 merged commit 0aef83b into master Jul 8, 2026
4 checks passed
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