Skip to content

Commit 3f293d9

Browse files
Lum1104claude
andcommitted
fix(update): type-guard the guidance-hints ledger against corrupted state
A hand-edited ~/.rgit/update-check.json with a non-list guidance_hints made mark_hint_shown raise AttributeError past installer's (OSError, UnicodeDecodeError) guard, breaking the module's never-raises contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 771bdbe commit 3f293d9

2 files changed

Lines changed: 19 additions & 2 deletions

File tree

src/rgit/updatecheck.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,21 @@ def maybe_start_background_check(now: float) -> None:
130130
threading.Thread(target=_fetch_once, args=(now,), daemon=True).start()
131131

132132

133+
def _hints(state: dict) -> list:
134+
# Type-guard like every other reader here: a hand-edited or drifted state
135+
# file must degrade to "no hints shown yet", never raise.
136+
hints = state.get("guidance_hints")
137+
return hints if isinstance(hints, list) else []
138+
139+
133140
def hint_pending(path: str) -> bool:
134-
return path not in load_state().get("guidance_hints", [])
141+
return path not in _hints(load_state())
135142

136143

137144
def mark_hint_shown(path: str) -> None:
138145
state = load_state()
139-
hints = state.setdefault("guidance_hints", [])
146+
hints = _hints(state)
140147
if path not in hints:
141148
hints.append(path)
149+
state["guidance_hints"] = hints
142150
save_state(state)

tests/test_updatecheck.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,12 @@ def test_hint_ledger(monkeypatch, tmp_path):
172172
updatecheck.mark_hint_shown("/x/AGENTS.md")
173173
assert updatecheck.hint_pending("/x/AGENTS.md") is False
174174
assert updatecheck.hint_pending("/y/CLAUDE.md") is True
175+
176+
177+
def test_hint_ledger_tolerates_corrupt_guidance_hints(monkeypatch, tmp_path):
178+
_use_tmp_state(monkeypatch, tmp_path)
179+
updatecheck.save_state({"guidance_hints": "corrupt"})
180+
assert updatecheck.hint_pending("/x/AGENTS.md") is True
181+
updatecheck.mark_hint_shown("/x/AGENTS.md") # must not raise
182+
assert updatecheck.hint_pending("/x/AGENTS.md") is False
183+
assert updatecheck.load_state()["guidance_hints"] == ["/x/AGENTS.md"]

0 commit comments

Comments
 (0)