Contrôleur de fraîcheur

Évalue si les instantanés d'analyse boursière existants sont assez récents pour être réutilisés ou si une nouvelle collecte de données est nécessaire.

Spar Skills Guide Bot
Data & IAIntermédiaire
0028/08/2026
Claude Code
#staleness-check#data-freshness#stock-analysis#snapshot-reuse

Recommandé pour

Staleness Checker — SKILL.md

Role: Step 0 — Evaluate whether existing snapshot data is fresh enough to reuse, or whether new data collection is required. Triggered by: CLAUDE.md at the start of Workflow 1 (Single Stock Analysis) and Workflow 3 (Watchlist Scan) Reads: output/data/{ticker}/latest.json, staleness rules from this file Writes: Nothing (read-only evaluation; result is reported inline to orchestrator) References: references/staleness-rules.md


Instructions

Step 0.1 — Check for Existing Snapshot

Check if output/data/{ticker}/latest.json exists. New files are pointer-only documents; legacy full-snapshot files may still appear and must remain readable.

IF file does not exist:
    → Routing decision: FRESH_COLLECTION (no cached data)
    → Proceed to Step 1 (query-interpreter)

If file exists, read it and extract:

  • analysis_date (YYYY-MM-DD)
  • expires_at and refs.analysis_result when kind is stock-analysis.latest-snapshot-pointer
  • data_mode (enhanced / standard)
  • output_mode (A / B / C / D)
  • rr_score
  • verdict

If latest.json is a pointer, verify that refs.analysis_result exists before routing to REUSE or DELTA_FAST. If the pointer is missing, expired, or points to a missing file, route to FRESH_COLLECTION.

Step 0.2 — Calculate Staleness

Calculate days_since_analysis = today - analysis_date. For pointer files, treat expires_at as the primary 24-hour reuse boundary; analysis_date remains the coarser fallback for older files and user-facing explanations.

Mode E hard override (OD-F1): When the orchestrator has set pipeline_state.mode_override == "E" (because earnings-window-detector returned window in {preview, review} at CLAUDE.md Step 0.5, or the user passed --mode E / --earnings-mode preview|review), skip the staleness table entirely and route to FRESH_COLLECTION. Mode E should never reuse a stale snapshot — implied moves, options chains, and consensus EPS shift fast in the D-7~D+3 window.

IF pipeline_state.mode_override == "E":
    → Routing decision: FRESH_COLLECTION
    → Reason: Mode E (earnings window) per OD-F1
    → Skip Step 0.2 / 0.3 / 0.4 staleness rules
    → Proceed to Step 1 (query-interpreter)

Otherwise apply the standard staleness rules:

| Days Since Analysis | Data Mode | Routing Decision | |--------------------|-----------|-----------------| | ≤ 1 day (same day) | Any | REUSE — skip Steps 1–5, proceed directly to output generation | | 2–6 days | Enhanced | DELTA_FAST — re-collect price only (Step 3 minimal), regenerate output | | 2–6 days | Standard | DELTA_FAST — run web search Step 4 only (skip full re-research) | | 7–29 days | Any | STALE — full re-collection required (Steps 1–9) | | ≥ 30 days | Any | VERY_STALE — full re-collection + flag STALE_30D in watchlist |

Step 0.3 — Earnings Detection (Override Staleness Rules)

Regardless of staleness, check if an earnings event occurred since analysis_date:

Enhanced Mode check: Call get_company_news(ticker, limit=5). If any news title contains earnings keywords, flag EARNINGS_OVERRIDE.

Standard Mode check: Search "{ticker}" earnings results Q{N} 2026. If results dated after analysis_date contain earnings data, flag EARNINGS_OVERRIDE.

Earnings keywords: earnings, quarterly results, Q1, Q2, Q3, Q4, revenue beat, EPS beat, revenue miss, 실적, 분기, 매출, 영업이익

IF EARNINGS_OVERRIDE:
    → Routing decision: FULL_COLLECTION regardless of days_since_analysis
    → Reason: earnings data fundamentally changes valuation inputs

Step 0.4 — Delta Analysis Detection (Auto Delta Mode, default ON)

