ring/dev-team/skills/shared-patterns/standards-cache-protocol.md
Fred Amaral 33c9e97d03
fix(codereview): complete cache-first standards injection end-to-end
The cache-first feature injected <standards> blocks into 5 reviewer dispatch prompts, but only performance-reviewer parsed them — code, business-logic, security, and test reviewers ignored the injection and re-fetched standards on every run. The orchestrator-side half shipped without the consumer-side half.

Each of the 4 default reviewer agents now has a Standards Loading (Cache-First) section implementing the canonical three-tier resolution: cache hit from state.cached_standards, cache miss via WebFetch with warning, standalone fallback to hardcoded URLs. The per-reviewer fallback URL lists are unique and derived from each reviewer's standards_slice.

The 5-way verbatim duplication of the dispatch block in codereview/SKILL.md is collapsed to per-reviewer URL-slice markers that reference shared-patterns/standards-cache-protocol.md as the single source of truth. The shared pattern now carries the canonical <standards> template, orchestrator pseudocode, three-tier protocol, rolling-standards policy, and an anti-rationalization table defending cache-first behavior. Net 117-line reduction in codereview/SKILL.md.

X-Lerian-Ref: 0x1
2026-04-18 10:44:17 -03:00

6.6 KiB
Raw Blame History

name description
shared-pattern:standards-cache-protocol Protocol for reading cached standards from cycle state instead of WebFetching directly. Includes the canonical `<standards>` dispatch block format and the cache-first resolution protocol that reviewer agents follow at runtime.

Standards Cache Protocol

Purpose

Eliminate redundant WebFetch calls during a dev-cycle by pre-caching all required standards at cycle start (dev-cycle Step 1.5) and having sub-skills and reviewer agents read from state instead of fetching inline on every dispatch.

This document is the single source of truth for:

  1. How orchestrators build the <standards> block at dispatch time.
  2. How reviewer agents resolve that block (cache hit / cache miss / standalone fallback).

Canonical <standards> Block Format

Orchestrators (dev-cycle, codereview SKILL) MUST use this exact block shape when injecting cached standards into a reviewer's dispatch prompt:

<standards>
  <standard url="https://raw.githubusercontent.com/LerianStudio/ring/main/.../file.md">
    <content>{{ state.cached_standards["<same url>"].content OR empty }}</content>
  </standard>
  <!-- ...one <standard> per URL in the reviewer's slice... -->
</standards>

Rules:

  • url attribute is ALWAYS populated (the canonical URL on main).
  • <content> is populated when state.cached_standards[url] exists (cache hit).
  • <content> is empty when the orchestrator has no cached entry (cache-miss signal).

Orchestrator Resolution (at dispatch time)

for each url in standards_slice:
  if state.cached_standards[url] exists:
    emit <standard url="..."><content>{{cached content}}</content></standard>
  else:
    emit <standard url="..."><content></content></standard>  # cache-miss signal

Reviewer/Sub-Skill Resolution (at runtime)

Reviewer agents and sub-skills MUST follow this three-tier protocol, in order:

  1. Cache hit. If the dispatch prompt contains a <standards> block and a <standard>'s <content> is populated, use that content as the authoritative rules source. No WebFetch needed.
  2. Cache miss fallback. If a <standard>'s <content> is empty, WebFetch that <standard>'s url yourself and use the fetched content. Log a "Standard {url} not in cache; fetching inline" warning so operators can detect orchestrator misconfigurations. Do not skip the standard.
  3. Standalone fallback. If the dispatch prompt contains no <standards> block at all (standalone/legacy invocation, no dev-cycle context), WebFetch the reviewer's hardcoded fallback URL list (defined in the reviewer agent itself) and proceed.

Pseudocode form (equivalent):

STEP 1: Check cache
  IF <standards> block is present AND <standard>.<content> is populated:
    use content directly (cache hit)
    proceed

STEP 2: Cache-miss fallback
  IF <standards> block is present AND <standard>.<content> is empty:
    log WARNING: "Standard {url} not in cache; fetching inline"
    content = WebFetch(standard.url)
    proceed

STEP 3: Standalone fallback
  IF no <standards> block in dispatch prompt:
    FOR EACH url in reviewer's hardcoded fallback list:
      content = WebFetch(url)
    proceed

Rolling Standards Policy

All URLs point to the main branch. WebFetch always returns current rules; there is no pinned version. This is intentional — installed plugins pick up standards updates without a plugin release.

For Orchestrators (dev-cycle, dev-cycle-frontend)

At Step 1.5 of the cycle:

  1. Detect project stack (Go / TypeScript / Frontend).
  2. Build the URL list (see dev-cycle Step 1.5 for the current list).
  3. WebFetch each URL once.
  4. Write to state.cached_standards[URL] = {fetched_at, content}.
  5. MANDATORY: Save state to file.
  6. Blocker if ANY URL fails to fetch.

At dispatch time (Step 3 of codereview, and elsewhere): build the <standards> block per the canonical format above, one <standard> entry per URL in the reviewer's slice.

Why

Before: ~1525 WebFetch calls per cycle (one per sub-skill/reviewer dispatch). Prompt cache TTL of 5 min is regularly exceeded, causing repeated network fetches of identical content.

After: Exactly ONE WebFetch per unique URL per cycle. Same content, ~5x fewer network operations.

Safety

If the cache mechanism fails or is bypassed:

  • Sub-skills and reviewers fall back to direct WebFetch (with warning log).
  • No correctness regression; only performance regression.
  • Operators can monitor "Standard {URL} not in cache" warnings to detect misconfigurations.

Anti-Rationalization Table

Rationalization Why It's WRONG Required Action
"The cache might be stale — safer to WebFetch directly" The cache is populated once at dev-cycle Step 1.5 specifically so every sub-skill and reviewer sees identical standards content within a cycle. Re-fetching creates drift between reviewers running in parallel and produces inconsistent verdicts. MUST read from state.cached_standards[url] when a <standards> block is present in the dispatch prompt. MUST NOT re-WebFetch on cache hit.
"Empty <content> probably means the orchestrator failed — I'll just skip" Empty <content> is the documented cache-miss signal. Skipping standards loading silently omits compliance checks the orchestrator expected to run. MUST WebFetch the URL on empty <content> and emit a WARNING to surface the cache miss. MUST NOT skip the standard.
"No <standards> block in my prompt — I'll abort" Absence of the block means standalone invocation (not dispatched from dev-cycle). Standalone invocation is a supported mode; the reviewer MUST still load standards via direct WebFetch using its own fallback URL list. MUST fall back to WebFetch of hardcoded URLs when no <standards> block is present. MUST NOT fail the review.
"The cached content looks old — I'll fetch a fresh copy" The cache is an intra-cycle consistency guarantee, not a freshness guarantee. Freshness is the orchestrator's concern at Step 1.5. A reviewer that second-guesses cache freshness breaks the guarantee for its peers. MUST trust cached content within a cycle. Report staleness concerns to the orchestrator via the Standards Compliance section of the review output, not by re-fetching.
"Silent fallback is fine — no one reads warnings" Silent fallbacks hide misconfigured orchestrators and let cache-population bugs fester across cycles. The WARN log is how operators detect cache-population regressions. MUST emit a clearly-prefixed WARNING log on every cache miss (e.g., [cache-miss] WebFetching <url>).