chore(absence): serialization hardening, renderer DRY, hygiene#407
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 hardeningFORMAT_VERSIONconstant +load()validation: a sidecar with an unknown/changed JSON shape now raisesVocabIndexStale(→ rebuild) instead of being misread.format_versionwas written but never checked.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._name_indexfrom the sidecar: derivable from records, rebuilt in__init__on load (single source of truth, no bloat). Backward-compatible — old sidecars withname_indexload fine (field ignored).except (VocabIndexStale, FileNotFoundError, Exception)tuple (Exceptionsubsumes the others).jrag_render.py— DRY + message rendering_ABSENCE_VERDICT_TEXT+_verdict_line()— the verdict→label mapping was triplicated across not-found / listing / traversal empty.absence.messagein the not-found block (the authored per-cause help was being dropped on the CLI surface).elsebranches (verdict is a closed Literal).absence_diagnosis.py— correct the_threshold_verdictdocstring (onlyabsence_absent_floordecides;close_thresholdis 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 regeneratedbuilt_at. Rebuilt on demand.Deliberately NOT done (would not improve correctness)
SymbolRecord.resolveddefault: leaving it required is safer (explicit > implicit);_row_to_symbol_recordalready defaults missing→True.🤖 Generated with Claude Code