Auto Delta Mode (Phase B) defaults ON. Whenever a previous snapshot exists for the ticker the orchestrator must auto-run the delta comparator regardless of keyword detection. Keyword detection is retained only as a manual fallback for older single-snapshot states (treat it as advisory, not gating).

Auto trigger rule:

IF previous snapshot exists for {ticker} (latest pointer or snapshots dir):
    → Set auto_delta = true (unless orchestrator received --no-delta)
    → After Step 10 persists the new snapshot, the prior snapshot becomes the
      "old" side and the new one becomes the "new" side.
    → Run:
      python .claude/skills/data-manager/scripts/delta-comparator.py compare \
          --ticker {ticker} --old-date latest --new-date latest --format html
    → Capture stdout into pipeline state as `auto_delta_payload.html`.
      Also capture --format markdown into `auto_delta_payload.markdown` for
      Mode D / chat-summary surfaces.
    → Renderers (Mode A/B/C/D) prepend the banner above their first content
      section. Empty stdout = no banner (graceful skip / single snapshot /
      --no-delta).

Keyword triggers (manual fallback only):

English: "compare", "vs last time", "since last analysis", "what changed", "update", "delta", "difference from before", "how has it changed"

Korean: "이전이랑", "지난번이랑", "비교해줘", "달라진 것", "바뀐 것", "업데이트", "뭐가 달라졌어", "전이랑 비교"

When --no-delta is passed by the orchestrator (CLAUDE.md Workflow 1 Step 0), set auto_delta = false and skip the comparator call. The renderers must still tolerate a missing banner (no fallback content required).

Step 0.5 — Session Context Check

Before any file checks, verify session context:

IF ticker was analyzed in the current session:
    → Use session-cached validated data (skip Steps 3–5)
    → Only regenerate output if different output_mode requested
    → Log: "Using session-cached data for {ticker} from {session_time}"

Session context keywords: "same stock", "same company", "just analyzed", 같은 종목", "방금 분석한"

Step 0.6 — Report Routing Decision

Output a concise routing decision block:

=== Staleness Check: {TICKER} ===
Snapshot found: {YES/NO}
Analysis date: {date or N/A}
Days since: {N or N/A}
Earnings override: {YES/NO}
Mode E override: {YES/NO}        # set when CLAUDE.md Step 0.5 detected window
Earnings window: {preview/review/none/—}
Delta mode: {YES/NO}

→ Routing: {REUSE / DELTA_FAST / STALE / FRESH_COLLECTION / EARNINGS_OVERRIDE}
→ Action: {brief description of what will happen next}

When Mode E override = YES, the routing block must always read Routing: FRESH_COLLECTION and the action must mention "Mode E (earnings preview/review) — fresh collection per OD-F1". Auto-delta is also applicable to Mode E (Section 0.4 still runs after Step 10) so that Review reports can show the price/EPS delta against the prior Mode C snapshot — but the staleness table itself is bypassed.


Watchlist Scan Mode

When called from Workflow 3 (watchlist scan), apply these rules per ticker:

| Condition | Action | |-----------|--------| | Pointer expires_at still valid, or legacy latest.json age < 24 hours | SKIP — reuse existing data | | Pointer expired but analysis_date < 7 days, or legacy latest.json age 24h–7 days | QUICK_UPDATE — price + news only | | latest.json age > 7 days | FULL_SCAN — abbreviated pipeline (Steps 3+4+simplified 5) | | No latest.json | FRESH — full pipeline |

For watchlist scan, do NOT run full Steps 6–9 (analysis generation). Only collect data and update alert flags.


Completion Check

  • [ ] Confirmed whether output/data/{ticker}/latest.json exists
  • [ ] If pointer format, confirmed refs.analysis_result exists
  • [ ] If mode_override=="E": forced FRESH_COLLECTION (OD-F1) and skipped staleness table
  • [ ] Calculated days_since_analysis if snapshot exists (skipped for Mode E)
  • [ ] Applied staleness rules to determine routing (skipped for Mode E)
  • [ ] Checked for earnings override condition
  • [ ] Checked for delta analysis trigger in user query
  • [ ] Checked session context for recently analyzed tickers
  • [ ] Reported routing decision with clear action statement
Skills similaires