cold-audit catch from 2026-05-24 (round 3)
Three coordinated governance amendments per the major-decisions already
made (per "继续吧 unless major decision" + my F5/F11/F13+F14 option-(b)
calls earlier in the session). All P3-class, all docs-only. Single
PR per IDR cleanup-batch convention given the unified theme
("spec was aspirational; reality is X; amend spec to match").
Changes (3 docs files, +52 / -2):
1. docs/adr/0003-intermediate-representation.md — Amendment 1 (NEW
Amendments section, first ever for ADR 0003):
- F5 closure: removes the unimplemented `__irRoundTripTest()`
export-name claim from § Mitigations. The mental model
(symmetric irToNative+nativeToIR pair on each plugin) does NOT
fit the actual plugin shape (asymmetric spawn-wrappers:
request→CLI-args+stdin, response-stream→IR-chunks). Zero plugins
export this function.
- Documents the substitute test strategy that IS live at v0.1:
· Suite 3 covers entry-surface IR↔OpenAI round-trip
· Per-plugin spawn-with-mock test blocks cover IR→CLI→IR-chunk
· Lossy-translation edges documented inline in each plugin's
header comment (mistral.mjs DOCS-N markers being the most
thorough; anthropic.mjs + codex.mjs carry equivalent tables)
- Future plugins MUST satisfy both (a) spawn-with-mock test block
and (b) header lossy-field documentation — the enforcement
mechanism replacing the original export-name aspiration.
- Original § Mitigations bullet replaced with a pointer to
Amendment 1 (preserves history).
2. docs/adr/0005-cache-cross-provider.md — Amendment 5 (after D27
Amendment 4):
- F11 closure: acknowledges that the "Anthropic's own prompt cache
is consulted at the provider" half of § D2 is structurally
impossible at v0.1.
- Root cause: Anthropic plugin uses `claude -p --output-format text`
(verified at anthropic.mjs:196), a plain-text wire surface that
has no Messages-API field for cache_control markers. The markers
are also stripped at IR construction (openai-to-ir.mjs:45-89
whitelists fields, drops cache_control) per ADR 0003 IR design
reaffirmed in D27 Amendment 4 (F10).
- Clarifies v0.1 effective behavior: OLP-cache-bypass works
correctly (no double-caching when Anthropic + markers); the
delegate-to-Anthropic-prompt-cache half does not fire.
- Forward path (v1.x): switch Anthropic plugin to --output-format
json (NDJSON wire) or direct Messages API spawn — substantial
parser rewrite; deferred since no user has requested delegation.
- § D2 paragraph stays intact; an inline parenthetical reference
to Amendment 5 is added immediately after the affected sentence.
3. ALIGNMENT.md — new "Rule 4 exception class — Speculative-Candidate
Plugin" sub-section after Rule 5, before § Authorities:
- F13+F14 closure: formalizes the gap between strict ALIGNMENT
Rule 2 (no speculative shape assumptions) + Rule 4 (unalignable
plugins are deleted, not feature-flagged) and the actual practice
where Codex (D6) + Mistral (D8) plugins ship with explicit
UNPINNED assumptions documented in their headers, gated as
Candidate-not-Enabled.
- 5 precise conditions for a Speculative-Candidate plugin:
(1) STATIC_REGISTRY entry present, (2) candidate: true in
models-registry, (3) NOT in any user's providers.enabled config,
(4) header has explicit UNPINNED assumption section with labeled
IDs and planned-pin triggers, (5) defensive multi-shape parsers
tied to UNPINNED markers (greppable for future single-shape
replacement).
- Enablement criteria (Speculative-Candidate → Enabled): 3 explicit
requirements (remove UNPINNED labels from header; replace
multi-shape parsers with single-shape; file pin ADR amendment).
- Currently-in-class table:
· codex.mjs (D6) — A3 (auth token field name), A4 (NDJSON event
schema)
· mistral.mjs (D8) — A4 (JSON output event schema), A5 (model
flag), A6 (exact model IDs), A7 (streaming vs json output
mode), A8 (stdin prompt passing)
- Anthropic explicitly NOT in this class (CLI version pinned at
@anthropic-ai/claude-code v2.1.89 per Provider Authority Pins
table).
- CI enforcement noted as deferred (reviewer obligation today; a
future PR may add grep-based gate).
Pre-commit fold-in (per evidence-first checkpoint #4):
- **D31 reviewer flagged wording precision** ("Provider Inventory
table above" was structurally wrong — the table is BELOW the new
sub-section). Folded in: 1-word fix "above" → "below" on the
Speculative-Candidate condition #2.
Tests: 400/400 unchanged (docs-only).
Authority:
- ADR 0003 § Mitigations (modified) + new Amendment 1 (self-amendment)
- ADR 0005 § D2 (annotated) + new Amendment 5 (self-amendment)
- ALIGNMENT.md § Rules (extended with Rule 4 exception class)
- D27 F10 Amendment 4 of ADR 0005 (cited for cache_control IR-strip
precedent)
- CC 开发铁律 v1.6 § 10.x — Round-3 Cold Audit caught all 3 items
Reviewer (Iron Rule v1.6 § 10.x Mode A, fresh-context opus, independent
of drafter): APPROVE_WITH_MINOR. Verified:
- Suite 3 + 3 plugin spawn-with-mock blocks + 3 plugin lossy-field
header tables all present (F5 substitute test strategy claims
match implementation)
- anthropic.mjs:196 hardcodes --output-format text + openai-to-ir.mjs
drops cache_control from messages (F11 wire-limitation technically
accurate)
- All 8 UNPINNED assumption labels (codex A3/A4 + mistral A4/A5/A6/A7/A8)
match plugin header text exactly — no invention
- Anthropic-not-in-class claim verified against Provider Authority Pins
table
Follow-up items (reviewer's non-blocking notes, NOT in this PR):
1. **mistral.mjs A5 internal disconnect** — header lines 145-156 label
A5 as `UNPINNED-D-later-verifies`, but function body at 371-374
already cites DeepWiki enumeration as the pin and marks A5
`CONFIRMED-NOT-APPLICABLE` (no --model flag exists in vibe CLI).
The disconnect predates D31 and is a per-plugin header cleanup
(not a constitutional amendment), so it stays out of D31 scope per
IDR. File as separate follow-up issue — A5 should be moved out of
the Speculative-Candidate table once the header is updated.
2. **ADR 0005 Amendment ordering cosmetic** — strict reverse-chronological
would put Amendment 5 above Amendment 4 (current order is 4, 5, 3,
2 because both 4 and 5 share the 2026-05-24 date and 5 was inserted
after 4). Not blocking; future cleanup if maintainers want strict
numeric-descending.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Architecture Decision Records — OLP
This directory holds the OLP Architecture Decision Records (ADRs) — short documents that capture the why behind structural choices.
Read these before proposing governance, plug-in contract, IR, fallback, cache, or provider-inclusion changes.
Numbering
ADRs in OLP start at 0001 (the project's founding decision). OLP did not inherit the 0001 placeholder convention OCP used; the project starts on a fresh numbering line.
New ADRs increment from the highest existing number. Filenames are NNNN-<short-slug>.md.
Index
| ADR | Title | What it covers |
|---|---|---|
| 0001 | Project Founding | Why OLP exists (the 2026-06-15 Anthropic billing-split trigger), mission + non-mission boundaries, explicit supersession of OCP ADR 0005 "No Multi-Provider". |
| 0002 | Plugin Architecture for Providers | The lib/providers/<name>.mjs plug-in model, the Provider contract (name / models / auth / spawn / estimateCost / quotaStatus / healthCheck / hints), static in-tree registry, why-not full external plugin discovery. |
| 0003 | Intermediate Representation (IR) Design | The OLP-internal canonical request/response shape between the OpenAI-compat entry surface and each provider plugin. v1.0 IR fields, IR-vs-OpenAI-vs-native-provider three-shape model, IR is not exposed externally. |
| 0004 | Fallback Engine Semantics & Safety | Trigger taxonomy (Hard / Soft / Deterministic-deferred / Cost-aware-deferred), idempotent-failure safety (first-chunk rule), chain advancement one-at-a-time, observability headers. |
| 0005 | Cache Layer Cross-Provider Design | Cache key composition over (provider, model, messages, …), per-model isolation, D1+D2+D3+D4 port from OCP v3.13.0, cross-provider fallback cache behaviour (correct miss). |
| 0006 | Provider Inclusion / Exclusion + Risk-Tier Framework | The 4-tier classification (A excluded by default / B explicit consent / C opt-in / D eligible-for-default-enabled), Candidate-vs-Enabled distinction, current v0.1 candidate inventory (0 Enabled), Antigravity exclusion rationale (named prohibition + no cost advantage + reinstatement friction; pending primary-source pin), consent UX, future provider addition procedure. |
When to write a new ADR
Open one whenever:
- A structural rule is being added or changed (e.g., new IR field, new trigger type, new cache-key composition).
- A new provider plugin is being proposed (per ADR 0002 + ADR 0006 — ADR is a hard prerequisite for plugin merge).
- A decision encodes a lesson from an external event (provider policy change, drift incident).
- A future contributor reading the code alone could plausibly undo or re-litigate the choice.
Skip ADRs for routine implementation choices (algorithm pick, naming) — those belong in commit messages.
Format
Keep ADRs short — Context / Decision / Consequences / Alternatives is the standard skeleton. Cite incidents, PRs, or commits where useful. Length per ADR ~150–250 lines; longer than that, split.