docs: D20 — honest forward-reference annotations across README/ADRs (Finding 9)

cold-audit catch from 2026-05-23

Cold-audit Finding 9 (P3 drift): multiple docs referenced files / paths
/ directories that don't exist at the current implementation state. A
reader following AGENTS.md § "Key files to know" to read lib/keys.mjs
would find no such file; following README architecture to dashboard.html
same; ADR 0005 § D1 described a `~/.olp/cache/<key>/<prefix>/<hash>.json`
layout that doesn't exist (current impl is in-memory Map per
lib/cache/store.mjs). D20 doesn't gut the designs — it adds honest
status callouts so the gap is obvious within seconds.

Files changed (8, docs only, +46 / -14):

1. README.md (+32 / -3):
   - New H2 section "Implementation status (as of 2026-05-24)" with a
     10-row table distinguishing  Shipped vs 📋 Planned, including phase
     numbers (Phase 2 / 6 / 7) matching the existing §"Phase plan"
   - Inline status annotation on the multi-key auth bullet
     (lib/keys.mjs marked planned for Phase 2)
   - Inline status on the cache layer bullet (file-backed storage marked
     Phase 2 — current is in-memory Map)
   - Migration section's Phase 7 placeholder annotated explicitly

2. AGENTS.md (+8 / -3):
   - Inline `📋 Planned (Phase N) — not yet authored` markers on
     lib/keys.mjs and dashboard.html in the "Key files" bullet list
   - Inline marker on setup.mjs reference in the
     "Project-specific constraints" section
   - New "Implementation status note" paragraph at the end of the Key
     files block pointing to README's status table for the full picture

3. ALIGNMENT.md (+6 / -3):
   - docs/openai-spec-pin.md references (Authority 2 + audits section)
     tightened from "deferred" to "deferred, not yet authored; must be
     created before first annual audit (target: v1.0)"
   - docs/alignment-audits/ directory annotated as "directory does not
     exist yet; it is created when the first audit is conducted"

4. CLAUDE.md (+2):
   - release_kit.bootstrap_quirk_policy YAML retains the
     scripts/migrate-from-ocp.mjs reference (forward-looking spec
     compliance) and adds an inline YAML comment explicitly noting
     "is planned (Phase 7), not yet authored. The scripts/ directory
     does not currently exist. References here are forward-looking;
     do not attempt to run this script."

5-8. ADR amendments (status notes only — no Amendment blocks, since
     these are clarifications about implementation state, NOT decision
     changes per se):
   - ADR 0001 (Consequences/Negative): scripts/migrate-from-ocp.mjs
     annotated as Phase 7 planned
   - ADR 0003 § Decision (lossy-translation paragraph): inline note that
     docs/provider-caveats.md is planned; until it exists, lossy edges
     are recorded only in plugin headers. Plus a status mention in
     Consequences/Positive
   - ADR 0004 Mitigations: docs/provider-caveats.md annotated as planned
   - ADR 0005 § Decision (D1 paragraph): the file-backed layout block
     reframed from "Cache directory structure:" to "Designed file-backed
     layout (target for Phase 2 storage adapter):". Added a status
     blockquote explicitly noting "v0.1 implementation in lib/cache/store.mjs
     uses an in-memory Map; no files written to ~/.olp/cache/. The
     file-backed layout described above is the designed shape; it
     transitions in via a Phase 2 storage adapter. Per-key isolation and
     singleflight (D4) are live; file persistence is not."

Note on ADR Decision-section edits (corrected from initial writeup):
two ADR amendments DO touch Decision-section text (ADR 0003 lossy-
translation paragraph, ADR 0005 D1 cache layout). Both edits are
conservative — status caveats that preserve the original prose verbatim
(0003) or reframe section headings without changing the path-shape spec
(0005). No design content is gutted. No Amendment block was added
because the decisions themselves aren't changing; these are clarifications
about what's live today vs designed. The discipline boundary here:
inline-status-note ≠ decision-amendment.

Tests: 328/328 unchanged (sanity check; docs-only changes).

7/7 Finding 9 forward references annotated (confirmed by reviewer
running independent `ls` on each path):
- lib/keys.mjs  doesn't exist → annotated
- dashboard.html  doesn't exist → annotated
- docs/provider-caveats.md  → annotated (2 ADR sites + Consequences)
- docs/openai-spec-pin.md  → annotated (ALIGNMENT.md Authority 2)
- docs/alignment-audits/  → annotated
- scripts/migrate-from-ocp.mjs  → annotated (README + ADR 0001 + CLAUDE.md release_kit)
- setup.mjs  → annotated (AGENTS.md)

