Skip to content

Canonical Home Artifact Cache Key

Issue #1199 defines the canonical Home artifact key for the #1195 responsiveness work. This document is a spec for later foreground-read, stale-first, and warmer wiring; the #1199 implementation does not change production foreground serving behavior.

The tracked implementation is app/lib/board/cache_key.py. It is pure and side-effect-free: callers provide an explicit HomeArtifactKeyInputs snapshot and receive a deterministic home-artifact-v1:<digest> key plus a human-readable hit/miss/stale comparison report.

The key is used today only by the inert local/shadow harness:

  • app/lib/board/cache_key_shadow.py models foreground current inputs, stale-first prior artifact inputs, and warmer-produced inputs, then compares the stale-first and warmer snapshots against the foreground canonical key.
  • imperfect-cli home-cache-key-shadow <snapshot.json> reads explicit JSON snapshots into that adapter and emits the report as JSON or compact text.
  • tests/lib/board/test_cache_key_shadow.py and tests/cli/commands/test_home_cache_key_shadow.py cover that usage path.

Future #1200/#1203 work can wire the same adapter shape into live foreground/stale/warm behavior. This PR does not import it from UserBoard._prepare_generation or change production foreground serving decisions.

Freshness Boundary

The canonical key includes every input family that can change the rendered Home artifact:

Family Inputs Source
Request day/context local date, timezone, locale, units, client platform, rounded location bucket foreground request or latest stored client profile
Provider state active provider set, hashed provider refs, permissions, connection sync token imperfect-api connection state
Health freshness opaque provider/data-type freshness token Alice-owned monotonic watermark in production; local tests may use row-count/date proxies
Event active event id and version UserEvent snapshot
Plan plan id, plan start, version, content hash WeeklyPlan snapshot
Schema/client bucket board schema version, app-version bucket, schema source hash API/schema release rules
Prompt/context prompt version/hash and context version/hash board generation code and replay context

The existing production cache telemetry still reports event-plan-v1. That current serving boundary checks only board date, active event id, and plan version timestamp. home-artifact-v1 is stricter and is not wired into UserBoard._prepare_generation yet.

Comparison Semantics

compare_home_artifact_inputs(current=..., prior=...) returns:

  • miss with no_prior_artifact when no prior artifact exists.
  • hit when the canonical key and all compared dimensions match.
  • stale with stable reason codes when a prior artifact exists but any key dimension changed.

Reason codes are intentionally human-readable in reports: timezone_changed, locale_changed, units_changed, provider_set_changed, health_freshness_changed, active_event_added, event_version_changed, plan_version_changed, app_version_bucket_changed, prompt_context_changed, and the adjacent subfield reasons for plan identity/content, board schema/source, platform, and location bucket.

Foreground reads and stale-first candidates should compute the same current HomeArtifactKeyInputs. Stale-first is a serving policy over a prior artifact after comparison; it is not a separate key.

For role-level local checks, compare_home_artifact_shadow(...) returns one report with:

  • the foreground current key
  • a stale-first prior artifact comparison row
  • a warmer-produced artifact comparison row
  • request-context mismatch fields for local date, timezone, locale, units, app-version bucket, client platform, and rounded location bucket

Warmer Contract

Warmers should write artifacts per canonical client-context bucket when they have a target bucket. The request-context dimensions are:

  • local date
  • timezone
  • locale
  • units
  • app-version bucket / board schema bucket
  • client platform
  • rounded location bucket

A warmer that only knows the latest stored client profile can warm that bucket. If a later foreground request arrives with a different timezone, locale/units, old-client schema bucket, platform, or location bucket, the canonical comparison must report a warm miss or stale reason. That is the intended safe tradeoff: accept request-context warm misses instead of serving a stale/no-activity or wrong-locale artifact as fresh.

Health Freshness

The #1199 local shadow used row count plus min/max observed dates as a health token proxy. Production should not do SQL-ish probes from imperfect-api for this key. The key accepts opaque HomeHealthFreshnessToken values so #1200/#1203 can later consume Alice-owned monotonic freshness watermarks without changing the key shape.

Local Shadow Findings

The local #1199 shadow result showed that the current event-plan-v1 boundary catches date, active-event-id, and newer-plan changes, but misses locale/units, provider set, health freshness, event-version-only, schema/app-version bucket, prompt/context, and app-visible location/settings changes.

Warmer-style keys agreed for database/event-driven changes when reading the same canonical state, but missed request/client-context changes. home-artifact-v1 makes that mismatch explicit by requiring the same key inputs and by reporting the request-context stale reason.