Step 10j (host + extension): cache contract three-state UX
Completes the two-tier cache contract from step 9 / docs/CACHE_CONTRACT.md
on the extension side. The Python side shipped in the Python repo at
33c495a.
Host (rcjav-host.py):
- fetch_rules_info() memoizes per-script-path calls to
`rc-jav.py --print-rules-info` so handle_cache_status doesn't pay
the Python startup cost on every poll.
- _cache_freshness_fields(data, rules_info) computes the new
cache_schema / id_rules / id_rules_signature trio + their three
*_match booleans + cache_state ('fresh' / 'stale_by_rules' /
'schema_mismatch' / 'missing'). Legacy version:3 caches still on
disk report as stale_by_rules with cache_schema_match=True (we'll
migrate them at next load_cache).
- New handle_reextract_ids() action forwards to
`rc-jav.py --reextract --format json` with a 5-minute timeout.
background.js:
- New `reextract-ids` message forwards to host with a 300s timeout.
options-cache.js + options-library-issues.js:
- renderCacheContractBanner() paints a three-state banner above the
per-remote list: green ✓ fresh / amber ! stale-by-rules (with
"Re-extract IDs (fast, no rescan)" chip button) / red ✗ schema
mismatch. Includes a snippet of the cache signature for diagnostics.
- Delegated click handler in options-library-issues.js catches
.cache-reextract, sends the message, shows transient
"Re-extracting…" state, and replaces the button with a per-summary
line ("Re-extracted N IDs · X changed · Y unchanged · Z dropped").
- rules_info_error from the host surfaces as its own amber line above
the banner.
node --check passes on background.js, options-cache.js,
options-library-issues.js individually and on the concatenation of all
four script files. python -m py_compile passes on rcjav-host.py.
Behavioral verification requires reloading the unpacked extension and
running through:
- Check Cache → banner shows "stale by rules" amber (legacy v3 cache)
- Click "Re-extract IDs" → fast path runs, summary appears
- Check Cache again → banner now shows "Cache up to date" green
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -415,6 +415,38 @@ document.getElementById("library-issues-modal").addEventListener("click", (e) =>
|
||||
showSkipped.closest("div")?.after(panel);
|
||||
return;
|
||||
}
|
||||
const reextract = event.target.closest(".cache-reextract");
|
||||
if (reextract) {
|
||||
const original = reextract.textContent;
|
||||
reextract.disabled = true;
|
||||
reextract.textContent = "Re-extracting…";
|
||||
(async () => {
|
||||
try {
|
||||
const r = await chrome.runtime.sendMessage({ type: "reextract-ids" });
|
||||
if (!r || !r.ok) {
|
||||
reextract.textContent = original;
|
||||
reextract.disabled = false;
|
||||
const note = document.createElement("div");
|
||||
note.style.cssText = "color:#faa;margin-top:6px;font-size:11px;";
|
||||
note.textContent = `Re-extract failed: ${r?.error || "no response"}`;
|
||||
reextract.after(note);
|
||||
return;
|
||||
}
|
||||
const note = document.createElement("div");
|
||||
note.style.cssText = "color:#afa;margin-top:6px;font-size:11px;";
|
||||
note.textContent = `Re-extracted ${r.total ?? 0} IDs · ${r.changed ?? 0} changed · ${r.unchanged ?? 0} unchanged · ${r.dropped ?? 0} dropped. Re-run Check Cache to refresh this view.`;
|
||||
reextract.replaceWith(note);
|
||||
} catch (err) {
|
||||
reextract.textContent = original;
|
||||
reextract.disabled = false;
|
||||
const note = document.createElement("div");
|
||||
note.style.cssText = "color:#faa;margin-top:6px;font-size:11px;";
|
||||
note.textContent = `Re-extract failed: ${err?.message || String(err)}`;
|
||||
reextract.after(note);
|
||||
}
|
||||
})();
|
||||
return;
|
||||
}
|
||||
const refresh = event.target.closest(".cache-refresh-remote");
|
||||
if (refresh) {
|
||||
const remote = refresh.dataset.remote || "";
|
||||
|
||||
Reference in New Issue
Block a user