Authority:
- README/AGENTS.md/ADR/ALIGNMENT.md/CLAUDE.md self — the doc set is
  its own authority for what it documents; D20 brings each statement
  into honest agreement with the current implementation
- CC 开发铁律 v1.6 § 10.x — Cold Audit Finding 9

Reviewer (Iron Rule v1.6 § 10.x Mode A, fresh-context opus, independent
of drafter): APPROVE_WITH_MINOR. Verified each Finding 9 path doesn't
exist via independent `ls`; cross-checked phase numbers match the
existing §"Phase plan" listing; ran `npm test` to confirm 328/328
unchanged. Two non-blocking minors:

1. Implementer's initial writeup overstated "ADR decision text NOT
   edited" — reality is two Decision-section paragraphs got inline
   status caveats. Commit message above is corrected.

2. Reviewer found an additional drift D20 didn't address: ADR 0002 §
   Decision filesystem layout lists `vibe.mjs` for the Mistral plugin,
   but the shipped file is `mistral.mjs` (the binary is `vibe`, the
   plugin file is `mistral`). Different drift class from Finding 9
   (file exists, just named differently in the ADR). Filed as
   follow-up issue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 12:26:02 +10:00
co-authored by Claude Opus 4.7
parent ed82e65859
commit d85a2dcf71
8 changed files with 46 additions and 14 deletions
+5 -3
View File
@@ -37,14 +37,16 @@ Runtime: Node.js (ESM, `.mjs` throughout). No build step. No bundler. `server.mj
- `lib/ir/` — Intermediate Representation definition + serializers. Governed by ADR 0003.
- `lib/cache/` — content-addressed cache layer (per-key isolation, `cache_control` bypass, chunked stream replay, singleflight). Governed by ADR 0005.
- `lib/fallback/` — fallback engine (trigger detection, chain advancement, idempotent-failure safety, header annotation). Governed by ADR 0004.
- `lib/keys.mjs` — multi-key auth, per-key namespacing, audit log. Carries OCP's per-key isolation model into OLP.
- `dashboard.html` — owner-only multi-provider dashboard (quota panels, fallback rate, cache hit rate).
- `lib/keys.mjs` — multi-key auth, per-key namespacing, audit log. Carries OCP's per-key isolation model into OLP. **📋 Planned (Phase 2) — not yet authored.**
- `dashboard.html` — owner-only multi-provider dashboard (quota panels, fallback rate, cache hit rate). **📋 Planned (Phase 6) — not yet authored.**
- `models-registry.json` — single source of truth for `(provider, model) → metadata`. SPOT.
- `ALIGNMENT.md` — the constitution. Binding for any plugin / entry-surface / IR change.
- `docs/adr/` — Architecture Decision Records. Read the index in `docs/adr/README.md` before proposing governance, SPOT, or contract changes.
- `.github/workflows/alignment.yml` — CI blacklist grep + per-provider citation soft check; fails the build on known-hallucinated tokens.
- `CLAUDE.md` — Claude-Code-specific session instructions + `release_kit` overlay (Iron Rule 5.5).
**Implementation status note (as of 2026-05-24):** Files marked 📋 above are designed and documented but not yet on disk. For the full status table see `README.md § "Implementation status"`. Do not attempt to read or import these files — they will not be found. The shipped set as of Phase 1 is: `server.mjs`, `lib/ir/`, `lib/providers/{anthropic,codex,mistral}.mjs`, `lib/cache/{keys,store}.mjs`, `lib/fallback/engine.mjs`, `models-registry.json`, `test-features.mjs`.
---
## Project-specific constraints
@@ -52,7 +54,7 @@ Runtime: Node.js (ESM, `.mjs` throughout). No build step. No bundler. `server.mj
- **`ALIGNMENT.md` is binding.** Any PR touching a provider plugin, the entry surface, or the IR must cite the relevant authority (provider CLI documentation / OpenAI spec URL / ADR number) in the commit body and PR description. See `CLAUDE.md` § "Hard requirements for plugin / server.mjs changes" and `ALIGNMENT.md` Rules 1, 2, 5.
- **Alignment CI is not suppressible.** The `alignment.yml` workflow greps for known-hallucinated tokens (currently carrying OCP's `api.anthropic.com/api/oauth/usage` as a transitive guardrail) and runs per-provider sanity checks. Adding new blacklist tokens is done via PR amendment to `alignment.yml`; removing entries requires an `ALIGNMENT.md` amendment PR.
- **No self-approval.** Implementation author cannot merge their own PR (Iron Rule 10). A fresh-context reviewer must open the cited authority and confirm in the review comment.
- **`models-registry.json` is the only place to add/edit `(provider, model)` metadata.** Do not touch hardcoded model maps in `server.mjs`, `lib/providers/*.mjs`, or `setup.mjs`. The OLP ADR that codifies this SPOT discipline lands in Phase 1 (OCP's ADR 0003 — `models.json` SPOT — is the precedent; OLP needs its own SPOT ADR because the registry shape differs).
- **`models-registry.json` is the only place to add/edit `(provider, model)` metadata.** Do not touch hardcoded model maps in `server.mjs`, `lib/providers/*.mjs`, or `setup.mjs` (📋 `setup.mjs` is planned, not yet authored). The OLP ADR that codifies this SPOT discipline lands in Phase 1 (OCP's ADR 0003 — `models.json` SPOT — is the precedent; OLP needs its own SPOT ADR because the registry shape differs).
- **Provider plugins follow the contract in ADR 0002.** A new provider plugin must implement every method on the Provider contract (`name`, `displayName`, `models`, `auth`, `spawn`, `estimateCost`, `quotaStatus`, `healthCheck`, `hints`). Partial implementations are unalignable per `ALIGNMENT.md` Rule 4.
- **No anti-fingerprinting.** OLP is honest about spawning the real CLI. If a provider detects subscription-spawn proxying and bans it, the response is to drop the provider per ADR 0006, not to mask the spawn.
- **No conversation state.** OLP is a stateless proxy. Memory / continuity is the client's responsibility (see ADR 0001 § Non-mission).
+3 -3
View File
@@ -65,7 +65,7 @@ OLP exposes a single external HTTP surface: `/v1/chat/completions` in OpenAI Cha
Citation format for entry-surface PRs: OpenAI spec URL + the specific field, parameter, or behaviour. Example: `OpenAI Chat Completions, response_format parameter (https://platform.openai.com/docs/api-reference/chat/create#chat-create-response_format)`.
The spec pin lives in `docs/openai-spec-pin.md` (created at Phase 1; not required for v0.1 governance bootstrap to land).
The spec pin lives in `docs/openai-spec-pin.md` — deferred, not yet authored; will land before the first annual audit (target: v1.0). Not required for v0.1 governance bootstrap.
### Authority 3 — IR contract (internal interop scope)
@@ -154,10 +154,10 @@ In addition to the recurring 14 May audit below, the following one-shot audits a
- **Date:** 14 May each year (the anniversary of the Anthropic 2026-05-14 announcement, which is the structural trigger for OLP).
- **Scope (per-provider plugin):** For each enabled provider, re-audit the provider CLI version against the pin in the Authorities table above. Re-verify that every spawn invocation, flag, and output-parser expectation in `lib/providers/<name>.mjs` still matches that CLI version's actual behaviour. Update the pin row in this file.
- **Scope (entry surface):** Snapshot OpenAI's `/v1/chat/completions` specification and diff against the pin in `docs/openai-spec-pin.md`. For each field OLP implements, verify the spec still defines it the same way. Update the pin.
- **Scope (entry surface):** Snapshot OpenAI's `/v1/chat/completions` specification and diff against the pin in `docs/openai-spec-pin.md` (📋 deferred — not yet authored; must be created before the first annual audit). For each field OLP implements, verify the spec still defines it the same way. Update the pin.
- **Scope (IR):** Diff the IR documented in ADR 0003 against the implementation in `lib/ir/`. Any drift triggers an amendment or a deletion PR.
- **Scope (Risk Tier reclassifications):** For each provider, re-evaluate the risk tier against current ToS, FAQ language, and observed enforcement events from the past year. Reclassifications land as ADR 0006 amendments.
- **Output:** A signed audit note committed to `docs/alignment-audits/YYYY-05-14.md`, updating pins inline in this file as needed.
- **Output:** A signed audit note committed to `docs/alignment-audits/YYYY-05-14.md` (📋 `docs/alignment-audits/` directory does not exist yet; it is created when the first audit is conducted). Inline pin updates go into this file.
- **Failure mode:** Any finding that cannot be reconciled triggers an immediate deletion PR per the Unalignable Policy.
---
+2
View File
@@ -106,4 +106,6 @@ release_kit:
- new file / SPOT / schema → Architecture or contributor § with link
bootstrap_quirk_policy:
- any first-run migration quirk (e.g., from OCP) → README § "Troubleshooting" + scripts/migrate-from-ocp.mjs if applicable
# NOTE: scripts/migrate-from-ocp.mjs is planned (Phase 7), not yet authored. The scripts/ directory
# does not currently exist. References here are forward-looking; do not attempt to run this script.
```
+29 -3
View File
@@ -133,6 +133,32 @@ If a fallback chain is exhausted, `X-OLP-Fallback-Exhausted` lists the tried pro
---
## Implementation status (as of 2026-05-24)
Phase 1 is in progress. This table reflects what is currently shipped vs. what is designed for later phases.
| File / artifact | Status | Notes |
|---|---|---|
| `server.mjs` | ✅ Shipped | HTTP listener + dispatcher |
| `lib/ir/` | ✅ Shipped | IR definition + serializers (ADR 0003) |
| `lib/providers/anthropic.mjs` | ✅ Shipped | `claude -p` spawn-binary plugin |
| `lib/providers/codex.mjs` | ✅ Shipped | `codex exec --json` plugin |
| `lib/providers/mistral.mjs` | ✅ Shipped | `vibe --prompt` plugin |
| `lib/cache/keys.mjs` | ✅ Shipped | Content-addressed key computation |
| `lib/cache/store.mjs` | ✅ Shipped | In-memory Map (file-backed layout: 📋 Phase 2 storage adapter) |
| `lib/fallback/engine.mjs` | ✅ Shipped | Trigger evaluation + chain advancement (ADR 0004) |
| `models-registry.json` | ✅ Shipped | SPOT for `(provider, model)` metadata |
| `test-features.mjs` | ✅ Shipped | 328-test suite (CI: `test.yml`) |
| `lib/keys.mjs` | 📋 Planned (Phase 2) | Multi-key auth, per-key namespacing, audit log |
| `dashboard.html` | 📋 Planned (Phase 6) | Owner-only multi-provider dashboard |
| `docs/provider-caveats.md` | 📋 Planned (Phase 3+) | Lossy-translation reference; for now documented inline in each plugin header |
| `docs/openai-spec-pin.md` | 📋 Planned (Phase 1 gate) | OpenAI spec snapshot for annual audit; deferred from v0.1 bootstrap |
| `docs/alignment-audits/` | 📋 Planned | Output directory for annual alignment audits (first audit: 2027-05-14) |
| `scripts/migrate-from-ocp.mjs` | 📋 Planned (Phase 7) | OCP → OLP migration tool |
| `setup.mjs` | 📋 Planned | Setup wizard / initial config |
---
## Architecture
OLP is a Node.js (ESM, `.mjs`) HTTP proxy with no build step and minimal dependencies. The high-level shape:
@@ -140,9 +166,9 @@ OLP is a Node.js (ESM, `.mjs`) HTTP proxy with no build step and minimal depende
- **Entry surface** — `server.mjs` handles `/v1/chat/completions` and the administrative endpoints. Governed by OpenAI's `/v1/chat/completions` specification as the wire authority. See [`ALIGNMENT.md` § Authorities](./ALIGNMENT.md#authorities).
- **Intermediate Representation (IR)** — `lib/ir/` normalizes between the entry surface and provider-native shapes. The IR is the lingua franca; any extension is an [ADR 0003](./docs/adr/0003-intermediate-representation.md) amendment.
- **Provider plugins** — `lib/providers/<name>.mjs`. Each plugin implements the contract in [ADR 0002 (Plugin Architecture for Providers)](./docs/adr/0002-plugin-architecture.md), spawns its CLI, and translates between IR and provider-native IO.
- **Cache layer** — `lib/cache/` is a content-addressed cache keyed on `(provider, model, messages, tools, temperature, response_format, cache_control)`. Per-key isolation, prompt-caching bypass, chunked stream replay, and singleflight. See [ADR 0005 (Cache Layer Cross-Provider Design)](./docs/adr/0005-cache-cross-provider.md).
- **Cache layer** — `lib/cache/` is a content-addressed cache keyed on `(provider, model, messages, tools, temperature, response_format, cache_control)`. Per-key isolation, prompt-caching bypass, chunked stream replay, and singleflight. See [ADR 0005 (Cache Layer Cross-Provider Design)](./docs/adr/0005-cache-cross-provider.md). Current backing store is an in-memory Map; file-backed storage is planned for Phase 2.
- **Fallback engine** — `lib/fallback/` advances a configured chain one provider at a time on configured triggers, never retrying after the first response chunk has been emitted to the client. See [ADR 0004](./docs/adr/0004-fallback-engine.md).
- **Multi-key auth** — `lib/keys.mjs` carries OCP's per-OLP-key namespace isolation forward. Each OLP API key has independent quota, cache namespace, and audit log; each key declares which providers it can access.
- **Multi-key auth** — `lib/keys.mjs` (📋 planned, Phase 2) will carry OCP's per-OLP-key namespace isolation forward. Each OLP API key will have independent quota, cache namespace, and audit log; each key declares which providers it can access.
Read the ADRs in `docs/adr/` in order before proposing structural changes.
@@ -168,7 +194,7 @@ Full spec (decision rationale, open questions, risks): `~/.cc-rules/memory/proje
## Migration from OCP
_placeholder — `scripts/migrate-from-ocp.mjs` lands with Phase 7._
_placeholder — `scripts/migrate-from-ocp.mjs` lands with Phase 7 (📋 planned, not yet authored)._
Anticipated user-facing flow (target: <5 minutes):
+1 -1
View File
@@ -53,7 +53,7 @@ OCP ADR 0005 receives a header amendment on merge of this ADR: *"Superseded in p
**Negative**
- OCP's `cli.js`-alignment moat (ADR 0002 + 0005) does not transfer. OLP proxies multiple CLIs, each with its own protocol authority; the `cli.js` byte-for-byte discipline becomes per-provider per-CLI discipline (see ADR 0002 and the new OLP ALIGNMENT.md). This is more surface area to keep honest, not less.
- Migration cost for the user: stop OCP, install OLP, point clients at the new port, migrate auth tokens. Spec §7 budgets this at <5 minutes via `scripts/migrate-from-ocp.mjs`. Real-world time will be higher on the first machine.
- Migration cost for the user: stop OCP, install OLP, point clients at the new port, migrate auth tokens. Spec §7 budgets this at <5 minutes via `scripts/migrate-from-ocp.mjs` (📋 planned, Phase 7 — not yet authored). Real-world time will be higher on the first machine.
- The maintainer now operates two repos during OLP's pre-v1.0 phase: OCP in maintenance, OLP under active development. This is intentional — OCP serves real traffic today and cannot be deleted in advance — but doubles the release surface temporarily.
**Mitigations**
+2 -2
View File
@@ -65,7 +65,7 @@ for await (const irChunk of irResponseStream) {
}
```
**Lossy-translation documentation requirement.** When a provider plugin's `irToNative` or `nativeToIR` cannot losslessly carry an IR field (e.g., Mistral Vibe does not support `tool_choice: "required"`), the lossy edge is documented in the provider plugin's header comment AND in `docs/provider-caveats.md`. The caveats document is referenced from `/v1/models` response metadata so clients can see provider-specific limits without reading source.
**Lossy-translation documentation requirement.** When a provider plugin's `irToNative` or `nativeToIR` cannot losslessly carry an IR field (e.g., Mistral Vibe does not support `tool_choice: "required"`), the lossy edge is documented in the provider plugin's header comment AND in `docs/provider-caveats.md` (📋 planned — not yet authored; until it exists, lossy translations are recorded only in the provider plugin header comments). The caveats document is referenced from `/v1/models` response metadata so clients can see provider-specific limits without reading source.
**IR is versioned.** This ADR ratifies IR v1.0. Future additions (e.g., a `reasoning_effort` field if reasoning-model behavior diverges enough across providers to warrant explicit modeling) require an amendment ADR. Removals are breaking changes and require a major-version bump of OLP.
@@ -76,7 +76,7 @@ for await (const irChunk of irResponseStream) {
**Positive**
- Adding a provider is N translation functions (one IR→native, one native→IR), not 2N (one openai→native, one native→openai for every provider). The maintenance burden of "OpenAI shipped a new field" is one entry-adapter change, not one change per provider.
- The fallback engine (ADR 0004) replays the same IR object across providers in a chain. Replay correctness depends on IR being a fixed-shape data structure; there is no per-provider state leaking through that the next chain hop has to re-derive.
- Lossy translations are documented per-provider and surfaced to clients via `docs/provider-caveats.md` + `/v1/models` metadata. A client choosing a fallback chain can see "this chain's third hop is Mistral, which does not support tool_choice=required" *before* they hit the failure mode.
- Lossy translations are documented per-provider and surfaced to clients via `docs/provider-caveats.md` (📋 planned) + `/v1/models` metadata. A client choosing a fallback chain can see "this chain's third hop is Mistral, which does not support tool_choice=required" *before* they hit the failure mode.
- The IR is OLP's source of truth for "what was actually requested" for cache-key generation (ADR 0005). Caching on OpenAI shape would couple cache keys to OpenAI field naming; caching on IR makes the cache key provider-agnostic.
**Negative**
+1 -1
View File
@@ -105,7 +105,7 @@ Each fallback hop emits a structured log event with: timestamp, chain id, hop in
**Mitigations**
- The first-chunk rule applies at the byte level (any data written to the response stream blocks fallback), not at the semantic level (where it would require parsing). Implementation is a single boolean flag tracking whether anything has been written; the rule is auditable in a few lines of code.
- Provider plugins that cannot retrieve quota (`quotaStatus` returns null) are documented in their plugin header and in `docs/provider-caveats.md`. Soft triggers configured against such providers issue a startup warning so the user knows the trigger will never fire.
- Provider plugins that cannot retrieve quota (`quotaStatus` returns null) are documented in their plugin header and in `docs/provider-caveats.md` (📋 planned — not yet authored; until it exists, this information lives in the plugin header comment). Soft triggers configured against such providers issue a startup warning so the user knows the trigger will never fire.
- The deferred trigger types (deterministic, cost-aware) are tracked in spec §8 with explicit Q-tags. Adding them later is an ADR amendment plus a contract addition to the trigger taxonomy, not a redesign.
## Alternatives considered
+3 -1
View File
@@ -61,12 +61,14 @@ key = sha256(JSON.stringify({
**Per-model isolation.** Cache entries are keyed on `(provider, model)` pair. `anthropic/claude-sonnet-4-6` and `openai/gpt-5-codex` produce distinct cache entries for identical IR messages. There is no cross-model cache sharing in v1.0; this is intentional and correct.
**D1 — per-key isolation (ported from OCP v3.13.0).** Each OLP API key has an independent cache namespace. Cache directory structure:
**D1 — per-key isolation (ported from OCP v3.13.0).** Each OLP API key has an independent cache namespace. Designed file-backed layout (target for Phase 2 storage adapter):
```
~/.olp/cache/<olp-key-id>/<hash-prefix>/<hash>.json
```
The `<olp-key-id>` segment ensures per-key isolation; the `<hash-prefix>` is the first two hex chars of the key for filesystem-fanout sanity at high cache counts.
> **Implementation note (as of 2026-05-24):** The v0.1 implementation in `lib/cache/store.mjs` uses an in-memory `Map` as the backing store — no files are written to `~/.olp/cache/`. The file-backed layout described above is the designed shape; it transitions in via a Phase 2 storage adapter. Per-key isolation and singleflight (D4) are live; file persistence is not.
**D2 — `cache_control` bypass (ported, scope-expanded).** If the IR request contains Anthropic `cache_control` markers AND the active provider in the current chain hop is Anthropic, the OLP response cache is bypassed (Anthropic's own prompt cache is consulted at the provider). If the active provider is not Anthropic, the `cache_control` markers are stripped from the IR before provider translation (so they don't get passed to providers that wouldn't understand them) and a debug log entry is emitted. Future provider-specific bypass markers extend this rule by adding their own provider-conditional bypass logic.
**D3 — chunked stream replay (ported).** When a cache hit occurs on a `stream: true` request, the cached response is replayed as SSE chunks with the same chunking granularity as the original spawn. This requires storing the chunk boundaries (not just the concatenated content) in the cache entry. Cache entry format includes a `chunks[]` array, each with `delta` and `timestamp` relative to spawn start; replay throttles to the original timing pattern (configurable: real-time replay vs. burst-replay; default burst-replay because real-time replay adds latency without value for cached requests).