Skip to content

Cache: confidence updates, self-invalidation, and repair rewrite (PRD §5.3) #64

Description

@myselfsiddharth

Context

contracts/cache-row.schema.json carries confidence, success_count, failure_count, and last_verified_at on every row. Nothing ever updates them. The compiler writes zeros; ReplayRunner never touches the cache at all.

PRD section 5.3 makes these fields the mechanism, not bookkeeping:

Entries are confidence-weighted by recent success rate; stale entries self-invalidate on assertion failure; the repair rewrites the entry — self-healing, and (once pooled) the repair benefits everyone

and section 11 names staleness as the top research-flagged risk, with "assertion-guards + confidence decay + self-heal" as the mitigation — "Design law, not feature."

Without this, "self-healing cache" is a claim in a pitch deck with no implementation behind it. The pitch pack already flags every performance claim as [PENDING TRACK-1]; this is one of the claims that has no code at all.

Depends on: the cache-store issue (needs somewhere to persist to).

What to build

A cache-update path invoked by the runner after each step outcome.

  1. On PASS — increment success_count, refresh last_verified_at, recompute confidence.
  2. On assertion failure (ASSERTION_FAILED, LOCATOR_NOT_FOUND, TIMEOUT) — increment failure_count, recompute confidence, and mark the row invalidated once confidence falls below a threshold. Per section 5.3 an entry that fails its assertion is by definition stale.
  3. On REPAIRED_PASS — the repair rewrites the entry: persist the corrected action as a new row version, reset counters appropriately, and record provenance linking it to the repair that produced it. This is the self-healing claim; make it literally true in the data.
  4. Define the confidence function explicitly and document it in docs/privacy/boundary-spec.md or a new docs/gate/cache.md. Recent success must count more than old success — a row that passed 100 times last year and failed 3 times today is stale. State the decay, state the invalidation threshold, and state why you chose them. These are design choices, not measurements: label them as chosen defaults, do not present them as validated.
  5. Invalidated rows are not deleted. Mark them and keep them. Deletion destroys the record of what churn did, which is the entire experiment.

Constraints

  • Confidence must never gate the gate measurement. In the matrix run, every compiled step is attempted regardless of confidence — otherwise a low-confidence row gets skipped and the step-validity denominator silently shrinks, inflating the headline number. Confidence is recorded during Track 1, not acted on. Say this in the code and in the doc, because it is exactly the kind of optimisation a later agent will "helpfully" add.
  • Updates flow through writeCacheRow() so the privacy boundary applies to rewritten rows too. A repaired action carrying a fresh tenant-tainted locator must be caught by the same fail-closed check.
  • No thresholds presented as evidence. docs/INTEGRITY-AUDIT.md category B exists because of exactly this failure mode.

How to test

npm run test        # unit: PASS increments and raises; failure increments and lowers;
                    #       threshold crossing marks invalidated; REPAIRED_PASS writes a
                    #       new version with provenance; invalidated rows are retained
npm run test:canary # a repaired action with a tainted locator must still be refused
npm run ci

Add an integration case using the fixture pipeline: replay the fixture program twice against a JsonlCacheStore and assert success_count reached 2 and last_verified_at advanced. Then break a locator, replay again, and assert failure_count incremented and the row is marked invalidated once the threshold is crossed.

Confirm the non-gating rule empirically: with a row marked invalidated, run the matrix and verify the step is still attempted and still counted in the denominator.

Before you open the PR

  • Confidence function and invalidation threshold documented as chosen defaults, with rationale, not as measured values
  • Invalidated rows retained, never deleted
  • Verified that low confidence does not cause a step to be skipped in the matrix run
  • Repaired rows pass through writeCacheRow(); tainted repair refused in a canary test
  • Integration test covers pass/fail/repair transitions end to end
  • npm run ci, npm run test:canary green
  • docs/README.md row for any new doc
  • Branch track1/b5-cache-confidence

Metadata

Metadata

Assignees

Labels

area: cacheTouches cacheenhancementNew feature or requestprivacy-boundaryTouches the privacy boundary — canary is merge-blockingsize/M<= 200 changed linestrack-1Technical gate / churn harness

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions