Keep filtered lists fresh; derive observed status per sky object#528
Open
brickbots wants to merge 4 commits into
Open
Keep filtered lists fresh; derive observed status per sky object#528brickbots wants to merge 4 commits into
brickbots wants to merge 4 commits into
Conversation
…e sky rotates Two kinds of object state change under an unchanged filter and were never picked up by the filter cache until a parameter changed: - Logging an observation: Catalogs.mark_logged(obj) now sets obj.logged and bumps dirty_time when an observed criterion is active, so an "Observed: No" list drops the object on its next refresh (and a "Yes" list gains it). With observed == "Any" no verdict can change, so the cached lists survive. Logged status stays per catalog listing, matching check_logged's (catalog_code, sequence) keying. - Altitude drift: with an altitude criterion active, verdicts age out as the sky rotates (<= 15 deg/hour). CatalogFilter.is_stale() reports staleness (TTL 600s, bounding drift to ~2.5 deg) and also fires once when an alt/az fix arrives after verdicts were computed without one — closing the boot-time gap where everything "passed" the skipped altitude test forever. Catalogs.filter_catalogs() promotes staleness to a dirty bump so both cache layers re-evaluate; is_dirty() surfaces it to the screen-activation refresh path, and UIObjectList.update() polls it so a list screen left open refreshes in place. Without an altitude criterion is_stale() short-circuits, preserving the O(catalogs) list-open fast path from #526. Freshness policy rationale in docs/adr/0020; glossary updated (docs/ax/catalog/CONTEXT.md: Dirty time, Stale). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sting Log entries stay recorded per (catalog, sequence), but observed status now keys on object_id for DB-backed objects: the observed cache maps each logged listing to its object id at load, check_logged tests id membership, and Catalogs.mark_logged propagates to sibling composites in-session. Logging M 31 marks NGC 224 observed — durably across restarts and retroactively for historical logs. Virtual objects (negative, session-minted object_ids) keep the per-listing test: id-keyed status would cross-mark the shared -1 default or vanish on reboot. Supersedes ADR 0020's per-listing decision (amended in place — unpublished). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ails get_logs_for_object resolves a DB-backed object's sibling listings and returns log entries recorded under any of them, so NGC 224's details show M 31's logs instead of "Not Logged" while the row carries an observed checkmark. Virtual objects keep the per-listing query. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
refresh_object_list() re-sorts and reset the cursor to the top, so logging an object (or the altitude-staleness refresh on a left-open list) dumped the user back at the start of the list. Now the cursor re-locates the previously selected object; if it was filtered out, it falls to the first surviving old successor — the natural next target — clamping as a last resort. The NEAREST auto re-sort follows the same rule, so the selection tracks the object through the distance ranking. Matching is by (catalog_code, sequence): CompositeObject.__eq__ compares object_id alone and would land the cursor on a sibling listing (M 31 == NGC 224). Co-Authored-By: Claude Fable 5 <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.
Summary
Follow-up to #526: the filter cache keys all reuse on
dirty_time, which only advances when a filter parameter changes — but object state changes under an unchanged filter too. This PR keeps filtered lists correct in those cases, and makes observed status behave as a property of the sky object rather than of the catalog listing.Four commits, one concern each:
fix(catalogs): keep filtered lists fresh as objects are logged and the sky rotates
Catalogs.mark_logged), so an "Observed: No" list drops it on its next refresh.CatalogFilter.is_stale(), TTL 600 s ≈ 2.5° of sky drift, inside the 10°-step filter granularity), and the arrival of an alt/az fix triggers one refilter — closing the boot-time gap where pre-lock verdicts skipped the altitude test and everything "passed" forever. Staleness is promoted to a dirty bump infilter_catalogs()so both cache layers re-evaluate, andUIObjectList.update()polls it so a list screen left open refreshes in place.is_stale()short-circuits — perf(catalogs): skip re-filtering unchanged catalogs on list open #526's O(catalogs) list-open fast path is preserved.feat(observations): derive observed status per sky object, not per listing
Logging M 31 marks NGC 224 observed — in-session, across restarts, and retroactively for historical logs. Log entries stay recorded per
(catalog, sequence)(no schema change); the observed cache additionally maps each logged listing to itsobject_idat load,check_loggedtests id membership for DB-backed objects, andmark_loggedpropagates to sibling composites. Virtual objects (planets/comets/coordinate entries with session-minted negative ids) keep the per-listing test — logging Mars must not mark Jupiter.feat(observations): show log entries from all sibling listings on details
get_logs_for_objectresolves a DB-backed object's sibling listings, so NGC 224's details show M 31's logs ("1 Logs") instead of contradicting the row's checkmark.fix(ui): keep the cursor on target across object-list refreshes
Refreshes re-locate the previously selected object; if it was filtered out (just logged, or dropped below the altitude criterion), the cursor falls to the first surviving old successor — the natural next target — instead of resetting to the top. Matching is by
(catalog_code, sequence), sinceCompositeObject.__eq__comparesobject_idalone and would land on a sibling listing.User-visible after upgrade (intended): historical observations retroactively mark sibling listings — an "Observed: No" NGC list may visibly shrink, sibling rows gain the observed checkmark, and a sibling's details show the combined log count.
Docs
docs/adr/0020-filter-freshness-staleness-promotion.md) records the freshness policy and the observed-identity decision, including rejected alternatives (timer thread, per-object invalidation, in-memory-only propagation, schema migration).docs/ax/catalog/CONTEXT.md: Logged redefined per sky object, Log entry and Stale terms added;docs/ax/catalog.md§4 updated to match.Test plan
test_catalog_filter_cache.py,test_observed_identity.py,test_object_list_cursor.py(freshness triggers, sibling propagation, restart derivation, virtual-id fallback, sibling details logs, cursor next-target rule).main; ruff + mypy clean.🤖 Generated with Claude Code