mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-21 21:15:10 +00:00
f9f2eaa059623e9f1664589cb86fee6abdee29a1
7
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e87b6b73ec |
release(phase-2-close): v0.2.0 — multi-key auth + audit + owner gating + keygen CLI (D43-A → D47) (#24)
Closes Phase 2. All 11 ADR 0007 § 10 acceptance criteria shipped + tested
in main across 6 D-day commits (D43-A doc cleanup, D43-B ADR 0007 ratify,
D44 lib/keys.mjs core, D45 server.mjs auth integration + lib/audit.mjs,
D46 owner gating /health + X-OLP-Fallback-Detail, D47 bin/olp-keys.mjs
keygen CLI). Test count 468 (v0.1.1) → 544 (v0.2.0).
Per CLAUDE.md release_kit.phase_close_trigger this PR is the explicit
maintainer-triggered close action.
CHANGES IN THIS COMMIT (release-kit machinery only — no code):
package.json:
- version 0.1.1 → 0.2.0
CLAUDE.md release_kit.phase_rolling_mode:
- current_phase: Phase 2 → Phase 3
- current_pre_release_identifier: "0.2.0-phase2" → "0.3.0-phase3"
CHANGELOG.md:
- Unreleased promoted to "## v0.2.0 — 2026-05-25" with the D43-A
→ D47 entries intact (already accumulated under release_kit
phase_rolling_mode discipline during Phase 2 D-days).
- New Phase 2 release_kit checklist + ADR 0007 § 10 acceptance
criteria final-ship table + known-limitations-beyond-v0.2.0.
- New "## Unreleased\n\n(empty — Phase 3 entries land here once
Phase 3 opens)" sentinel for the next phase. D37
phase_rolling_mode gate will pass (sentinel-only Unreleased).
README.md:
- Status header v0.1.1 → v0.2.0; Phase 1+2 shipped; Phase 3 next.
- Implementation status note dated post-v0.2.0; reflects Phase 2
close.
- Phase plan Phase 2 promoted to ✅ Shipped; Phase 3 marked (next).
Test count 544 / 544 pass (npm test verified locally; no test or .mjs
file touched in this release commit).
NEXT STEPS (post-merge, auto-triggered):
- git tag v0.2.0 + git push --tags
- release.yml fires: phase_rolling_mode gate passes (Unreleased is
sentinel-only) + GitHub Release auto-published from the CHANGELOG
v0.2.0 section.
ACKNOWLEDGEMENTS:
- Phase 2 was executed under the maintainer's standing autopilot
grant (~/.cc-rules/memory/auto/standing_autopilot_phase_2.md,
cc-rules bf0ed9a); D-day cadence: 6 implementation D-days +
multiple opus-reviewer fold-ins, all in a single session.
- ADR 0007 was authored via D43-B with maintainer text review on
top of fresh-context opus review (4 findings: 1 P1 safety + 2 P2
+ 1 P3) folded in before ratification.
Authority:
- CLAUDE.md release_kit overlay phase_rolling_mode (Iron Rule 5.5)
governs this commit's shape; phase_close_trigger requires explicit
maintainer action — the user issued "go" to trigger.
- ADR 0007 (multi-key auth) — the Phase 2 design contract;
acceptance criteria #1–#11 covered.
- CC 开发铁律 v1.6 § 10 — fresh-context opus reviewer required for
every implementation phase + design ADR (executed on D44, D45,
D46, D47, and D43-B with double-review).
Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
|
||
|
|
939f3e6bd9 |
feat+test+docs: D47 — bin/olp-keys.mjs keygen CLI (Phase 2 functional scope closes) (#23)
Fourth Phase 2 implementation D-day. Closes ADR 0007 § 10 acceptance criterion #9 (bootstrap workflow must be reproducible without manual file editing) by shipping a minimal keygen CLI per § 9.1. Phase 2 functional scope is complete with this D-day — remaining work is Phase 2 close → v0.2.0 (maintainer-triggered, explicit per CLAUDE.md release_kit.phase_close_trigger). NEW bin/olp-keys.mjs (~250 lines): subcommand CLI keygen [--owner|--name=X|--tier=guest|owner|--providers=csv|--force] Creates a key + prints plaintext token to stdout ONCE; manifest stores only SHA-256 hash. --force revokes existing owner keys before creating the new owner (ADR § 9.3 recovery flow). list [--owner-only|--include-revoked] Lists keys with token_hash redacted. revoke --id=<key-id> Marks the key's revoked_at; idempotent (already-revoked → no-op + status message); missing id → exit 2. Common flag: --olp-home=<path> overrides ~/.olp/ (defaults to OLP_HOME env then ~/.olp/). package.json bin field "bin": { "olp-keys": "./bin/olp-keys.mjs" } so npx olp-keys ... resolves. Also "scripts": { "olp-keys": "node bin/olp-keys.mjs" } for npm run. Module shape (testability) Exports runCli(argv, { out, err }) so tests invoke with synthetic argv + IO writers (no process spawn). Main guard auto-runs when invoked as entrypoint. Plaintext token discipline (ADR § 5 + § 9.1) Plaintext printed exactly once on stdout. Never logged, never written to manifest, never written to audit. Operators capture immediately; lost → --force revoke + regenerate. --force async correctness cmdKeygen is async and awaits each revokeKey (which is async — acquires per-key write lock per § 6.4). Sequence: revoke each existing owner manifest atomically → then createKey for new owner. Avoids race where create-new runs before revoke-old completes. TESTS — Suite 22, +20 (524 → 544): 22a-1..5: parseArgv unit (--flag=value, --flag value, boolean, mixed positional) 22b-1..5: keygen (owner default, name+providers, missing-name error, invalid-tier error, --force revoke-then-create with isolation tmpdir) 22c-1..3: list (empty, populated with token_hash-redaction check, --owner-only filter) 22d-1..4: revoke (valid id, idempotent re-revoke, missing-id error, nonexistent-id error) 22e-1..3: top-level CLI (--help / no args / unknown subcommand exit codes) DOCUMENTATION: - AGENTS.md: lib/keys.mjs marker promoted to ✅; new bin/olp-keys.mjs entry. Implementation-status-note + shipped-set updated. - README.md: Implementation Status row added for bin/olp-keys.mjs; Known limitations note rewritten to "Phase 2 functional scope complete; close pending"; new Bootstrap workflow section with copy-pasteable npx commands + recovery flow. - CHANGELOG.md: D47 entry under Unreleased per release_kit overlay. AUTHORITY: - ADR 0007 — § 5 token format, § 9.1 minimal keygen command surface, § 9.3 recovery, § 10 acceptance criterion #9 covered. - CLAUDE.md release_kit overlay phase_rolling_mode — under Unreleased. - Standing autopilot grant. Verified: 544/544 pass via npm test (no regression in 524 pre-D47 tests; 20 new Suite 22 tests all green). Co-authored-by: dtzp555 <dtzp555@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
8fd8f86942 |
release(phase-1-cleanup): v0.1.1 — pre-Phase-2 batch (D35-D42)
Phase 1 cleanup release per CLAUDE.md release_kit.phase_rolling_mode
policy. Closes 16 of 17 pre-Phase-2 GitHub issues; #16 stays OPEN as
v1.x tracker with design ratified in ADR 0005 Amendment 8.
Bumps package.json from 0.1.0 → 0.1.1. Promotes CHANGELOG "Unreleased"
section to "## v0.1.1 — 2026-05-25" with full D35-D42 entries
(backfilled D35/D36/D37 entries per cold-audit round 7 Finding 1) and
final cleanup batch summary covering all 8 D-day commits that landed
on `main` between 2026-05-24 and 2026-05-25.
Tag v0.1.1 will be pushed after this commit lands and CI is green.
release.yml auto-creates the GitHub Release from the CHANGELOG v0.1.1
section (extracted via awk pattern match on `## v0.1.1` heading).
D37's phase_rolling_mode gate now passes because Unreleased is
sentinel-only after this commit.
**What v0.1.1 delivers (D35-D42):**
- D35 — streaming empty-stream headers (#9) + truncation marker (#10)
+ irVersion strict check (#11) + alignment.yml scripts/** removal
(#12) + X-OLP-Latency-Ms uniform audit (#4)
- D36 — cache_control partial-noop log (#2) + ADR 0002 filename
correction (#5) + mistral A5 flip (#6) + /v1/models alias governance
(#13) + cache_control determinism test (#14) + anthropic v2.1.89
transcript artifact (#15)
- D37 — release.yml phase_rolling_mode CI gate (#17)
- D38 — maxConcurrent runtime enforcement + new CONCURRENCY_LIMIT
hard trigger (#1)
- D39 — CacheStore.delete + cache_evicted_truncated log + sticky-
cache regression test + SPAWN_TIMEOUT asymmetry ADR (#3)
- D40 — X-OLP-Fallback-Detail debug header + per-hop tuple collection
+ 4KB cap + RFC 7230 non-ASCII escape (#7)
- D41 — X-OLP-Provider-Used chain-origin semantics documented (#8)
- D42 — streaming singleflight v1.x design ADR + multi-layer
safeguards (issue #16; STAYS OPEN as v1.x tracker)
**Test growth:** 416 (v0.1.0) → 468 (v0.1.1). +52 tests across the
8 D-day batch. All 468 pass at the release-commit head.
**Cold-audit cycle:** 1 final round (round 7) over D35-D42 + v0.1.0
state. Result: PASS_WITH_MINOR with 4 findings (1×P3 + 3×P4).
- Finding 1 (P3 CHANGELOG missing D35/D36/D37) — FIXED in this commit
via backfill.
- Finding 2 (P4 ADR 0005 Amendment 8 "Amendment 1/3/5" notation
ambiguity) — FIXED in this commit (replaced with explicit
§ Decision body item-1 + Amendment 3 + Amendment 5 wording).
- Finding 3 (P4 ADR 0005 Amendment 8 Context paragraph cites line 811
but actual branch is at lines 817-823) — FIXED in this commit
(Context paragraph now points at lines 817-823 with the TODO anchor
at ~810 as the navigable landmark).
- Finding 4 (P4 ADR 0002 missing Amendment 2 — pre-existing gap)
— FIXED in this commit (added explanatory note under the
Amendments heading explaining the gap is intentional and load-
bearing).
No P1 or P2 findings.
**Phase 1 cleanup release_kit checklist** (per CLAUDE.md):
- [x] All 8 D-day deliverables landed on main (D35-D42)
- [x] CI green on every D-day commit + on this release commit's head
- [x] Cold-audit round 7 PASS_WITH_MINOR (0 P1/P2; 4 findings all
fixed in this commit)
- [x] 16 of 17 pre-Phase-2 GitHub issues closed (#1-#15 and #17);
#16 stays OPEN as v1.x tracker with design ratified
- [x] Issue #16 status comment posted (D42 commit
|
||
|
|
9db4266bc5 |
release(phase-1-close): v0.1.0 — multi-provider proxy core
Phase 1 close per CLAUDE.md release_kit.phase_rolling_mode policy. Bumps package.json from 0.1.0-bootstrap → 0.1.0. Promotes CHANGELOG "Unreleased" section to "## v0.1.0 — 2026-05-24" with full D10-D34 commit index summarizing the 25 D-day commits that landed on `main` between 2026-05-23 and 2026-05-24. Tag v0.1.0 will be pushed after this commit lands and CI is green. release.yml auto-creates the GitHub Release from the CHANGELOG v0.1.0 section (extracted via awk pattern match on `## v0.1.0` heading). **What v0.1.0 delivers:** - OpenAI-compat HTTP entry surface (/v1/chat/completions, /v1/models, /health) with full X-OLP-* observability headers + Rule 2(b) no- invention compliance - Plugin architecture for 3 Tier-D providers (anthropic / codex / mistral) shipping as Candidate-not-Enabled per ALIGNMENT.md - Cache layer: D1 per-key isolation + D4 buffered-path singleflight + 10MB entry size cap + cacheable opt-out + per-(provider, model) isolation (D5 streaming singleflight deferred to v1.x per ADR 0005 Amendment 6) - Fallback engine: hard-trigger taxonomy + first-chunk safety + spawn- timeout race fix + SPAWN_FAILED salvage of usable partial chunks + structured per-hop log observability (chain_id, trigger_type, ir_request_hash, next_provider) - IR design + entry adapters honoring ADR 0003 deterministic serialization (including post-D33 F3 fix for deprecated function_call cache key stability) - 416 unit + integration tests with Suite 17 port-collision flake fix (D29) so CI is stable **Test growth**: 277 (pre-D10) → 416 (post-D34). +51%. **Audit cycle**: 6 cold-audit rounds + per-D-day diff reviews per Iron Rule v1.6 § 10.x dual-mode review discipline. 78+ findings raised; ~50 closed via implementation; ~28 deferred to GitHub issues #1-#17 for v1.x. **Phase 1 → v0.1.0 release_kit checklist** (per CLAUDE.md): - [x] All Phase 1 D-day deliverables landed on main (D10-D34) - [x] CI green on the head commit - [x] CHANGELOG "Unreleased" promoted to "## v0.1.0 — 2026-05-24" - [x] package.json bumped from 0.1.0-bootstrap → 0.1.0 - [ ] Tag pushed (next step in this PR's lifecycle) - [ ] release.yml triggered + GitHub Release created (auto on tag push) **Known limitations carried to v1.x** (full list in CHANGELOG.md v0.1.0 § "Known limitations"): - Streaming singleflight not implemented (issue #16) - maxConcurrent runtime enforcement declarative-only (#1) - X-OLP-Fallback-Detail header documented but never emitted (#7) - Soft trigger quotaStatus polling not wired (per ADR 0004 Amendment 2) - 14 other follow-up items: #2 #3 #4 #5 #6 #8 #9 #10 #11 #12 #13 #14 #15 #17 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e2e67de23a |
feat(phase-1): land IR + plugin loader + server skeleton (D3)
Phase 1 Day 1. First executable code lands. Zero providers wired yet
(per ALIGNMENT.md "v0.1 ships 0 Enabled Providers"); the server starts
clean and POST /v1/chat/completions returns 503 with no_enabled_provider.
Files added:
lib/ir/types.mjs - IR v1.0 schema + validators (ADR 0003)
lib/ir/openai-to-ir.mjs - OpenAI Chat Completions to IR
lib/ir/ir-to-openai.mjs - IR chunks to OpenAI SSE / non-stream
lib/providers/base.mjs - Provider contract + validateProvider + ProviderError
lib/providers/index.mjs - Static empty registry stub (ADR 0002)
server.mjs - HTTP listener with createOlpServer factory + main guard
test-features.mjs - 61 tests across 7 suites (IR / provider / HTTP)
Files modified:
package.json - main and scripts.start/test added back; targets now exist.
Authority citations:
IR fields and translation direction: ADR 0003 sections Decision and
Translation direction model.
Provider contract (9 fields): ADR 0002 section Provider contract v1.0
interface.
Entry surface routes (health, v1/models, v1/chat/completions): OLP v0.1
spec section 4.1 single-protocol entry; ALIGNMENT.md Authority 2.
Zero-Enabled-Providers behaviour: ALIGNMENT.md Provider Inventory.
Architectural decisions worth recording:
1. server.mjs uses a createOlpServer factory plus an import.meta.url
main guard. The factory returns an unbound http.Server; only the
main-script invocation calls .listen(). Tests import the real
server.mjs and exercise the real router. No parallel implementation
in the test file.
This pattern was a fold-in from the orchestration step. The initial
sonnet draft put a top-level server.listen call in server.mjs, which
forced test-features.mjs to reimplement the router inline (a false-
confidence trap because the real server logic would never be tested).
Refactored before reviewer dispatch.
2. lib/providers/index.mjs ships an empty STATIC_REGISTRY array, not a
placeholder with dummy entries. ALIGNMENT.md Provider Inventory says
v0.1 ships zero Enabled Providers; the registry honors that exactly.
Phase 1 Day 2 adds the first import (Anthropic) when its plugin lands.
3. BadRequestError lives in openai-to-ir.mjs and ProviderError in
base.mjs. Reviewer suggested relocating to a shared lib/errors.mjs
once the count exceeds two; deferred to Phase 1 Day 2 to ship with
the third typed error class.
4. contractVersion: '1.0' on each provider plugin: not enforced at D3
because no providers exist yet. Reviewer flagged for Phase 1 Day 2
tightening when the first provider lands.
Reviewer chain (Iron Rule 10):
Initial implementer: sonnet (general-purpose).
Refactor (createOlpServer + main guard) by the orchestrator after
catching the inline-router parallel-implementation issue.
Fresh-context reviewer: opus (ecc:code-reviewer). Verdict
APPROVE_WITH_MINOR.
Reviewer's two non-blocking findings folded in:
F1: removed unused createServer import from test-features.mjs line 12,
left over from the refactor.
F2: replaced finish_reason value 'error' with 'stop' in both the
streaming error chunk path (lib/ir/ir-to-openai.mjs line 72) and
the non-streaming error aggregation path (lib/ir/ir-to-openai.mjs
line 153). The 'error' value is not in OpenAI's documented
finish_reason enum (stop / length / tool_calls / content_filter /
function_call / null), so emitting it would violate ALIGNMENT.md
Rule 2 (b). Provider errors are now surfaced via a top-level
response.error object plus an inline content marker. The matching
test assertion at test-features.mjs line 325 was updated to verify
finish_reason stays within the OpenAI enum.
Note on the F2 fold-in:
Reviewer pointed only at the streaming path (line 72). After applying
that fix I ran grep across lib/ and test-features.mjs for the same
invention pattern and caught a second hit at line 153 (non-streaming
aggregation). This is the "fold-in must grep the full repo, not only
the file the reviewer named" discipline from
~/.cc-rules/memory/feedback/evidence_first_under_speed_pressure.md.
Both hits are fixed in this commit.
Verification:
node --check on all 7 new files plus modified package.json plus
server.mjs plus lib/ir/ir-to-openai.mjs - all clean.
npm test - 61/61 pass in 209ms, no flakes, no skipped.
OLP_PORT=14001 node server.mjs followed by curl /health returns
proper JSON; curl /v1/models returns 200 empty list; server shuts
down cleanly on signal.
grep "finish_reason.*error" returns zero hits across lib/ and tests.
Co-Authored-By: Claude Opus 4.7 (noreply@anthropic.com)
|
||
|
|
dff428f3d0 |
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) |
||
|
|
0041fb1017 |
chore: bootstrap OLP v0.1 — multi-provider LLM proxy
Initial release. OLP (Open LLM Proxy) is a personal- and family-scale
multi-provider LLM proxy that supersedes OCP (Open Claude Proxy).
Trigger: Anthropic's 2026-05-14 announcement (effective 2026-06-15)
moves `claude -p` / Agent SDK / third-party agent traffic out of the
Pro/Max subscription pool into a separate fixed monthly Agent SDK
Credit pool. OCP's foundational assumption ("subscription = unlimited
within rate limits") breaks for Anthropic on that date. Spreading
risk across multiple providers is the structural response.
Phase 0 lands:
- ALIGNMENT.md (constitution: 5 Rules, 3 Authorities, 4-tier Risk
Framework, 8-provider inventory)
- AGENTS.md (multi-tool agent guidelines; inherits cc-rules)
- CLAUDE.md (Claude-Code session instructions + release_kit overlay)
- README.md (phase-aware skeleton)
- docs/adr/0001-0006 (Founding ADRs: project founding / plugin
architecture / IR design / fallback engine / cross-provider cache /
provider inclusion + risk-tier framework)
- .github/PULL_REQUEST_TEMPLATE.md (8-radio Change Type + per-type
Authority Evidence + Iron Rule 10 reviewer checklist)
- .github/workflows/alignment.yml (blacklist + Antigravity exclusion
enforcement + models-registry validator + commit-citation soft check)
- .github/workflows/release.yml (auto-release on tag with version
match check per Iron Rule 5)
- .github/workflows/test.yml (Node 20/24 matrix, bootstrap-tolerant)
- package.json, .gitignore, LICENSE (MIT), CHANGELOG.md
Provider inventory at bootstrap:
Tier D (default-enabled): anthropic, openai, mistral
Tier C (opt-in): grok, kimi
Tier B (opt-in + consent): minimax, glm, qwen
Tier A (permanently excluded): google-antigravity
Supersedes OCP ADR 0005 (No Multi-Provider) per OLP ADR 0001. OCP
will enter maintenance mode when OLP v0.1 ships per Phase 7 plan.
Iron Rule 10 gate: fresh-context independent opus reviewer audited
all 15 governance files against OLP v0.1 spec + OCP precedent.
Verdict: APPROVE_WITH_MINOR. Two minor findings folded in:
1. alignment.yml heredoc EOF moved to column 0 (was indented;
bash parse failed silently on real blacklist hits, printing
a cryptic "syntax error" instead of the structured ALIGNMENT
GUARDRAIL FAILURE banner).
2. AGENTS.md clarified that the SPOT discipline for
models-registry.json will be codified by a Phase-1 ADR (OLP
ADR 0003 is currently the IR design, not a SPOT codification;
OCP's ADR 0003 is the precedent but OLP's registry shape
differs and warrants its own ADR).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|