From 004848176465765fe2a4bd7573829404b2aec597 Mon Sep 17 00:00:00 2001 From: dtzp555-max Date: Tue, 26 May 2026 07:59:11 +1000 Subject: [PATCH] =?UTF-8?q?feat+docs:=20D60=20=E2=80=94=20Phase=204=20char?= =?UTF-8?q?ter=20(ADR=200010)=20+=20default=20OLP=5FPORT=203456=20?= =?UTF-8?q?=E2=86=92=204567=20(#40)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat+docs: D60 — Phase 4 charter (ADR 0010) + default OLP_PORT 3456 → 4567 Opens Phase 4 (Operator + Client UX) end-to-end. Per release_kit.phase_rolling_mode, the version bump fires at Phase 4 close (v0.4.0), not at this D-day; D60 only ships governance + the port default change. ## ADR 0010 — Phase 4 Charter Phase 4 scope = 5 D-day groups (~13 D-days total): - D60 (this commit): charter + default port - D61-D63: SSE heartbeat + recentErrors[20] ring + /status combined endpoint - D64-D67: olp Node-based CLI scaffold + olp doctor next_action framework - D68-D70: olp-connect zero-config IDE setup + /health.anonymousKey + ADR 0011 - D71-D73: olp-plugin/ OpenClaw gateway plugin + docs/integrations/*.md bundle Charter records the EXPLICIT DECISION to DEFER /v1/messages (Anthropic-shape entry surface) on the rationale: under ADR 0009 P0 failure it provides no billing benefit AND degrades worse on fallback than OpenAI-shape clients (because OpenAI tool schema is the cross-provider lingua franca; Anthropic- specific features cache_control / computer_use / text_editor / thinking blocks have no clean fallback mapping). Re-open trigger: (a) ADR 0009 P0 success AND (b) maintainer-named family CC user. README posture updated: Claude Code listed as NOT SUPPORTED as an OLP client; recommended alternative is "Cline + OLP" (same fallback chain available, better cross-provider compatibility). ## Default port 3456 → 4567 server.mjs:74 default value moves so OLP and OCP (which stays on 3456) can co-host on the same machine without OLP_PORT env override. Existing deployments wanting the pre-D60 default can set OLP_PORT=3456 in launchd plist / shell env. Verified port-change invariants: - All test-features.mjs suites use port: 0 (ephemeral) — 0 test-surface impact - Cache / fallback / provider plugins port-agnostic - Dashboard 30s poll + management endpoints use relative paths - 623/623 tests pass on D60 branch HEAD ## ADR amendments - ADR 0001 § "Decision" port-conflict paragraph: struck + amended (co-host is now possible via 3456 → 4567 + launchd labels dev.olp.proxy vs dev.ocp.proxy) - ADR 0008 § 6.6 default-port reference updated - docs/adr/README.md index gains ADR 0010 row ## Authority - ADR 0010 (this commit) - ADR 0009 (interactive-mode placeholder — /v1/messages defer rationale) - 2026-05-26 brainstorm: OCP comprehensive feature audit (subagent output) + multi-provider proxy / IDE integration prior-art survey (subagent output, both this session) - docs/v1x-roadmap.md (Phase 4 was the named destination) - CLAUDE.md release_kit.phase_rolling_mode (current_phase already Phase 4; this charter formalizes contents) Co-Authored-By: Claude Opus 4.7 * fix: D60 reviewer P2-1 — soften ADR 0001 launchd-label assertion to forward-tense Reviewer flagged the ADR 0001 amendment's launchd-label collision claim ("avoided via dev.olp.proxy vs dev.ocp.proxy") as present-tense fact when the OLP plist generator hasn't shipped yet (lands D64-D70 per ADR 0010). Soften to forward-tense with explicit cross-reference. The factual claim ("co-host is possible") still stands because plist label is controlled by the OLP project anyway; this is precision, not correction. P2-2 (README "since v0.4.0" forward-dated branding) explicitly accepted as prior-art-consistent with D44+ Phase 2 mid-window doc conventions — no change. Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: dtzp555 Co-authored-by: Claude Opus 4.7 --- CHANGELOG.md | 13 +- README.md | 12 +- docs/adr/0001-project-founding.md | 2 +- docs/adr/0008-dashboard-and-audit-query.md | 2 +- ...-phase-4-charter-operator-and-client-ux.md | 162 ++++++++++++++++++ docs/adr/README.md | 1 + server.mjs | 7 +- 7 files changed, 189 insertions(+), 10 deletions(-) create mode 100644 docs/adr/0010-phase-4-charter-operator-and-client-ux.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f7f5500..828eefc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,18 @@ All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this ## Unreleased -(empty — Phase 4 entries land here once Phase 4 opens) +### D60 — Phase 4 charter (ADR 0010) + default port 3456 → 4567 + +Opens Phase 4 (Operator + Client UX). No functional code change beyond the default port value; the substantive D-day work lands D61 onward. Per `release_kit.phase_rolling_mode`, the version bump fires at Phase 4 close (v0.4.0), not at this D-day. + +- **Default `OLP_PORT` changed from `3456` to `4567`.** Rationale: OCP defaults to 3456; OLP and OCP can now co-host on the same machine without `OLP_PORT` env override. Existing deployments wanting the pre-D60 default can set `OLP_PORT=3456` in launchd plist / shell env. Tests use `port: 0` (ephemeral) — no test-surface impact. Cache / fallback / provider plugins are port-agnostic. Dashboard uses relative paths. +- **ADR 0010 (Phase 4 charter) ratified.** Records: (a) Phase 4 scope as 5 D-day groups (~13 D-days total) culminating in v0.4.0; (b) explicit DEFER of `/v1/messages` Anthropic-shape entry surface with re-open trigger gated on ADR 0009 P0 success + maintainer-named family CC user; (c) opportunistic Phase 4 micro-additions and Phase 5+ deferrals. +- **ADR 0001 amendment.** § "Decision" paragraph about port conflict struck and amended: the OCP-OLP port-conflict assumption is lifted by the 3456 → 4567 default move + per-project launchd labels (`dev.ocp.proxy` vs `dev.olp.proxy`). +- **ADR 0008 amendment.** § 6.6 default-port reference updated. +- **README quick start + Environment Variables table + Migration from OCP § note** updated for the new default. +- **Authority:** ADR 0010 (Phase 4 charter), ADR 0009 (interactive-mode placeholder — `/v1/messages` defer rationale), 2026-05-26 brainstorm (OCP feature audit + multi-provider proxy / IDE integration prior-art survey). + + ## v0.3.2 — 2026-05-25 diff --git a/README.md b/README.md index 5d3d6e4..b61db5d 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,12 @@ npm install -g @dtzp555-max/olp # run setup (writes ~/.olp/config.json, asks which providers to enable) olp setup -# start the proxy (default port 3456 — same as OCP if you migrate) +# start the proxy (default port 4567 since v0.4.0 — moved off OCP's 3456 so +# OLP and OCP can co-host on the same machine. Set OLP_PORT=3456 if you have +# no OCP on the machine and want the old default.) olp start -# point your IDE at http://localhost:3456/v1/chat/completions with the OLP API key from `olp keys list`. +# point your IDE at http://localhost:4567/v1/chat/completions with the OLP API key from `olp keys list`. ``` --- @@ -112,7 +114,7 @@ _placeholder — full table lands per-phase as variables are introduced._ | Variable | Default | Description | |---|---|---| -| `OLP_PORT` | `3456` | HTTP listener port. | +| `OLP_PORT` | `4567` | HTTP listener port. Moved off `3456` at D60 / v0.4.0 to co-host with OCP — set `OLP_PORT=3456` to restore the pre-D60 default. | | `OLP_CLAUDE_BIN` | `claude` (from PATH) | Override path to the `claude` binary (Anthropic provider). Useful when multiple `claude` installs are present. | | `OLP_CODEX_BIN` | `codex` (from PATH) | Override path to the `codex` binary (OpenAI provider). | | `OLP_VIBE_BIN` | `vibe` (from PATH) | Override path to the `vibe` binary (Mistral provider). | @@ -216,7 +218,7 @@ Behaviors that work correctly at personal/family scale but have ratified follow- npm start # 4. Validate the key works (substitute the captured plaintext token) - curl -H "Authorization: Bearer olp_..." http://localhost:3456/health + curl -H "Authorization: Bearer olp_..." http://localhost:4567/health ``` **Recovery if owner token is lost:** `npx olp-keys keygen --owner --force` revokes the previous owner key + creates a fresh one (plaintext printed once). @@ -270,7 +272,7 @@ Anticipated user-facing flow (target: <5 minutes): 1. Stop OCP (`launchctl bootout` the OCP service or `ocp stop`). 2. Install OLP. 3. Run `olp migrate-from-ocp` — copies `~/.ocp/keys/` to `~/.olp/keys/` and points provider plugins at OCP's existing auth artifacts where applicable. -4. Start OLP. Clients pointing at port 3456 keep working; their existing OLP API keys remain valid. +4. Start OLP. Clients pointing at port 4567 (or 3456 with `OLP_PORT=3456`) keep working; their existing OLP API keys remain valid. **Note (v0.4.0+):** default port moved from 3456 → 4567 so OCP and OLP can co-host during migration; set `OLP_PORT=3456` if you want the pre-D60 default. OCP's cache directory is *not* migrated: OLP's cache key format includes provider+model and warms cold naturally. OCP enters maintenance mode (stability fixes only) when OLP v0.1 ships; new development happens in OLP. diff --git a/docs/adr/0001-project-founding.md b/docs/adr/0001-project-founding.md index e132783..a2527d4 100644 --- a/docs/adr/0001-project-founding.md +++ b/docs/adr/0001-project-founding.md @@ -40,7 +40,7 @@ What OLP **does NOT inherit** from ADR 0005 (and where ADR 0005's reasoning does - ADR 0005's separate-project recommendation came with two qualifiers that OLP rejects: "BYOK from day one" and "no `cli.js` spawn." Both qualifiers were appropriate for the *commercial* path ADR 0005 was contemplating. OLP is not commercial — it is personal- and family-scale, shares the maintainer's own subscription quota across family clients, and explicitly spawns provider CLIs (it is precisely the spawn-binary architecture that delivers the "subscription quota maximization" value proposition spec §1 names). - OLP is therefore not the commercial pivot ADR 0005 endorsed. It is a personal-use re-architecture of the proxy-CLI pattern, which ADR 0005 did not contemplate. The supersession is honest about this gap. -OCP itself is not deleted. Per spec §7, OCP enters maintenance mode when OLP v0.1 ships. The two projects do not parallel-run in production (port-3456 conflict, single launchd service slot, one set of credentials per machine). +OCP itself is not deleted. Per spec §7, OCP enters maintenance mode when OLP v0.1 ships. ~~The two projects do not parallel-run in production (port-3456 conflict, single launchd service slot, one set of credentials per machine).~~ **Amended at D60 (2026-05-26, ADR 0010 Phase 4 charter):** the port-conflict assumption is lifted. OLP's default port moved `3456 → 4567` at v0.4.0 so OCP (which stays on 3456) and OLP can co-host on the same machine during a transition window. Launchd label collision **will be** avoided via `dev.olp.proxy` (OLP plist generation lands at Phase 4 close per ADR 0010 D64–D70; not on disk at D60) vs `dev.ocp.proxy` (OCP, already shipped). Credentials remain per-project (`~/.ocp/` vs `~/.olp/`). Co-host is explicit-opt-in, not the recommended steady state. OCP ADR 0005 receives a header amendment on merge of this ADR: *"Superseded in part by OLP — see https://github.com/dtzp555-max/olp ADR 0001 for the narrow scope of the supersession (single-provider-sufficiency premise only; ADR 0005's commercial / BYOK / no-spawn recommendations are not adopted)."* The body of ADR 0005 is otherwise untouched. Future readers should see the original reasoning intact and the supersession marker scoped explicitly. diff --git a/docs/adr/0008-dashboard-and-audit-query.md b/docs/adr/0008-dashboard-and-audit-query.md index f67f8a1..8af466b 100644 --- a/docs/adr/0008-dashboard-and-audit-query.md +++ b/docs/adr/0008-dashboard-and-audit-query.md @@ -195,7 +195,7 @@ The dashboard sets a 30s `setInterval` that calls `fetch('/v0/management/dashboa ### 6.6 Localhost-bound by default -The dashboard is served from the existing OLP HTTP port (default 3456) which is already bound to `127.0.0.1` per `server.mjs` startup (`server.listen(PORT, '127.0.0.1', ...)`). No additional binding logic. Remote operators access via SSH tunnel; ADR 0007 § 7 owner-only auth provides the per-request gate. +The dashboard is served from the existing OLP HTTP port (default 4567 since v0.4.0 / D60; 3456 pre-v0.4.0) which is already bound to `127.0.0.1` per `server.mjs` startup (`server.listen(PORT, '127.0.0.1', ...)`). No additional binding logic. Remote operators access via SSH tunnel; ADR 0007 § 7 owner-only auth provides the per-request gate. --- diff --git a/docs/adr/0010-phase-4-charter-operator-and-client-ux.md b/docs/adr/0010-phase-4-charter-operator-and-client-ux.md new file mode 100644 index 0000000..6b47c21 --- /dev/null +++ b/docs/adr/0010-phase-4-charter-operator-and-client-ux.md @@ -0,0 +1,162 @@ +# ADR 0010 — Phase 4 Charter: Operator + Client UX + +**Status:** Accepted (Phase 4 open as of 2026-05-26) +**Date:** 2026-05-26 +**D-day:** D60 (charter + default port change) + +--- + +## Context + +Phases 1 — 3 shipped OLP's structural core: HTTP entry surface, IR, provider plugins, fallback engine, content-addressed cache (including streaming-path singleflight at D57+D58 → v0.3.2), multi-key auth + audit ndjson + daily rotation, owner-only management endpoints + dashboard. v1.x roadmap items #1 / #2 / #4 / #7 are closed. Items #3 / #5 / #6 remain trigger-gated. + +Two complementary brainstorm passes (2026-05-26) — a comprehensive OCP feature audit + a multi-provider proxy / IDE integration prior-art survey — converged on a clear gap: **OLP's operator and client surfaces are 0% inherited from OCP**. Today OLP has `bin/olp-keys` and `bin/olp-audit-rotate` as the entire operator CLI, no `olp doctor` / no `olp-connect`, no Telegram/Discord integration, no SSE heartbeat for long-running streams behind reverse proxies. Family members get OLP API keys via out-of-band paste, point their IDEs at OLP via the README's one-line example, and discover failure modes via curl. OCP's UX worked because of a load-bearing combination: README `paste-this-prompt-to-Claude-Code` instructions + machine-readable `ocp doctor next_action.ai_executable[]` + `ocp-connect` zero-config LAN setup + `/health.anonymousKey` self-advertising token + `/ocp` Telegram slash commands. **Phase 4 brings these forward as OLP-native primitives.** + +A separate strategic decision — should OLP add `/v1/messages` (Anthropic-shape entry surface) for Claude Code support — was considered and **rejected for Phase 4** (see § "Out of Phase 4 scope" below). The decision is recorded with an explicit re-open trigger. + +--- + +## Decision + +Phase 4 scope is **Operator + Client UX**. The phase opens 2026-05-26 with D60 (this charter + default port change). Phase 4 close ships v0.4.0; per `CLAUDE.md release_kit.phase_rolling_mode`, the close PR is maintainer-triggered. + +### In scope — Phase 4 D-day plan (~13 D-days) + +| D-day | Deliverable | Authority | Estimate | +|---|---|---|---| +| **D60** | Default port `3456 → 4567` + this ADR 0010 charter + README / CHANGELOG / ADR 0001 + ADR 0008 amendments | This charter | 0.5d | +| **D61 — D63** | SSE heartbeat (opt-in via `streaming.heartbeat_interval_ms` config; eager-headers-post-spawn; `X-Accel-Buffering: no` constant) + `recentErrors[20]` ring buffer + `/status` combined endpoint | Port OCP `server.mjs:660-685` + `301-358` + `1151-1188`; OCP `docs/superpowers/specs/2026-04-25-47-sse-heartbeat-design.md` | 2.5d | +| **D64 — D67** | `olp` Node-based CLI scaffold (subcommands `status / health / usage / models / logs / cache / providers / chain show / restart / doctor`) + `olp doctor` machine-readable `next_action.ai_executable[]` framework + one fix-template per shipped provider plugin | Port OCP `ocp` bash wrapper (translated to Node — bash dep on python3 is a known fragile point) + OCP `scripts/doctor.mjs` framework | 4d | +| **D68 — D70** | `olp-connect ` client-side IDE auto-config (Cline / Continue.dev / Cursor / Aider / Claude Code / OpenClaw detection) + `/health.anonymousKey` field (opt-in via `auth.advertise_anonymous_key` config; default off) + ADR 0011 (anonymous-key deployment-context limits — trusted-LAN-only invariant explicit) | Port OCP `ocp-connect` + `server.mjs:1454,1488` | 3d | +| **D71 — D73** | `olp-plugin/` (OpenClaw gateway plugin for `/olp` Telegram/Discord slash commands; subcommand parity with `olp` CLI minus mutations) + `docs/integrations/{continue.md,cline.md,cursor.md,aider.md,claude-code.md,openclaw.md}` IDE setup docs | Port OCP `ocp-plugin/index.js`; cross-ref Prior-Art § 3 + § 4 | 3d | +| **close** | v0.4.0 release PR — `package.json` bump, CHANGELOG promotion, `release_kit.phase_rolling_mode` advance to Phase 5 pre-release identifier | `CLAUDE.md release_kit overlay` | maintainer-triggered | + +### Out of Phase 4 scope (with explicit triggers) + +#### `/v1/messages` — Anthropic-shape entry surface + +**Status:** Deferred. Re-enable strictly gated on ADR 0009 P0 success. + +**Value matrix (decisive):** + +| Scenario | Without `/v1/messages` | With `/v1/messages` | +|---|---|---| +| Maintainer's own Claude Code usage | Direct via Anthropic OAuth → subscription (today) or Agent SDK pool (post-2026-06-15) | Same — maintainer never routes own CC through OLP per stated workflow | +| Family member wanting CC access | Not supported (OAuth is full-account; OLP CLI tokens are scoped) | CC via `ANTHROPIC_BASE_URL=http://olp:4567` + `olp_*` token | +| **P0 succeeds** (ADR 0009 interactive-mode bills as subscription) | OpenAI-shape IDE clients (Cline/Continue/Cursor) all benefit automatically via OLP's anthropic plugin | CC users additionally benefit; both subscription-billed | +| **P0 fails** (interactive-mode bills as Agent SDK same as `-p`) | OpenAI-shape clients still work; no billing change | CC users get same billing as direct OAuth; **fallback to codex/mistral degrades Anthropic-specific features (tool_use schema mismatch / cache_control drop / computer_use no-op / thinking-block drop)** more severely than OpenAI-shape clients which speak the multi-provider lingua franca | + +**Rationale.** Under P0 failure, `/v1/messages` provides no billing benefit AND degrades worse on fallback than OpenAI-shape clients (because OpenAI tool schema is the cross-provider standard). The security benefit (no OAuth exposure) is equally achievable via Cline/Continue/Cursor. **Net non-positive under P0 failure.** + +**Re-open condition.** (a) ADR 0009 P0 confirms interactive-mode billing classification as subscription (≥ 2026-07-15) AND (b) maintainer explicitly opens Phase 5 "Anthropic-shape hub" scope with the name of at least one family member who wants CC access. If only (a) fires without (b), `/v1/messages` is reconsidered at the start of whichever phase covers it but is not auto-opened. + +**README posture (Phase 4).** README § Supported Clients explicitly lists OpenAI-compatible clients (Cline, Continue.dev, Cursor, Aider, OpenClaw bots). Claude Code is listed as **Not supported as an OLP client**, with the explicit alternative "Cline + OLP" (same fallback chain available, better cross-provider compatibility). README links to this ADR for the reasoning. + +#### Other deferred items + +- **v1.x roadmap #3 (soft trigger reactivation)**, **#5 (provider `cacheKeyFields` mask)**, **#6 (streaming SPAWN_FAILED salvage)** — trigger conditions per `docs/v1x-roadmap.md` have not fired. Not in Phase 4. +- **Anthropic / codex billing audits** — date-gated (`anthropic.mjs:53, 416, 441` say 2026-06-16; `codex.mjs:572` post-D7 E2E audit). Not in Phase 4. +- **`context_window_exceeded` fallback trigger** (LiteLLM prior-art) — small ADR amendment + trigger taxonomy add; opportunistically in Phase 5 unless trigger fires sooner. +- **`X-OLP-Cost-USD` per-request response header** — depends on provider-cost weights table (Phase 5 prerequisite). +- **per-(provider, model) live stats Map** (replacing audit-query scan for dashboard 30s poll) — current scan latency adequate; Phase 5+. +- **OpenTelemetry GenAI span emission** — `npm` dep + ~150 LOC; family-scale ROI marginal. Phase 6+ unless Langfuse self-host requested. +- **Intent-based routing**, **stackable transformer plugin model** — explicit non-goals per Prior-Art § 8 anti-patterns. + +### Opportunistic Phase 4 micro-additions (not blocking) + +Items small enough to land alongside a planned D-day without scope creep, if encountered: + +- Env-var deny-list before provider plugin `spawn` (per OCP `server.mjs:531-534`; each plugin declares its own list) +- 5 MB request body cap with HTTP 413 (per OCP `server.mjs:1270,1278-1281`) +- Error-response path-sanitization (per OCP `server.mjs:1395`) +- Stable node-path resolution in launchd plist (Homebrew `/Cellar//` → `/opt/` rewrite; per OCP `setup.mjs:344-351`) +- Legacy model alias resolution in `models-registry.json` (`aliases:` field; per OCP `legacyAliases`) + +### Exit gate — v0.4.0 close criteria + +1. D60 — D73 all merged with fresh-context opus reviewer APPROVE per Iron Rule 10. +2. CI green on every D-day merge commit and on the v0.4.0 release commit head. +3. README § Operator CLI + § IDE Setup + § Telegram/Discord Usage sections present. +4. ADR 0010 (this charter) + ADR 0011 (anonymous-key deployment-context limits) on disk. +5. `CHANGELOG.md "Unreleased"` promoted to `"## v0.4.0 — "` with D60 — D73 entries. +6. `package.json` bumped to `0.4.0`. +7. `CLAUDE.md release_kit.phase_rolling_mode.current_phase` advances `Phase 4 → Phase 5`; `current_pre_release_identifier` advances `0.4.0-phase4 → 0.5.0-phase5`. +8. Standing autopilot grant covers D-day-by-D-day execution; v0.4.0 close PR is maintainer-triggered. + +--- + +## Default port change (D60 specific) + +The default `OLP_PORT` value moves `3456 → 4567` at this D-day. Rationale: + +- OCP defaults to 3456 and the maintainer's existing OCP installs stay on 3456 indefinitely. +- A standard `olp` install on the same host without overriding `OLP_PORT` collides at bind time. +- Setting `OLP_PORT=4567` as the default makes co-host the recommended steady state during the migration window (and beyond — there is no enforced deprecation of OCP). +- Existing OLP deployments wanting the pre-D60 default can set `OLP_PORT=3456` in the launchd plist / shell env. + +**Tested invariants preserved by the port change:** + +- All `test-features.mjs` suites use `port: 0` (ephemeral assigned port) — no test depends on the default value. Verified via `grep -nE '\\b3456\\b' test-features.mjs` returning empty. +- All cache / fallback / provider plugin code is port-agnostic. +- Dashboard 30s poll uses relative paths — no port change required in `dashboard.html`. +- `/v0/management/*` endpoints use relative paths — no client-side update required. + +**Files amended at D60:** + +- `server.mjs:17` — env-var doc comment +- `server.mjs:74` — default value +- `README.md` quick start + Environment Variables table + Migration from OCP § note +- `docs/adr/0001-project-founding.md` § "Decision" paragraph about port conflict (struck and amended) +- `docs/adr/0008-dashboard-and-audit-query.md` § 6.6 port reference +- `CHANGELOG.md` Unreleased entry +- This ADR + +--- + +## Consequences + +**Positive.** + +- Family member onboarding goes from "maintainer texts API key + edits IDE config" to `curl -fsSL .../olp-connect | bash -s -- `. +- `paste-this-prompt-to-Claude-Code` self-installation pattern unlocks AI-driven setup / upgrade / repair, eliminating the maintainer's Tier-1 support role. +- Long-reasoning streams behind nginx / Cloudflare / Tailscale Funnel no longer 502 at 60s idle. +- `/olp` Telegram slash commands enable "is OLP up?" / "show usage" / "rotate key" from anywhere with chat access. +- OCP and OLP co-host on the same workstation, lowering the maintainer's cost of running both. + +**Negative.** + +- Phase 4 is the first phase whose scope is primarily about *operator experience* rather than functional capability. The work doesn't unlock new requests OLP can serve; it makes OLP's existing capability survive contact with real users. +- The `olp-connect` IDE auto-detect logic accumulates IDE-specific quirks (Cline base-URL UI regressions per their issue #7128; Cursor's malformed-request-when-OpenRouter behavior; etc.). Maintenance burden grows. +- README size grows substantially with Operator CLI + IDE Setup + Telegram/Discord sections. Discoverability of the existing technical reference (ADRs, environment variables) may degrade unless the navigation is refactored. + +**Neutral.** + +- Phase 4 deliberately spends 0 D-days on `/v1/messages`. If ADR 0009 P0 succeeds in Q3 2026, Phase 5 "Anthropic-shape hub" becomes the natural next phase, with the prerequisite IR work that Phase 4 surfaces (every IDE doc page is a test of which IR fields actually flow through). If P0 fails, `/v1/messages` shelves indefinitely and the README simply documents CC as out-of-scope. + +--- + +## Alternatives considered + +1. **Phase 4 = `/v1/messages` first, operator UX later.** Rejected. The brainstorm matrix demonstrated `/v1/messages` is value-positive only if ADR 0009 P0 succeeds, and operator UX gains accrue regardless. Building speculative infrastructure ahead of P0 risks 5-7 D-days of work shelving. +2. **Phase 4 = operator + client UX + `/v1/messages` together (full kitchen sink).** Rejected. ~20 D-days lengthens the Phase 4 close window unnecessarily; the natural review chunks blur; maintainer review fatigue is real. +3. **Phase 4 = just D60 + opportunistic SSE heartbeat, no CLI / no plugin / no docs bundle.** Rejected. Each of the operator-UX items individually has small ROI; the value compounds when they ship together (CLI surfaces data → `/status` exposes shape → Telegram plugin renders → IDE docs reference → `olp-connect` automates). Splitting them across phases loses the compounding. +4. **Defer Phase 4 entirely; jump to Phase 5 Anthropic-shape hub when P0 lands.** Rejected. Operator UX is needed now (this session is itself evidence — the maintainer spent ~30 minutes confirming OCP feature inheritance because there's no `olp doctor` answer). Waiting for P0 stalls progress on independently-valuable work. + +--- + +## Authority + +- `docs/v1x-roadmap.md` — Phase 4 was named as the canonical destination for the post-cleanup batch since v0.3.0 close. +- `CLAUDE.md release_kit.phase_rolling_mode` — `current_phase: Phase 4` already; this charter formalizes the contents. +- OCP comprehensive feature audit (2026-05-26 subagent output, summarized in `~/.cc-rules/memory/auto/MEMORY.md` and in this session's transcript). +- Multi-provider proxy / IDE integration prior-art survey (2026-05-26 subagent output). +- ADR 0009 (Anthropic interactive-mode path placeholder) — establishes the gate for `/v1/messages` re-consideration. +- ADR 0001 (project founding) — § "Decision" paragraph about port conflict, amended at this D-day. +- ADR 0008 (dashboard + audit query) — § 6.6 default-port reference, amended at this D-day. +- `~/.cc-rules/memory/auto/standing_autopilot_phase_2.md` — standing autopilot grant covering D-day-by-D-day execution; v0.4.0 close PR is maintainer-triggered per `release_kit.phase_close_trigger`. + +--- + +## Procedural mechanism + +CC 开发铁律 v1.6 § 5.5 (release-kit overlay drives Phase boundaries) + § 10 (independent reviewer on every implementation D-day) + § 11 (minimum reviewable unit per PR — this charter ships as D60 PR alongside the default port change because both are governance-class and small). diff --git a/docs/adr/README.md b/docs/adr/README.md index 7ece71b..2b014aa 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -23,6 +23,7 @@ New ADRs increment from the highest existing number. Filenames are `NNNN-/manifest.json`) + opaque `olp_<32-byte>` token + SHA-256 hash. Owner / guest / anonymous tier gating with explicit `config.json auth.allow_anonymous` (default false). Bootstrap keygen command surface + `OLP_OWNER_TOKEN` env override with stable synthetic `key_id`. Audit ndjson append-only at `~/.olp/logs/audit.ndjson`, warn+1-retry on append failure. Rejects direct SQLite port at v0.2.0 due to Node baseline (`engines >=18` + CI 20/24 vs `node:sqlite` added 22.5.0 / RC); Option 3 hybrid documented as forward path when Phase 3+ Dashboard / SQL-aggregate quota arrives. | | [0008](0008-dashboard-and-audit-query.md) | Dashboard + Audit Query Layer | Phase 3 design ADR (D48, 2026-05-25). Static HTML dashboard + vanilla JS + fetch (no build step). In-memory ndjson scan for aggregate queries (O(N) per call; family-scale acceptable; defers SQLite migration to Option 3 hybrid trigger). Daily audit rotation `audit-YYYY-MM-DD.ndjson` on first append after UTC midnight; cross-file query layer for rolling 30-day windows. Owner-only gating on `/dashboard` + 3 `/v0/management/*` JSON endpoints reusing ADR 0007 § 7 auth model. 30s page poll (no SSE infra). Panels: per-provider quota / 24h request+cache+fallback / 30d spend trend / top-N fallback chains per spec § 4.6. Opens ADR 0007 § 12 Phase 3 deferral (Dashboard + audit query + rotation). | | [0009](0009-interactive-mode-path-placeholder.md) | Anthropic Interactive-Mode Path (Placeholder) | Placeholder ADR (2026-05-25, Draft) — blocked on OCP ADR 0007 P0 experiment outcome. Records the maintainer's "wait + port" decision: do NOT independently implement; ride OCP's P0 result. If P0 confirms Transport A (stdio NDJSON) or B (PTY) bills as subscription rather than Agent SDK credit, port to OLP `lib/providers/anthropic.mjs` (Option 1 parallel impl, or Option 2 OCP-as-backend; decision deferred to P0-resolution time). If P0 fails on both, shelve. No Phase 4 D-day scheduled until P0 lands AND maintainer issues explicit "go" naming this ADR. | +| [0010](0010-phase-4-charter-operator-and-client-ux.md) | Phase 4 Charter — Operator + Client UX | Phase 4 scope ratification (2026-05-26, Accepted). Phase 4 = operator + client UX (SSE heartbeat / `olp` CLI + doctor / `olp-connect` zero-config + Telegram-Discord plugin + IDE docs bundle). ~13 D-days, D60 → v0.4.0. Records the explicit decision to DEFER `/v1/messages` (Anthropic-shape entry surface) on the rationale that under ADR 0009 P0 failure it provides no billing benefit AND degrades worse on fallback than OpenAI-shape clients. Re-open trigger: ADR 0009 P0 success + maintainer-named family CC user. Also closes the OCP-OLP port co-host ambiguity from ADR 0001 (default `OLP_PORT` 3456 → 4567). | ## When to write a new ADR diff --git a/server.mjs b/server.mjs index ffc1b7b..7d9e74f 100644 --- a/server.mjs +++ b/server.mjs @@ -14,7 +14,10 @@ * - Zero runtime npm dependencies in the proxy core * * Env vars: - * OLP_PORT — listen port (default: 3456) + * OLP_PORT — listen port (default: 4567 since D60 / v0.4.0 — moved off 3456 + * so OLP can co-host with OCP for migration windows. ADR 0010 § + * Default port. Set OLP_PORT=3456 explicitly to restore the + * pre-D60 default when not co-hosting with OCP.) */ import { createServer } from 'node:http'; @@ -71,7 +74,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')); const VERSION = pkg.version; -const PORT = parseInt(process.env.OLP_PORT ?? '3456', 10); +const PORT = parseInt(process.env.OLP_PORT ?? '4567', 10); const BODY_LIMIT = 5 * 1024 * 1024; // 5 MB // ── Logging ───────────────────────────────────────────────────────────────