Skip to content

Commit cb57835

Browse files
committed
docs(signals): deferred-items log for the as_of + Dow-30 plan pair
1 parent 933be1a commit cb57835

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Deferred items — as_of endpoint (PR A #340) + Dow-30 reconcile (PR B/C)
2+
3+
Deferred-items log for the 2026-07-10 plan pair (`2026-07-10-signals-asof-endpoint.md`, `2026-07-10-dow30-watchlist-reconcile.md`), per the AFK-loop defer rules (D1–D6).
4+
5+
### §PR-A.1 — Producer retention (`prune_artifacts`) is mtime-ordered, not calendar-aware
6+
7+
**Status: deferred 2026-07-11 in PR #340 (defer rule D1 — unrelated module untouched by the PR)**
8+
9+
**What:** `Heartbeat/news_signals.py:598-613` prunes to `SIGNALS_KEEP_N` newest artifacts by raw `(mtime, name)`. After an old day's artifact is rewritten in place with a fresh mtime (state-file surgery, or crash-recovery reprocessing after extended downtime), the next prune (needs ≥15 artifacts on disk) can evict a calendar-newer artifact while keeping the backfilled older day — a `?as_of=<evicted day>` then 404s for a date inside the nominal retention window. Verified CONFIRMED but narrow: no automated path reprocesses a state-recorded items file; PR A's read path is already hardened (`(stem_date, mtime, name)` selection).
10+
11+
**Why deferred:** D1 — the producer is untouched by PR #340 (`git diff origin/main...feat/signals-asof -- Heartbeat/` was empty); the design spec deliberately scoped retention out (spec §"backfilled/reprocessed" note). Pre-existing property of PR #339.
12+
13+
**Next-session entry point:** `Heartbeat/news_signals.py:607` — align the prune sort with `(stem_date, mtime, name)` (mirroring `Main/backend/api/signals_views.py:_load_artifact`), or document mtime-based retention in the §4.4 contract. Effort: ~1h incl. a regression test.
14+
15+
### §PR-A.2 — Flaky pre-existing DeprecationWarning in test output
16+
17+
**Status: deferred 2026-07-11 in PR #340 (defer rule D1 — unrelated module untouched by the PR)**
18+
19+
**What:** `Main/backend/api/utils/resource_monitor.py:63``asyncio.get_event_loop()` raises `DeprecationWarning: There is no current event loop` during `test_artifact_loaded_from_disk_once_per_request` in some runs (nondeterministic; also the lone warning in the 675-test full-suite run). Breaks pristine-output discipline.
20+
21+
**Why deferred:** D1 — `resource_monitor.py` is untouched by PR #340; the triggering test predates the branch.
22+
23+
**Next-session entry point:** `Main/backend/api/utils/resource_monitor.py:63` — replace with `asyncio.get_running_loop()` inside try/except or `asyncio.new_event_loop()` per intent. Effort: ~15 min.
24+
25+
### Triage log — reviewed and intentionally not changed (not deferrals)
26+
27+
- **Split malformed-`as_of` handling** (`signals_views.py` `_get_artifact` swallows → None for `@condition`; view re-parses → 400): plan-mandated verbatim, single caller, pairing documented in both docstrings; inherent to Django's validators-must-not-raise constraint. WONTFIX (polish option: request-stashed parse-error flag).
28+
- **Double `_as_of` parse per request / double `_stem_date` per candidate:** pure CPU string parses, N≤~30, no I/O; restructuring risks the frozen selection-key semantics. WONTFIX.
29+
- **ETag excludes the resolved as_of date:** REFUTED as a defect — `source_items` structurally embeds the batch stem (producer `news_signals.py:626-627` derives the artifact filename from the same string), so distinct days cannot collide. Optional defense-in-depth (fold `newest.name` into the ETag) noted, not needed.
30+
- **Non-dated stems excluded under `as_of` but not under no-param:** intentional per plan; unreachable from the producer (all stems date-prefixed); §4.4 now says "latest **dated** artifact".
31+
- **Test `os.utime` skew boilerplate ×3:** style nit; a `_touch()` helper if the convention ever changes.

0 commit comments

Comments
 (0)