docs(governance): fold in codex round-2 review findings (6 issues)

External Codex CLI review pass 2 surfaced 6 substantive issues that
round 1 fold-in missed — the self-consistency trap recurred when fold-in
was scoped only to files codex explicitly named in round 1. This commit
closes round 2 in full.

1. ADR 0002 contradicted ALIGNMENT.md (P1, codex round 2 finding 1)
   ADR 0002 still said "three default-enabled (Anthropic, OpenAI Codex,
   Mistral Vibe)" while ALIGNMENT.md (post round 1) said v0.1 ships zero
   Enabled Providers. Accepted ADR contradicted constitution.
   Fix: ADR 0002 + ADR 0001 + docs/adr/README.md index rewritten to
   Candidate framing.

2. release.yml would publish stale v0.1.0-bootstrap notes (P1, round 2
   finding 2)
   The "Unreleased" amendments would have been silently dropped on tag
   push because release.yml extracts only the matching version section.
   Fix: CHANGELOG restructured so the amended state IS the v0.1.0-
   bootstrap section. Full review history (opus + 2 codex rounds)
   captured inline.

3. package.json advertised non-existent entrypoints (P2, round 2
   finding 3)
   main/scripts.test/scripts.start pointed to files that do not exist.
   Local npm test and npm start failed; CI masked.
   Fix: remove all three from package.json. They return in Phase 1
   alongside the real files. test.yml bootstrap-tolerance updated to
   also skip when scripts.test is absent.

4. models-registry.json missing despite SPOT claim (P2, round 2
   finding 4)
   Fix: minimal stub committed (version + empty providers map).
   alignment.yml validator now actually runs.

5. alignment.yml commit-citation soft check Bash subshell trap (P2,
   round 2 finding 5)
   git log ... while read ... WARN=1 — the while loop ran in a subshell
   because of the pipe, so WARN never propagated out. The post-loop
   check always reported "clean" even when warnings fired.
   Fix: process substitution done less than less than (git log ...).

6. Tier A "permanent" wording inconsistent across ADR 0006 + alignment.
   yml workflow text (P3, round 2 finding 6)
   Fix: unified to "Excluded by default with no routine reinstatement
   path; re-inclusion requires ADR 0006 supersession or amendment with
   new primary-source evidence."

Reviewer: OpenAI Codex CLI (external, fresh-context, pass 2). Iron Rule
10 satisfied — round 2 reviewer was not the implementer of round 1
fold-in.

Memory learning updated: the self-consistency trap recurs in the fold-in
step. Future fold-ins must grep the entire repo for the concept, not
only edit files the reviewer named. See learnings/ai_reviewer_self_
consistency_trap.md in cross-machine memory.

Co-Authored-By: Claude Opus 4.7 (noreply@anthropic.com)
This commit is contained in:
2026-05-23 16:35:23 +10:00
co-authored by Claude Opus 4.7 (noreply@anthropic.com)
parent 91223ee9ab
commit dff428f3d0
9 changed files with 78 additions and 59 deletions
+14 -6
View File
@@ -89,7 +89,7 @@ jobs:
for token in "${FORBIDDEN_PROVIDER_TOKENS[@]}"; do for token in "${FORBIDDEN_PROVIDER_TOKENS[@]}"; do
HITS="$(echo "$SOURCE_FILES" | xargs grep -n -F "$token" 2>/dev/null || true)" HITS="$(echo "$SOURCE_FILES" | xargs grep -n -F "$token" 2>/dev/null || true)"
if [ -n "$HITS" ]; then if [ -n "$HITS" ]; then
echo "::error::Tier-A-excluded provider token '$token' detected in OLP source. Per ALIGNMENT.md / ADR 0006, this provider is permanently excluded." echo "::error::Tier-A-excluded provider token '$token' detected in OLP source. Per ALIGNMENT.md / ADR 0006, this provider is excluded by default; re-inclusion requires ADR 0006 supersession/amendment with new primary-source evidence."
echo "$HITS" echo "$HITS"
FAIL=1 FAIL=1
fi fi
@@ -101,7 +101,7 @@ jobs:
echo "ALIGNMENT GUARDRAIL FAILURE" echo "ALIGNMENT GUARDRAIL FAILURE"
echo "============================================================" echo "============================================================"
echo "OLP source contains a token on the alignment blacklist or" echo "OLP source contains a token on the alignment blacklist or"
echo "references a permanently excluded provider." echo "references a Tier-A-excluded provider."
echo "" echo ""
echo "Blacklist tokens were introduced by LLM hallucinations and" echo "Blacklist tokens were introduced by LLM hallucinations and"
echo "do not appear in the relevant authority (provider CLI," echo "do not appear in the relevant authority (provider CLI,"
@@ -110,8 +110,10 @@ jobs:
echo "record at https://github.com/dtzp555-max/ocp." echo "record at https://github.com/dtzp555-max/ocp."
echo "" echo ""
echo "Excluded providers are listed in ALIGNMENT.md \xc2\xa7 Risk Tier" echo "Excluded providers are listed in ALIGNMENT.md \xc2\xa7 Risk Tier"
echo "Framework and ADR 0006. Permanent exclusion means not" echo "Framework and ADR 0006. Tier-A exclusion means not"
echo "bundled, not pluggable, not added via opt-in." echo "bundled, not pluggable, not added via opt-in;"
echo "re-inclusion requires ADR 0006 amendment with new"
echo "primary-source evidence."
echo "" echo ""
echo "Required action:" echo "Required action:"
echo " 1. Remove the token from source." echo " 1. Remove the token from source."
@@ -191,8 +193,14 @@ jobs:
exit 0 exit 0
fi fi
# Use process substitution `< <(...)` rather than piping into the
# while loop. A piped while runs in a subshell, so `WARN=1` would
# never propagate back out to this scope — the if-check below would
# always report "clean" even when warnings were emitted. Classic
# Bash subshell trap; see commit history for the codex review that
# caught this.
WARN=0 WARN=0
git log --format="%H" "${BASE_SHA}..${HEAD_SHA}" | while read -r sha; do while read -r sha; do
BODY="$(git log -1 --format=%B "$sha")" BODY="$(git log -1 --format=%B "$sha")"
if echo "$BODY" | grep -E -i -q '(provider|claude|codex|vibe|grok|kimi|minimax|glm|qwen|cli)[[:space:]]+(code[[:space:]]+)?uses'; then if echo "$BODY" | grep -E -i -q '(provider|claude|codex|vibe|grok|kimi|minimax|glm|qwen|cli)[[:space:]]+(code[[:space:]]+)?uses'; then
if echo "$BODY" | grep -E -i -q '(cli[[:space:]]+v[0-9]+|https?://|ADR[[:space:]]+[0-9]{4})'; then if echo "$BODY" | grep -E -i -q '(cli[[:space:]]+v[0-9]+|https?://|ADR[[:space:]]+[0-9]{4})'; then
@@ -202,7 +210,7 @@ jobs:
WARN=1 WARN=1
fi fi
fi fi
done done < <(git log --format="%H" "${BASE_SHA}..${HEAD_SHA}")
if [ "$WARN" -ne 0 ]; then if [ "$WARN" -ne 0 ]; then
echo "Soft check raised warnings. Reviewer: please enforce per CLAUDE.md." echo "Soft check raised warnings. Reviewer: please enforce per CLAUDE.md."
+6 -6
View File
@@ -46,12 +46,12 @@ jobs:
- name: Run npm test - name: Run npm test
shell: bash shell: bash
run: | run: |
# Bootstrap tolerance: if test-features.mjs does not exist yet (Phase 0 # Bootstrap tolerance: skip if either test-features.mjs is absent OR
# ships before Phase 1 lands the test harness), skip with a notice. # package.json has no scripts.test entry. v0.1 founding ships
# The `npm test` script is configured in package.json from day one, so # neither — both land with Phase 1 per spec §6. Once one or both
# checking script presence is not a useful gate — the file must exist. # are present, this guard falls through to `npm test`.
if [ ! -f test-features.mjs ]; then if [ ! -f test-features.mjs ] || ! node -e "p=require('./package.json');process.exit(p.scripts&&p.scripts.test?0:1)" 2>/dev/null; then
echo "::notice::test-features.mjs not present yet (Phase 0 bootstrap phase). Skipping. Test harness lands with Phase 1 per docs/adr/0001 / spec §6." echo "::notice::Phase 0 bootstrap: test-features.mjs absent OR scripts.test not declared in package.json. Skipping. Both land with Phase 1 per docs/adr/0001 / spec §6."
exit 0 exit 0
fi fi
npm test npm test
+48 -37
View File
@@ -2,57 +2,68 @@
All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this file is the source of truth for GitHub release notes. All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this file is the source of truth for GitHub release notes.
## Unreleased — 2026-05-23 (governance amendments per external codex review)
External AI review (OpenAI Codex CLI) of the bootstrap governance surfaced six substantive findings beyond what the internal opus reviewer caught. All six folded in this turn:
1. **Provider Inventory split into Candidate vs Enabled** — ALIGNMENT.md previously listed `anthropic` / `openai` / `mistral` as Tier D default-enabled while their Authority pins were still `TBD at Phase N spawn`. This violated Rule 1 (Cite First) and Rule 3 (Match the Implementation). The v0.1 founding commit now ships **zero Enabled Providers**; all 8 providers are Candidate. Enablement is a Phase audit deliverable, not a bootstrap claim. (ALIGNMENT.md § Provider Inventory; README.md § Supported Providers.)
2. **Antigravity Tier A evidence strength downgraded to "evidence-backed, pending primary-source pin"** — ADR 0006 previously framed the Antigravity exclusion as a closed case based on secondary reports. The reports actually disagree on blast radius (piunikaweb 03-02 says AI-tier only; piunikaweb 02-23, OpenClaw issue #14203, VentureBeat say broader). The Google FAQ language naming OpenClaw/OpenCode/Claude Code is cited from secondary sources only; the original FAQ URL or archival snapshot has not been primary-source-pinned. The exclusion is still active by default, but the constitutional weight now matches the evidence: secondary-sourced. Primary-source pinning is tracked as an open one-shot audit task with a 90-day Tier-reconsideration trigger.
3. **ADR 0001 supersession scope honesty** — ADR 0001 previously claimed OLP is "the structural shape ADR 0005 endorsed: a separate repo with multi-provider design baked in from day one." But ADR 0005's separate-repo recommendation came with two qualifiers OLP rejects: "BYOK from day one" and "no `cli.js` spawn." OLP rejects both — it is non-commercial and explicitly spawn-binary. The supersession is now narrowly scoped to "single-provider-sufficiency premise only"; the BYOK / no-spawn parts of ADR 0005 are not inherited.
4. **Anthropic post-2026-06-15 one-shot audit scheduled** — ALIGNMENT.md's annual 14 May audit would have left the Anthropic Tier re-evaluation almost a year late. Added a one-shot audit for 2026-06-16 (or first Anthropic billing-cycle close) that verifies the post-effective-date behaviour and updates ADR 0006 + Authority pin.
5. **Tier A "permanent" language unified across docs** — ALIGNMENT.md and ADR 0006 disagreed: one said "permanently excluded," the other said "amendment-procedure-revisable." Unified as "Excluded by default. Cannot be re-included unless ADR 0006 is superseded or amended with new primary-source evidence." The amendment procedure remains available; "Tier A" sets the bar for re-inclusion at constitutional-amendment level, not at routine PR level.
6. **OpenAI Tier D wording softened** — ADR 0006 previously described Codex Discussion #8338 as "maintainer confirmed permissive." The discussion is actually a maintainer posture statement ("OSS projects like OpenCode are doing things similar") with an explicit "I'm an engineer, not a lawyer" caveat. Now described as "maintainer signal indicates low risk; formal ToS pin pending" with the pin tracked as a follow-up audit task.
Files changed: `ALIGNMENT.md`, `README.md`, `docs/adr/0001-project-founding.md`, `docs/adr/0006-provider-inclusion.md`. No code, no CI workflow, no PR template change.
Reviewer for this amendment: OpenAI Codex CLI (external, fresh-context). Iron Rule 10 satisfied — the internal opus reviewer was not the source of the findings, and the maintainer is not the author of the underlying critique. The amendment's substantive changes are direct fold-ins of the reviewer's six findings; the internal opus reviewer's earlier APPROVE_WITH_MINOR verdict is therefore narrowed retroactively to "APPROVE conditional on these amendments" for the purposes of the v0.1 governance bootstrap.
## v0.1.0-bootstrap — 2026-05-23 ## v0.1.0-bootstrap — 2026-05-23
### Phase 0 — Repo bootstrap ### Phase 0 — Repo bootstrap (founding + post-codex-review hardening)
This is the founding commit of OLP (Open LLM Proxy), a personal- and family-scale multi-provider LLM proxy that supersedes OCP. The trigger was Anthropic's 2026-05-14 announcement (effective 2026-06-15) splitting `claude -p` / Agent SDK / third-party agent traffic out of the Pro/Max subscription pool into a separate fixed monthly Agent SDK Credit pool. This is the founding commit set of OLP (Open LLM Proxy), a personal- and family-scale multi-provider LLM proxy that supersedes OCP. The trigger was Anthropic's 2026-05-14 announcement (effective 2026-06-15) splitting `claude -p` / Agent SDK / third-party agent traffic out of the Pro/Max subscription pool into a separate fixed monthly Agent SDK Credit pool.
**What lands in this commit:** **What lands at v0.1.0-bootstrap (final state on `main` as of 2026-05-23):**
- `ALIGNMENT.md` — OLP constitution. Three concurrent authorities (per-provider CLI / OpenAI spec / IR contract), 5 Rules, 4-tier Risk Tier Framework, 8-provider inventory. - `ALIGNMENT.md` — OLP constitution. Three concurrent authorities (per-provider CLI / OpenAI spec / IR contract), 5 Rules, 4-tier Risk Tier Framework, Candidate-vs-Enabled provider inventory, one-shot triggered audits (2026-06-16 Anthropic post-split; 90-day Antigravity primary-source pin).
- `AGENTS.md` — multi-tool agent guidelines (inherits `~/.cc-rules/AGENTS.md`). - `AGENTS.md` — multi-tool agent guidelines (inherits `~/.cc-rules/AGENTS.md`).
- `CLAUDE.md` — Claude-Code-specific session instructions + machine-readable `release_kit` overlay (Iron Rule 5.5). - `CLAUDE.md` — Claude-Code-specific session instructions + machine-readable `release_kit` overlay (Iron Rule 5.5).
- `README.md` — phase-aware skeleton with provider inventory, API endpoint table, environment-variables table, response-headers spec, architecture overview, phase plan, migration-from-OCP outline. Placeholder content marked as such per phase. - `README.md` — phase-aware skeleton with Candidate-vs-Enabled provider tables, API endpoint table, environment-variables table, response-headers spec, architecture overview, phase plan, migration-from-OCP outline. Placeholder content marked as such per phase.
- `docs/adr/` — 6 founding ADRs: - `docs/adr/` — 6 founding ADRs:
- `0001-project-founding.md` — Mission, non-mission, and supersession of OCP ADR 0005 (No Multi-Provider). - `0001-project-founding.md` — Mission, non-mission, narrow-scope supersession of OCP ADR 0005 (single-provider-sufficiency premise only; BYOK / no-spawn parts of ADR 0005 not inherited).
- `0002-plugin-architecture.md``lib/providers/<name>.mjs` plug-in model with the Provider contract (name / models / auth / spawn / estimateCost / quotaStatus / healthCheck / hints). - `0002-plugin-architecture.md``lib/providers/<name>.mjs` plug-in model with the Provider contract (name / models / auth / spawn / estimateCost / quotaStatus / healthCheck / hints). 8 candidate providers declared, 0 Enabled at v0.1.
- `0003-intermediate-representation.md` — OLP-internal canonical IR between OpenAI-compat entry and provider plugins. - `0003-intermediate-representation.md` — OLP-internal canonical IR between OpenAI-compat entry and provider plugins.
- `0004-fallback-engine.md` — Trigger taxonomy (Hard / Soft / Deterministic-deferred / Cost-aware-deferred), idempotent-failure safety, first-chunk rule, chain advancement. - `0004-fallback-engine.md` — 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-cross-provider.md` — Cache key composition over `(provider, model, messages, ...)`, D1+D2+D3+D4 port from OCP v3.13.0. - `0005-cache-cross-provider.md` — Cache key composition over `(provider, model, messages, ...)`, D1+D2+D3+D4 port from OCP v3.13.0.
- `0006-provider-inclusion.md` — 4-tier Risk Framework, 8-provider classification, Antigravity exclusion (named prohibition + no cost advantage + reinstatement friction; *not* whole-account ban — Google AI services tier only per piunikaweb 2026-03-02 OpenClaw exec confirmation). - `0006-provider-inclusion.md` — 4-tier Risk Framework, Candidate-vs-Enabled distinction, 8-provider candidate classification, Antigravity Tier A (evidence-backed, pending primary-source pin) — exclusion rests on (named prohibition + no cost advantage + reinstatement friction) combination; primary-source URL not yet pinned, follow-up tracked.
- `.github/PULL_REQUEST_TEMPLATE.md` — 8-radio Change Type taxonomy + per-type Authority Evidence sections + Iron Rule 10 reviewer checklist. - `.github/PULL_REQUEST_TEMPLATE.md` — 8-radio Change Type taxonomy + per-type Authority Evidence sections + Iron Rule 10 reviewer checklist.
- `.github/workflows/alignment.yml` — CI blacklist (transitive `api.anthropic.com/api/oauth/usage` from OCP 2026-04-11 drift; Antigravity provider exclusion enforcement) + `models-registry.json` validator + commit-citation soft check. - `.github/workflows/alignment.yml` — CI blacklist (transitive `api.anthropic.com/api/oauth/usage` from OCP 2026-04-11 drift; Antigravity provider exclusion enforcement) + `models-registry.json` validator + commit-citation soft check (process-substitution form, no Bash subshell trap).
- `.github/workflows/release.yml` — Auto-release on tag push with `package.json`-vs-tag version match check (Iron Rule 5). - `.github/workflows/release.yml` — Auto-release on tag push with `package.json`-vs-tag version match check (Iron Rule 5).
- `.github/workflows/test.yml` — Node 20/24 matrix; tolerates bootstrap-phase absence of `test-features.mjs`. - `.github/workflows/test.yml` — Node 20/24 matrix; tolerates bootstrap-phase absence of `test-features.mjs` AND `scripts.test`.
- `package.json`, `.gitignore`, `LICENSE` (MIT), `CHANGELOG.md` — standard project boilerplate. - `models-registry.json` — minimal v0.1 stub with empty `providers: {}`, matching the 0-Enabled posture; populated by Phase audits as providers transition Candidate → Enabled.
- `package.json` — minimal: no `main`, no `scripts.test`, no `scripts.start` (those entries land alongside the real files in Phase 1).
- `.gitignore`, `LICENSE` (MIT), `CHANGELOG.md` — standard project boilerplate.
**Provider inventory at bootstrap:** **Provider posture at v0.1.0-bootstrap (per ALIGNMENT.md § Provider Inventory):**
| Tier | Providers | | Tier | Anticipated providers | v0.1 default state |
|---|---| |---|---|---|
| D (default-enabled) | Anthropic, OpenAI Codex, Mistral Vibe | | D (eligible-for-default-enabled) | Anthropic, OpenAI Codex, Mistral Vibe | Candidate (transition gate: authority pin + plugin + Phase audit) |
| C (opt-in, no consent) | xAI Grok, Moonshot Kimi | | C (opt-in) | xAI Grok, Moonshot Kimi | Candidate |
| B (opt-in, explicit consent) | MiniMax, Zhipu GLM, Alibaba Qwen | | B (opt-in + consent) | MiniMax, Zhipu GLM, Alibaba Qwen | Candidate |
| A (permanently excluded) | Google Antigravity | | A (excluded by default; constitutional-amendment-only re-inclusion) | Google Antigravity | Excluded; pending primary-source pin |
**Governance gate at bootstrap:** **Total Enabled at v0.1.0-bootstrap: 0.** Enablement is a Phase audit deliverable, not a bootstrap claim. This explicit zero is intentional and codified — a constitution that names providers as "default-enabled" while their CLI versions, output shapes, auth artifacts, and exit-code semantics are still TBD would violate Rules 1 (Cite First) and 3 (Match the Implementation).
- Fresh-context independent reviewer (opus, Iron Rule 10) audited all 15 governance files against the OLP v0.1 spec and OCP precedent. Verdict: APPROVE_WITH_MINOR. Two minor findings folded in before this commit (alignment.yml heredoc indentation fix; AGENTS.md ADR-0003 reference clarification). **Review history for this version:**
**Next:** Phase 1 lands `server.mjs` skeleton + IR + Anthropic provider plugin + cache D1+D4 port from OCP. Per the spec §6 phase plan. 1. **Initial internal review (Claude Opus, fresh-context, Iron Rule 10).** Verdict: APPROVE_WITH_MINOR — 2 minor items (alignment.yml heredoc indent breaking bash parse on failure path; AGENTS.md cross-reference to ADR 0003 imprecise). Both folded in before the founding commit.
2. **External review #1 (OpenAI Codex CLI, no spec framing).** Verdict: 6 substantive findings beyond internal review.
- Provider Inventory split into Candidate vs Enabled (the v0.1 constitution had declared `anthropic` / `openai` / `mistral` as Tier D default-enabled while their Authority pins were still `TBD at Phase N spawn` — direct violation of Rule 1 / Rule 3 against the constitution's own text).
- Antigravity Tier A downgraded to "evidence-backed, pending primary-source pin" (secondary reports disagree on blast radius; Google FAQ URL not yet primary-source-pinned).
- ADR 0001 supersession scope narrowed (OLP rejects ADR 0005's "BYOK + no spawn" qualifiers, which originally applied to a commercial pivot; OLP is non-commercial and spawn-binary by design).
- Anthropic post-2026-06-15 one-shot audit scheduled (annual May 14 audit would leave Anthropic re-eval ~year late after the split takes effect).
- Tier A "permanent" language unified across docs (constitution and ADR 0006 had disagreed).
- OpenAI Tier D wording softened ("maintainer signal indicates low risk; formal ToS pin pending" — Discussion #8338 is a posture statement, not a formal ToS blessing).
3. **External review #2 (OpenAI Codex CLI, second pass after review #1 fold-in).** Verdict: 6 additional substantive findings — the self-consistency trap recurred when fold-in of review #1 was scoped only to files codex explicitly named. Round #2 caught:
- ADR 0002 still claimed "three default-enabled" while ALIGNMENT.md said zero Enabled — accepted ADR contradicting constitution.
- `release.yml` would publish stale `## v0.1.0-bootstrap` notes that ignored the "Unreleased" amendments — fixed by consolidating amendments into the v0.1.0-bootstrap section (this entry).
- `package.json` advertised `main` / `scripts.test` / `scripts.start` for files that don't exist — `npm test` / `npm start` failed locally. Removed all three; will return in Phase 1 alongside the real files.
- `models-registry.json` documented as SPOT but missing — minimal stub added.
- `alignment.yml` commit-citation soft check had a Bash subshell trap (`while` in pipe loses `WARN=1` mutation) — fixed via process substitution `< <(...)`.
- Tier A "permanent" wording still inconsistent across `alignment.yml` workflow text, ADR 0006 Consequences section, and the rest of the docs — unified throughout.
All 6 round-#2 findings folded in this consolidated v0.1.0-bootstrap state.
**Reviewer framing learning (recorded permanently in `~/.cc-rules/memory/learnings/ai_reviewer_self_consistency_trap.md`):** Internal AI reviewers framed on a shared source-of-truth miss bugs in the source-of-truth itself. The self-consistency trap recurred during the fold-in of round #1 — when an external reviewer surfaces findings, the fold-in must grep the entire repo for the same concept, not only edit the files the reviewer named. Round #2 caught what round #1's fold-in missed for exactly this reason. Both lessons updated in the cross-machine memory.
**Iron Rule 10 status:** Satisfied. Initial reviewer = internal opus (independent from drafters). Round #1 reviewer = external codex (independent from drafters and from internal opus). Round #2 reviewer = external codex (independent from the round #1 fold-in implementer). The maintainer's role across all three reviews was approver, not author. The drafting agents and fold-in agents were never the same as the reviewers for any of the three passes.
**Next:** Phase 1 lands `server.mjs` skeleton + IR + Anthropic provider plugin + cache D1+D4 port from OCP. At that point, `package.json` regains `main` + `scripts.test` + `scripts.start`, `test-features.mjs` lands, `models-registry.json` populates its first `providers.anthropic` entry, and Anthropic transitions Candidate → Enabled. Per spec §6 phase plan.
+1 -1
View File
@@ -23,7 +23,7 @@ Found OLP (Open LLM Proxy) as a new project, separate from OCP, with the followi
**Non-mission (explicit).** Per spec §1, OLP is **not**: **Non-mission (explicit).** Per spec §1, OLP is **not**:
- A commercial multi-tenant SaaS. Helicone, OpenRouter, LiteLLM, Portkey, Cloudflare AI Gateway already serve that market with funding, SOC2, dashboards, and team features. OLP enters none of those races. - A commercial multi-tenant SaaS. Helicone, OpenRouter, LiteLLM, Portkey, Cloudflare AI Gateway already serve that market with funding, SOC2, dashboards, and team features. OLP enters none of those races.
- A generic enterprise AI gateway competing on provider breadth. The provider set is intentionally narrow (currently 3 default + 2 optional tier-1 + 3 optional tier-2) and curated by subscription economics, not by "more is better." - A generic enterprise AI gateway competing on provider breadth. The candidate provider set is intentionally narrow (8 total: 3 anticipated Tier D + 2 anticipated Tier C + 3 anticipated Tier B; v0.1 founding ships 0 Enabled per ALIGNMENT.md § Provider Inventory) and curated by subscription economics, not by "more is better."
- A model-capability router. OLP does not auto-route to "the smartest model"; the user picks the model explicitly per chain in `config.routing.chains[]`. Capability routing is a separate problem with separate failure modes and is out of scope for v1.0 and beyond. - A model-capability router. OLP does not auto-route to "the smartest model"; the user picks the model explicitly per chain in `config.routing.chains[]`. Capability routing is a separate problem with separate failure modes and is out of scope for v1.0 and beyond.
- A conversation-state store. Memory and continuity are client-side concerns (Memory Continuity, Hermes equivalents, IDE-side context). OLP is a pure stateless proxy. - A conversation-state store. Memory and continuity are client-side concerns (Memory Continuity, Hermes equivalents, IDE-side context). OLP is a pure stateless proxy.
+2 -2
View File
@@ -7,7 +7,7 @@
## Context ## Context
OLP supports a curated set of providers — three default-enabled (Anthropic, OpenAI Codex, Mistral Vibe) plus two optional tier-1 (xAI Grok, Moonshot Kimi) and three optional tier-2 (MiniMax, Zhipu GLM, Alibaba Qwen). Each provider has its own CLI binary, its own auth artifact location, its own request shape, its own response shape, its own quota-reporting endpoint (or none), and its own rate-limit posture. The maintainer's strong prior is that this set grows over the project's lifetime — provider economics will continue to shift, and "the right five providers" in 2027 will not be identical to today's five. OLP declares a curated set of candidate providers — three anticipated Tier D (Anthropic, OpenAI Codex, Mistral Vibe), two anticipated Tier C (xAI Grok, Moonshot Kimi), and three anticipated Tier B (MiniMax, Zhipu GLM, Alibaba Qwen). Per ALIGNMENT.md § Provider Inventory, all 8 ship as **Candidate** at v0.1 founding; transition to **Enabled** requires authority pin filled + plugin landed + Phase audit passed. Each provider has its own CLI binary, its own auth artifact location, its own request shape, its own response shape, its own quota-reporting endpoint (or none), and its own rate-limit posture. The maintainer's strong prior is that this set grows over the project's lifetime — provider economics will continue to shift, and "the right five providers" in 2027 will not be identical to today's five.
The naive architecture is a monolithic dispatcher inside `server.mjs`: The naive architecture is a monolithic dispatcher inside `server.mjs`:
@@ -86,7 +86,7 @@ Every provider plugin exports an object conforming to:
## Alternatives considered ## Alternatives considered
**(a) Monolithic dispatch inside `server.mjs`.** A single function with `if/else if` per provider, each branch implementing spawn/quota/health inline. Rejected: this is the architectural shape that produced OCP's `server.mjs` length problem at *one* provider, and it does not survive contact with three default + two optional tier-1 + three optional tier-2 providers (eight code paths). Worse, it makes provider-disable a code change, which means fast-quarantine in response to a ToS announcement (spec §9) is a release event rather than a config flip. **(a) Monolithic dispatch inside `server.mjs`.** A single function with `if/else if` per provider, each branch implementing spawn/quota/health inline. Rejected: this is the architectural shape that produced OCP's `server.mjs` length problem at *one* provider, and it does not survive contact with 8 candidate providers (anticipated 3 D + 2 C + 3 B, eight code paths once they all transition from Candidate to Enabled). Worse, it makes provider-disable a code change, which means fast-quarantine in response to a ToS announcement (spec §9) is a release event rather than a config flip.
**(b) Full external plugin discovery (npm-installable, runtime-loaded, hot-discoverable).** Plugins are npm packages; OLP scans `node_modules/@olp-providers/*` at startup; users `npm install` to add a provider. Rejected for v1.0 on three grounds: (1) the provider set is curated for ToS-risk reasons (ADR 0006), and "anyone can install any provider" defeats that curation; (2) the discovery layer is itself non-trivial code (manifest validation, version compatibility, security review of third-party plugin code) that does not earn its complexity at three to eight providers; (3) the contract has not stabilized enough — locking it as a stable plugin API before v1.0 ships is premature commitment. **(b) Full external plugin discovery (npm-installable, runtime-loaded, hot-discoverable).** Plugins are npm packages; OLP scans `node_modules/@olp-providers/*` at startup; users `npm install` to add a provider. Rejected for v1.0 on three grounds: (1) the provider set is curated for ToS-risk reasons (ADR 0006), and "anyone can install any provider" defeats that curation; (2) the discovery layer is itself non-trivial code (manifest validation, version compatibility, security review of third-party plugin code) that does not earn its complexity at three to eight providers; (3) the contract has not stabilized enough — locking it as a stable plugin API before v1.0 ships is premature commitment.
+1 -1
View File
@@ -83,7 +83,7 @@ The inclusion ADR is a hard prerequisite for the plugin's merge — no ADR, no m
**Negative** **Negative**
- Tier B's consent UX adds a step to first-enable. Users who already understand the risk perceive friction. The friction is intentional; the consent is the structural mechanism that protects the user. - Tier B's consent UX adds a step to first-enable. Users who already understand the risk perceive friction. The friction is intentional; the consent is the structural mechanism that protects the user.
- The framework is provider-by-provider, not category-by-category. A new Chinese provider similar to MiniMax/GLM/Qwen gets its own ADR even though the pattern is shared. This is intentional — boilerplate-and-paste ADRs are still cheaper than the alternative of "we just classed them together once and now we have a category drift problem when their ToS shifts." - The framework is provider-by-provider, not category-by-category. A new Chinese provider similar to MiniMax/GLM/Qwen gets its own ADR even though the pattern is shared. This is intentional — boilerplate-and-paste ADRs are still cheaper than the alternative of "we just classed them together once and now we have a category drift problem when their ToS shifts."
- Tier-A exclusion is *permanent* in the current framework, with no documented reinstatement path. If Google were to walk back the named-tool prohibition and the cost picture changed, Antigravity would need a fresh ADR superseding this one. The framework deliberately makes Tier A "needs a new decision to revisit," not "auto-reconsidered each release." - Tier-A exclusion has **no routine reinstatement path** — re-inclusion requires this ADR to be superseded or amended with new primary-source evidence (per the Tier-A definition above). If Google were to walk back the named-tool prohibition and the cost picture changed, the path is "draft an ADR amendment citing the new primary-source evidence," not a routine config flip. The framework deliberately makes Tier A "needs a constitutional-level decision to revisit," not "auto-reconsidered each release." This is procedurally stricter than "permanent" (the amendment procedure is always available) but practically equivalent — the bar is constitutional, not operational.
**Mitigations** **Mitigations**
- The README "Supported Providers" table is the user's first stop and surfaces tiers prominently. The dashboard (spec §4.6) shows tier per enabled provider so users see it on every dashboard load, not only at enable-time. - The README "Supported Providers" table is the user's first stop and surfaces tiers prominently. The dashboard (spec §4.6) shows tier per enabled provider so users see it on every dashboard load, not only at enable-time.
+1 -1
View File
@@ -19,7 +19,7 @@ New ADRs increment from the highest existing number. Filenames are `NNNN-<short-
| [0003](0003-intermediate-representation.md) | 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. | | [0003](0003-intermediate-representation.md) | 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](0004-fallback-engine.md) | 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. | | [0004](0004-fallback-engine.md) | 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](0005-cache-cross-provider.md) | 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). | | [0005](0005-cache-cross-provider.md) | 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](0006-provider-inclusion.md) | Provider Inclusion / Exclusion + Risk-Tier Framework | The 4-tier classification (A excluded / B explicit consent / C opt-in / D default-enabled), current v0.1 inventory, Antigravity exclusion rationale (named prohibition + no cost advantage + reinstatement friction), consent UX, future provider addition procedure. | | [0006](0006-provider-inclusion.md) | 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 ## When to write a new ADR
+5
View File
@@ -0,0 +1,5 @@
{
"version": "0.1.0-bootstrap",
"comment": "OLP models registry — SPOT for (provider, model) → metadata per CLAUDE.md release_kit overlay. v0.1 founding ships zero Enabled Providers per ALIGNMENT.md § Provider Inventory, so 'providers' is empty. Each Phase audit that transitions a Candidate to Enabled populates its provider's entry here. Schema validated by .github/workflows/alignment.yml; provider keys must match ALIGNMENT.md inventory.",
"providers": {}
}
-5
View File
@@ -3,11 +3,6 @@
"version": "0.1.0-bootstrap", "version": "0.1.0-bootstrap",
"description": "Personal multi-provider LLM proxy. Successor to OCP. One HTTP endpoint, multiple subscriptions behind it, automatic routing + fallback + caching.", "description": "Personal multi-provider LLM proxy. Successor to OCP. One HTTP endpoint, multiple subscriptions behind it, automatic routing + fallback + caching.",
"type": "module", "type": "module",
"main": "server.mjs",
"scripts": {
"test": "node test-features.mjs",
"start": "node server.mjs"
},
"engines": { "engines": {
"node": ">=18" "node": ">=18"
}, },