mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-21 21:15:10 +00:00
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>
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
name: Alignment Guardrail
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'server.mjs'
|
||||
- 'setup.mjs'
|
||||
- 'lib/**'
|
||||
- 'scripts/**'
|
||||
- 'models-registry.json'
|
||||
- '.github/workflows/alignment.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'server.mjs'
|
||||
- 'setup.mjs'
|
||||
- 'lib/**'
|
||||
- 'scripts/**'
|
||||
- 'models-registry.json'
|
||||
- '.github/workflows/alignment.yml'
|
||||
|
||||
jobs:
|
||||
blacklist:
|
||||
name: source blacklist (hard fail)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Scan source for hallucinated tokens
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Known-hallucinated tokens. Extend only via an ALIGNMENT.md amendment PR.
|
||||
# Each token is matched as a fixed string against the OLP source tree
|
||||
# (excluding docs/, CHANGELOG, README, this workflow, and tests that
|
||||
# may legitimately reference the historical token as a guardrail).
|
||||
#
|
||||
# Inherited transitively from OCP's 2026-04-11 drift:
|
||||
# - api.anthropic.com/api/oauth/usage : fabricated Anthropic OAuth
|
||||
# usage endpoint. Does not appear in any shipped @anthropic-ai/
|
||||
# claude-code cli.js. Carried forward as a transitive guardrail.
|
||||
#
|
||||
# OLP-native entries: added as drift incidents accumulate.
|
||||
BLACKLIST=(
|
||||
"api.anthropic.com/api/oauth/usage"
|
||||
)
|
||||
|
||||
# Provider keys that may appear in source (positive list — present in
|
||||
# ALIGNMENT.md provider inventory). Any provider key in source that
|
||||
# is NOT in this list is suspicious and flagged below.
|
||||
KNOWN_PROVIDERS=(
|
||||
"anthropic"
|
||||
"openai"
|
||||
"mistral"
|
||||
"grok"
|
||||
"kimi"
|
||||
"minimax"
|
||||
"glm"
|
||||
"qwen"
|
||||
)
|
||||
|
||||
# Source files in scope. Exclude docs, CHANGELOG, README, the
|
||||
# workflow itself, and the test file (which may pin historical
|
||||
# strings intentionally).
|
||||
SOURCE_FILES="$(git ls-files \
|
||||
| grep -E '\.(mjs|js|ts|json)$' \
|
||||
| grep -v -E '^(docs/|CHANGELOG\.md|README\.md|test-features\.mjs|\.github/workflows/alignment\.yml)')"
|
||||
|
||||
FAIL=0
|
||||
|
||||
# 1. Blacklist scan
|
||||
for token in "${BLACKLIST[@]}"; do
|
||||
if echo "$SOURCE_FILES" | xargs grep -n -F "$token" 2>/dev/null; then
|
||||
echo "::error::Blacklisted token '$token' detected in OLP source."
|
||||
FAIL=1
|
||||
fi
|
||||
done
|
||||
|
||||
# 2. Excluded-provider scan: Google Antigravity is permanently
|
||||
# excluded per ADR 0006 / ALIGNMENT.md Risk Tier A. Any reference
|
||||
# to a `google-antigravity` plugin file or provider key in source
|
||||
# (outside docs which may discuss the exclusion) is a finding.
|
||||
FORBIDDEN_PROVIDER_TOKENS=(
|
||||
"google-antigravity"
|
||||
"antigravity"
|
||||
)
|
||||
for token in "${FORBIDDEN_PROVIDER_TOKENS[@]}"; do
|
||||
HITS="$(echo "$SOURCE_FILES" | xargs grep -n -F "$token" 2>/dev/null || true)"
|
||||
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 "$HITS"
|
||||
FAIL=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$FAIL" -ne 0 ]; then
|
||||
cat <<'EOF'
|
||||
|
||||
============================================================
|
||||
ALIGNMENT GUARDRAIL FAILURE
|
||||
============================================================
|
||||
OLP source contains a token on the alignment blacklist or
|
||||
references a permanently excluded provider.
|
||||
|
||||
Blacklist tokens were introduced by LLM hallucinations and
|
||||
do not appear in the relevant authority (provider CLI,
|
||||
OpenAI spec, or ADR). See ALIGNMENT.md and (where the
|
||||
token is inherited from OCP) the OCP 2026-04-11 drift
|
||||
record at https://github.com/dtzp555-max/ocp.
|
||||
|
||||
Excluded providers are listed in ALIGNMENT.md § Risk Tier
|
||||
Framework and ADR 0006. Permanent exclusion means not
|
||||
bundled, not pluggable, not added via opt-in.
|
||||
|
||||
Required action:
|
||||
1. Remove the token from source.
|
||||
2. Cite the real authority (provider CLI doc / OpenAI
|
||||
spec section / ADR) for the operation you intended.
|
||||
3. See ALIGNMENT.md Rules 1, 2, and 5.
|
||||
|
||||
Do not add allowlist entries to this workflow without an
|
||||
amendment PR to ALIGNMENT.md (see Amendment Procedure).
|
||||
============================================================
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Blacklist + excluded-provider scan clean."
|
||||
|
||||
models-registry:
|
||||
name: models-registry.json sanity (hard fail)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate models-registry.json
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ ! -f models-registry.json ]; then
|
||||
echo "models-registry.json not found yet (bootstrap phase). Skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Basic JSON validity.
|
||||
if ! node -e "JSON.parse(require('fs').readFileSync('models-registry.json','utf8'))"; then
|
||||
echo "::error::models-registry.json is not valid JSON."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Provider keys in models-registry.json must match the inventory
|
||||
# in ALIGNMENT.md.
|
||||
KNOWN_PROVIDERS='["anthropic","openai","mistral","grok","kimi","minimax","glm","qwen"]'
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const known = ${KNOWN_PROVIDERS};
|
||||
const reg = JSON.parse(fs.readFileSync('models-registry.json','utf8'));
|
||||
const providers = reg.providers || {};
|
||||
const bad = Object.keys(providers).filter(p => !known.includes(p));
|
||||
if (bad.length > 0) {
|
||||
console.error('::error::Unknown provider key(s) in models-registry.json: ' + bad.join(', '));
|
||||
console.error('Known providers per ALIGNMENT.md: ' + known.join(', '));
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('models-registry.json provider keys OK: ' + Object.keys(providers).join(', '));
|
||||
"
|
||||
|
||||
commit-citation:
|
||||
name: per-provider commit citation (soft check)
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- name: Checkout full history
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Scan PR commits for uncited assertions
|
||||
if: github.event_name == 'pull_request'
|
||||
shell: bash
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "${BASE_SHA:-}" ] || [ -z "${HEAD_SHA:-}" ]; then
|
||||
echo "No PR context; skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
WARN=0
|
||||
git log --format="%H" "${BASE_SHA}..${HEAD_SHA}" | while read -r sha; do
|
||||
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 '(cli[[:space:]]+v[0-9]+|https?://|ADR[[:space:]]+[0-9]{4})'; then
|
||||
echo "OK $sha: assertion cited."
|
||||
else
|
||||
echo "::warning::Commit $sha asserts 'Provider X uses ...' or '<provider> CLI uses ...' but does not cite a CLI version, docs URL, or ADR number. See CLAUDE.md -> Commit message conventions."
|
||||
WARN=1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$WARN" -ne 0 ]; then
|
||||
echo "Soft check raised warnings. Reviewer: please enforce per CLAUDE.md."
|
||||
else
|
||||
echo "Commit citation soft check clean."
|
||||
fi
|
||||
@@ -0,0 +1,73 @@
|
||||
name: Auto Release on Tag
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Extract version from tag
|
||||
id: ver
|
||||
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Verify package.json version matches tag
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ ! -f package.json ]; then
|
||||
echo "::warning::package.json not found; skipping version-match check."
|
||||
exit 0
|
||||
fi
|
||||
PKG_VERSION="$(node -p "require('./package.json').version")"
|
||||
TAG_VERSION="${{ steps.ver.outputs.version }}"
|
||||
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
|
||||
echo "::error::Tag v${TAG_VERSION} does not match package.json version ${PKG_VERSION}. Bump package.json before tagging (Iron Rule 5)."
|
||||
exit 1
|
||||
fi
|
||||
echo "Tag v${TAG_VERSION} matches package.json version ${PKG_VERSION}."
|
||||
|
||||
- name: Extract CHANGELOG section
|
||||
id: notes
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${{ steps.ver.outputs.version }}"
|
||||
if [ ! -f CHANGELOG.md ]; then
|
||||
echo "No CHANGELOG.md found; using minimal release notes"
|
||||
echo "Release v${VERSION}" > /tmp/release-notes.md
|
||||
exit 0
|
||||
fi
|
||||
awk -v ver="v${VERSION}" '
|
||||
$0 ~ "^## " ver { found=1; print; next }
|
||||
found && /^## v/ { exit }
|
||||
found { print }
|
||||
' CHANGELOG.md > /tmp/release-notes.md
|
||||
if [ ! -s /tmp/release-notes.md ]; then
|
||||
echo "No matching section in CHANGELOG for v${VERSION}; using minimal notes"
|
||||
echo "Release v${VERSION}" > /tmp/release-notes.md
|
||||
fi
|
||||
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${{ steps.ver.outputs.version }}"
|
||||
if gh release view "v${VERSION}" >/dev/null 2>&1; then
|
||||
echo "Release v${VERSION} already exists - skipping"
|
||||
exit 0
|
||||
fi
|
||||
gh release create "v${VERSION}" \
|
||||
--title "v${VERSION}" \
|
||||
--notes-file /tmp/release-notes.md \
|
||||
--latest
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test-features:
|
||||
name: test-features.mjs (smoke)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: ['20', '24']
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Detect package-lock
|
||||
id: detect_lock
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f package-lock.json ]; then
|
||||
DEPS="$(node -p "Object.keys(require('./package.json').dependencies || {}).length")"
|
||||
if [ "$DEPS" -gt 0 ]; then
|
||||
echo "needs_install=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "needs_install=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "needs_install=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: npm install (if dependencies present)
|
||||
if: steps.detect_lock.outputs.needs_install == 'true'
|
||||
run: npm ci
|
||||
|
||||
- name: Run npm test
|
||||
shell: bash
|
||||
run: |
|
||||
if [ ! -f test-features.mjs ] && ! node -e "process.exit(require('./package.json').scripts && require('./package.json').scripts.test ? 0 : 1)" 2>/dev/null; then
|
||||
echo "::notice::No test-features.mjs or npm test script yet (bootstrap phase). Skipping."
|
||||
exit 0
|
||||
fi
|
||||
npm test
|
||||
Reference in New Issue
Block a user