mirror of
https://github.com/dtzp555-max/olp.git
synced 2026-07-21 21:15:10 +00:00
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 b0c080d)
referencing ADR 0005 Amendment 8 design ratification
- [x] CHANGELOG "Unreleased" promoted to "## v0.1.1 — 2026-05-25"
with D35-D42 entries (including backfilled D35/D36/D37)
- [x] package.json bumped from 0.1.0 → 0.1.1
- [x] docs/v1x-roadmap.md created at D42 — 7 deferred items with
code anchors + GitHub-issue cross-refs + concrete start triggers
- [x] Editorial findings 2/3/4 from round 7 folded into this commit
- [ ] Tag pushed (next step in this PR's lifecycle)
- [ ] release.yml triggered + GitHub Release created (auto on tag
push; D37 phase_rolling_mode gate will pass because Unreleased
is now sentinel-only — gate dry-run verified locally)
**Known limitations carried to v1.x:** full list with code anchors
+ start triggers in docs/v1x-roadmap.md. The 7 items are:
1. Streaming-path singleflight (issue #16, ADR 0005 Amendment 8)
2. Multi-key auth (lib/keys.mjs)
3. Soft-trigger reactivation (ADR 0004 Amendment 2)
4. /health activeSpawns integration (ADR 0002 Amendment 6)
5. Provider-level cacheKeyFields mask (ADR 0005 Amendment 7)
6. Streaming-path SPAWN_FAILED salvage
7. D40 AUTH_MISSING tuple test coverage
Authority:
- All 8 D-day commit messages (D35-D42 on main)
- ADR 0002 Amendments 5+6 + Amendment-2-gap note (D36, D38, this
commit's editorial fix)
- ADR 0004 Amendments 3+4+5+6 (D34, D38, D40, D41)
- ADR 0005 Amendments 6+7+8 (D34, D42) + this commit's Amendment 8
editorial fixes
- ALIGNMENT.md controlled-deviations subsection (D36 #13)
- docs/v1x-roadmap.md (D42 — new file, this commit's checklist
references it)
- docs/provider-audits/anthropic.md (D36 #15 — new file)
- CC 开发铁律 v1.6 § 10.x — every D-day had an independent
fresh-context opus reviewer per Iron Rule 10; round 7 cold audit
was a separate fresh-context full-pass auditor
- CLAUDE.md release_kit_overlay phase_rolling_mode — this is the
Phase 1 cleanup release that the policy was written for
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -4,10 +4,48 @@ All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
(empty — Phase 2 entries land here once Phase 2 opens)
|
||||||
|
|
||||||
|
## v0.1.1 — 2026-05-25
|
||||||
|
|
||||||
|
### Phase 1 cleanup — pre-Phase-2 batch (D35–D42, closes 16 of 17 issues)
|
||||||
|
|
||||||
|
**Overview.** v0.1.1 closes the post-v0.1.0 cleanup batch covering all 17 pre-Phase-2 issues raised during the 6-round cold-audit cycle on the Phase 1 deliverable. 8 D-day commits (D35–D42) shipped between 2026-05-24 and 2026-05-25. 16 issues closed; issue #16 (streaming singleflight) stays OPEN as the v1.x tracker with its design ratified in ADR 0005 Amendment 8.
|
||||||
|
|
||||||
|
**Test count: 416 (v0.1.0) → 468 (v0.1.1).** +52 tests across the cleanup batch.
|
||||||
|
|
||||||
|
### D35 — pre-Phase-2 batch #1 (issues #4 #9 #10 #11 #12)
|
||||||
|
|
||||||
|
- **#4 — X-OLP-Latency-Ms uniform.** Audit confirmed already-correct via D32; D35 adds the `#4-audit` regression test pinning the 5-header invariant on the 503 no-provider sendError so future drift is caught immediately.
|
||||||
|
- **#9 — Streaming empty-then-clean-exit headers.** Zero-chunk streaming path now guards `!res.headersSent` and emits Content-Type=text/event-stream, Cache-Control=no-cache, Connection=keep-alive, X-Accel-Buffering=no, plus all 5 X-OLP-* headers via olpHeaders before writing `SSE_DONE`. Zero-chunk path correctly does NOT cache.
|
||||||
|
- **#10 — Streaming post-first-chunk error truncation marker.** Two sibling fixes: catch-block-firstChunkEmitted=true and error-chunk-after-first-chunk both now emit synthetic `{type:'stop', finish_reason:'length'}` via `irChunkToOpenAISSE` + `SSE_DONE` + `res.end()`. Per ADR 0004 § Fallback safety: post-first-chunk truncation surfaces as `length` finish, never a hang.
|
||||||
|
- **#11 — `validateIRRequest` irVersion strict check.** ADR 0003 IR contract pins irVersion to `'1.0'`. Validator now: `obj.irVersion !== undefined && obj.irVersion !== '1.0'` → rejection. Strict string match — `undefined` accepted (back-compat), `'1.0'` accepted, `'2.0'` rejected, numeric `1.0` rejected (`1.0 !== '1.0'`).
|
||||||
|
- **#12 — `alignment.yml` scripts/** trigger removal.** Removed from both `push.paths` and `pull_request.paths` since the `scripts/` directory does not currently exist (planned for Phase 7).
|
||||||
|
- **Test count:** 416 → 424 (+8).
|
||||||
|
|
||||||
|
### D36 — pre-Phase-2 batch #2 (issues #2 #5 #6 #13 #14 #15)
|
||||||
|
|
||||||
|
- **#2 — cache_control partial-noop debug log.** `server.mjs handleChatCompletions` fires `logEvent('debug', 'cache_control_partial_noop', { chain, marker_count })` at most once per request when markers present AND chain has at least one non-Anthropic hop. Per ADR 0005 § D2.
|
||||||
|
- **#5 — ADR 0002 vibe.mjs → mistral.mjs.** § Decision filesystem layout corrected to match the shipped file naming convention (file named after provider key, not CLI binary). Amendment 5 documents the correction + makes the convention statement explicit for future contributors.
|
||||||
|
- **#6 — mistral.mjs A5 flip + ALIGNMENT.md table update.** Header A5 (model flag) flipped from `UNPINNED-D-later-verifies` to `CONFIRMED-NOT-APPLICABLE` with DeepWiki citation; ALIGNMENT.md Speculative-Candidate table mistral row updated to remove A5.
|
||||||
|
- **#13 — /v1/models alias governance.** ALIGNMENT.md gains "Controlled deviations (entry-surface scope)" subsection documenting the alias surface as a controlled Rule 2(b) deviation; `docs/openai-spec-pin.md` gains the alias-surfacing subsection with full 4-field contract table.
|
||||||
|
- **#14 — cache_control slot determinism regression test.** 4 tests in test-features.mjs construct hand-built IRs with synthetic markers (bypassing openAIToIR which strips them at v0.1) and verify the cache key SHA-256 is deterministic. Per ALIGNMENT.md Rule 2 (No Invention), no `sortMarkers` helper shipped — the slot is dead-code at v0.1.
|
||||||
|
- **#15 — Anthropic v2.1.89 transcript artifact.** New file `docs/provider-audits/anthropic.md` as a single living version-capture artifact. Records observed `claude --version` (2.1.132 at capture date 2026-05-24), pinned version (v2.1.89 from D4), drift note, sample invocation, flag-surface table for 5 OLP-consumed flags. Closes the circular ALIGNMENT.md ↔ plugin header citation by anchoring on an external artifact.
|
||||||
|
- **Test count:** 424 → 431 (+7).
|
||||||
|
|
||||||
|
### D37 — release.yml phase_rolling_mode gate (issue #17)
|
||||||
|
|
||||||
|
- **CI gate enforcing phase_rolling_mode promotion discipline.** New "Enforce phase_rolling_mode (Unreleased must be promoted)" step in `release.yml` between the version-match check and the CHANGELOG extraction step. Awk extracts content between `## Unreleased` and the next `## ` heading; sed strips blank lines and parenthetical-sentinel-only lines. Non-trivial remaining content fails the workflow with `::error::` instructing the maintainer to promote Unreleased → `## v<version>` per CLAUDE.md release_kit.phase_rolling_mode.
|
||||||
|
- **Dry-run validated against 4 cases:** current sentinel-only Unreleased → PASS; synthetic non-trivial Unreleased → FIRES with offending lines reported; no Unreleased section → PASS; multi-sentinel + blank lines → PASS.
|
||||||
|
- **Gate is purely additive** — fires only on tag push to `v*.*.*`, does not affect normal push/PR CI.
|
||||||
|
- **Test count:** 431 → 431 (no test change — CI workflow only).
|
||||||
|
|
||||||
### D38 — maxConcurrent runtime enforcement (issue #1)
|
### D38 — maxConcurrent runtime enforcement (issue #1)
|
||||||
|
|
||||||
- **Spawn lifecycle gate** — `hints.maxConcurrent` is now enforced at runtime per ADR 0002 Amendment 6: `lib/providers/index.mjs` exports a per-provider `tryAcquireSpawn` / `releaseSpawn` / `getActiveSpawnCount` semaphore; `server.mjs` gates both the buffered and streaming spawn call sites in `handleChatCompletions` with a try/finally release. Saturation surfaces as `ProviderError(CONCURRENCY_LIMIT)` which the fallback engine treats as a hard trigger (ADR 0004 Amendment 4) — the chain advances to the next hop instead of queueing. If the entire chain is saturated, the user receives a chain-exhausted error via the existing exhaustion path. Closes #1. Queue+timeout deferred (see ADR 0002 Amendment 6 § Design choice). Test count 431 → 447.
|
- **Spawn lifecycle gate** — `hints.maxConcurrent` is now enforced at runtime per ADR 0002 Amendment 6: `lib/providers/index.mjs` exports a per-provider `tryAcquireSpawn` / `releaseSpawn` / `getActiveSpawnCount` semaphore; `server.mjs` gates both the buffered and streaming spawn call sites in `handleChatCompletions` with a try/finally release. Saturation surfaces as `ProviderError(CONCURRENCY_LIMIT)` which the fallback engine treats as a hard trigger (ADR 0004 Amendment 4) — the chain advances to the next hop instead of queueing. If the entire chain is saturated, the user receives a chain-exhausted error via the existing exhaustion path. Closes #1. Queue+timeout deferred (see ADR 0002 Amendment 6 § Design choice). Test count 431 → 447.
|
||||||
|
|
||||||
|
- **Spawn lifecycle gate** — `hints.maxConcurrent` is now enforced at runtime per ADR 0002 Amendment 6: `lib/providers/index.mjs` exports a per-provider `tryAcquireSpawn` / `releaseSpawn` / `getActiveSpawnCount` semaphore; `server.mjs` gates both the buffered and streaming spawn call sites in `handleChatCompletions` with a try/finally release. Saturation surfaces as `ProviderError(CONCURRENCY_LIMIT)` which the fallback engine treats as a hard trigger (ADR 0004 Amendment 4) — the chain advances to the next hop instead of queueing. If the entire chain is saturated, the user receives a chain-exhausted error via the existing exhaustion path. Closes #1. Queue+timeout deferred (see ADR 0002 Amendment 6 § Design choice). Test count 431 → 447.
|
||||||
|
|
||||||
### D39 — D16 follow-ups (issue #3): explicit cache delete + eviction log + SPAWN_TIMEOUT asymmetry doc
|
### D39 — D16 follow-ups (issue #3): explicit cache delete + eviction log + SPAWN_TIMEOUT asymmetry doc
|
||||||
|
|
||||||
- **Part 1 — `CacheStore.delete(keyId, cacheKey)`** — adds an explicit eviction primitive to `lib/cache/store.mjs`. Returns `boolean` (true if entry present and removed; false otherwise) and removes empty per-keyId namespace `Map` entries from the outer store for memory hygiene (matches the D38 `_activeSpawns` pattern). `server.mjs` D16 salvage path replaces `cacheStore.set(..., ttlMs=0)` (lazy tombstone that lived in the namespace `Map` until the next `get`/`peek` purged it) with `cacheStore.delete(...)` (immediate removal). Cache semantics unchanged — truncated responses still don't persist. ADR 0005 § "Cache write conditions" item 1 authority.
|
- **Part 1 — `CacheStore.delete(keyId, cacheKey)`** — adds an explicit eviction primitive to `lib/cache/store.mjs`. Returns `boolean` (true if entry present and removed; false otherwise) and removes empty per-keyId namespace `Map` entries from the outer store for memory hygiene (matches the D38 `_activeSpawns` pattern). `server.mjs` D16 salvage path replaces `cacheStore.set(..., ttlMs=0)` (lazy tombstone that lived in the namespace `Map` until the next `get`/`peek` purged it) with `cacheStore.delete(...)` (immediate removal). Cache semantics unchanged — truncated responses still don't persist. ADR 0005 § "Cache write conditions" item 1 authority.
|
||||||
@@ -45,6 +83,30 @@ All notable changes to OLP land here. Per `CLAUDE.md` release_kit overlay, this
|
|||||||
- **Authority:** ADR 0005 Amendment 8 (this commit); ADR 0005 Amendment 6 (D34 — original deferral note); GitHub issue #16 (round-6 F13 — sibling TOCTOU); ADR 0002 Amendment 6 (D38 — `tryAcquireSpawn` semantics that §7 coordination builds on); ADR 0004 Amendment 5 (D40 — observability pattern §11 extends); `CLAUDE.md` release_kit_overlay phase_rolling_mode — under Unreleased; CC 开发铁律 v1.6 § 10.x (design-only amendment; fresh-context reviewer not required per the Iron Rule 10 implementation-phase scope, documented in the amendment's procedural mechanism).
|
- **Authority:** ADR 0005 Amendment 8 (this commit); ADR 0005 Amendment 6 (D34 — original deferral note); GitHub issue #16 (round-6 F13 — sibling TOCTOU); ADR 0002 Amendment 6 (D38 — `tryAcquireSpawn` semantics that §7 coordination builds on); ADR 0004 Amendment 5 (D40 — observability pattern §11 extends); `CLAUDE.md` release_kit_overlay phase_rolling_mode — under Unreleased; CC 开发铁律 v1.6 § 10.x (design-only amendment; fresh-context reviewer not required per the Iron Rule 10 implementation-phase scope, documented in the amendment's procedural mechanism).
|
||||||
- **Test count:** 468 → 468 (no test change — design-only).
|
- **Test count:** 468 → 468 (no test change — design-only).
|
||||||
|
|
||||||
|
### Phase 1 cleanup release_kit checklist
|
||||||
|
|
||||||
|
- [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 (fresh-context opus full-pass) — PASS_WITH_MINOR, 0 P1/P2 findings
|
||||||
|
- [x] 16 of 17 pre-Phase-2 GitHub issues closed (#1-#15 and #17); #16 stays OPEN as v1.x tracker
|
||||||
|
- [x] Issue #16 status comment posted referencing ADR 0005 Amendment 8 design ratification
|
||||||
|
- [x] CHANGELOG "Unreleased" promoted to "## v0.1.1 — 2026-05-25" with D35-D42 entries
|
||||||
|
- [x] `package.json` bumped from 0.1.0 → 0.1.1
|
||||||
|
- [x] `docs/v1x-roadmap.md` created — 7 deferred items with anchors + start triggers
|
||||||
|
- [ ] Tag pushed (next step in this PR's lifecycle)
|
||||||
|
- [ ] `release.yml` triggered + GitHub Release created (auto on tag push; D37 phase_rolling_mode gate will pass because Unreleased is now sentinel-only)
|
||||||
|
|
||||||
|
### Known limitations carried to v1.x
|
||||||
|
|
||||||
|
Full list with code anchors + start triggers in [`docs/v1x-roadmap.md`](./docs/v1x-roadmap.md):
|
||||||
|
- Streaming-path singleflight (issue #16, ADR 0005 Amendment 8 design ratified)
|
||||||
|
- Multi-key auth (`lib/keys.mjs`)
|
||||||
|
- Soft-trigger reactivation (ADR 0004 Amendment 2)
|
||||||
|
- `/health` activeSpawns integration (ADR 0002 Amendment 6 forward note)
|
||||||
|
- Provider-level `cacheKeyFields` mask (ADR 0005 Amendment 7 forward note)
|
||||||
|
- Streaming-path SPAWN_FAILED salvage (bundled with #1 in v1.x)
|
||||||
|
- D40 AUTH_MISSING tuple test coverage (test polish)
|
||||||
|
|
||||||
## v0.1.0 — 2026-05-24
|
## v0.1.0 — 2026-05-24
|
||||||
|
|
||||||
### Phase 1 Close — Multi-provider proxy core
|
### Phase 1 Close — Multi-provider proxy core
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
## Amendments
|
## Amendments
|
||||||
|
|
||||||
|
> **Note on numbering.** Sequence is 1, 3, 4, 5, 6 — Amendment 2 was never written. The reserved slot was originally planned for a separate `maxConcurrent` ratification, but that content was folded into Amendment 1 (the retroactive contract-sync amendment) at filing time and the gap was not backfilled. The gap is intentional and load-bearing — no missing content; do not renumber Amendments 3+ to close it (cross-references to Amendment N from other docs would silently break).
|
||||||
|
|
||||||
### Amendment 6 — 2026-05-24: `maxConcurrent` runtime enforcement landed (D38, issue #1)
|
### Amendment 6 — 2026-05-24: `maxConcurrent` runtime enforcement landed (D38, issue #1)
|
||||||
|
|
||||||
- **Finding:** Amendment 1 (2026-05-23) ratified `maxSpawnTimeMs` into the Provider contract but explicitly noted that `hints.maxConcurrent` remained **declarative-only at v0.1** — type-validated at startup in `lib/providers/base.mjs` (`validateProvider` requires it to be a non-negative integer) but unenforced at runtime (no semaphore / in-flight counter / spawn queue in `server.mjs`). Cold-audit catch from D11 (commit `f659e29`): the diff-review reviewer grep-verified that the original ADR draft's claim "Enforced by the spawn-concurrency guard in `server.mjs`" was false. GitHub issue #1 was filed to track the gap. D38 closes that gap.
|
- **Finding:** Amendment 1 (2026-05-23) ratified `maxSpawnTimeMs` into the Provider contract but explicitly noted that `hints.maxConcurrent` remained **declarative-only at v0.1** — type-validated at startup in `lib/providers/base.mjs` (`validateProvider` requires it to be a non-negative integer) but unenforced at runtime (no semaphore / in-flight counter / spawn queue in `server.mjs`). Cold-audit catch from D11 (commit `f659e29`): the diff-review reviewer grep-verified that the original ADR draft's claim "Enforced by the spawn-concurrency guard in `server.mjs`" was false. GitHub issue #1 was filed to track the gap. D38 closes that gap.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
**Status:** Design ratified. Implementation deferred to v1.x.
|
**Status:** Design ratified. Implementation deferred to v1.x.
|
||||||
|
|
||||||
**Context.** Amendment 6 (D34) formally deferred streaming-path D4 singleflight participation with the note "the design alone warrants a dedicated ADR." Round-6 cold-audit F13 (filed as issue #16) raised the sibling TOCTOU window: `server.mjs:782 preCheckHit = await cacheStore.peek(...)` followed by streaming-branch entry at line 811 (gated on `!preCheckHit`) creates a race where, between peek and spawn, a concurrent populator can write the cache OR a TTL can expire. The streaming branch is path-locked at the moment of the peek result.
|
**Context.** Amendment 6 (D34) formally deferred streaming-path D4 singleflight participation with the note "the design alone warrants a dedicated ADR." Round-6 cold-audit F13 (filed as issue #16) raised the sibling TOCTOU window: `server.mjs:782 preCheckHit = await cacheStore.peek(...)` followed by the streaming-branch entry conditionals at lines 817–823 (the TODO anchor sits just above at line ~810 and is the navigable landmark; line numbers may drift across commits) creates a race where, between peek and spawn, a concurrent populator can write the cache OR a TTL can expire. The streaming branch is path-locked at the moment of the peek result.
|
||||||
|
|
||||||
This amendment ratifies the v1.x design so the implementation work has a single specification to follow.
|
This amendment ratifies the v1.x design so the implementation work has a single specification to follow.
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ This amendment ratifies the v1.x design so the implementation work has a single
|
|||||||
- For each `client ∈ attachedClients`: if `client.queueByteSize + chunkSize > PER_CLIENT_QUEUE_CAP` (default 1 MB), the client is disconnected with `STREAM_BACKPRESSURE` (see §8). Otherwise push the chunk into `client.queue`, update `queueByteSize`, fire `resolveNext` if pending.
|
- For each `client ∈ attachedClients`: if `client.queueByteSize + chunkSize > PER_CLIENT_QUEUE_CAP` (default 1 MB), the client is disconnected with `STREAM_BACKPRESSURE` (see §8). Otherwise push the chunk into `client.queue`, update `queueByteSize`, fire `resolveNext` if pending.
|
||||||
|
|
||||||
When the source iterator returns/throws/aborts, the tee task:
|
When the source iterator returns/throws/aborts, the tee task:
|
||||||
- On normal completion: writes `accumulatedChunks` to cache via the standard cache-write conditions (cacheable opt-out, truncated-not-cached, size cap — all from Amendment 1/3/5). Resolves all clients' `resolveNext` with their remaining queue then sentinel-marks `done`. Releases the D38 spawn slot once. Removes the entry from `_streamingInflight`.
|
- On normal completion: writes `accumulatedChunks` to cache via the standard cache-write conditions — `truncated-not-cached` from § Decision § "Cache write conditions" item 1; `cacheable=false` opt-out from Amendment 3; `claude -p --output-format text` wire-shape limitation from Amendment 5; size cap from Amendment 3. (Note: ADR 0005 has no Amendment 1 heading — the section §-Decision body item-1 is the source for `truncated-not-cached`, NOT a numbered amendment.) Resolves all clients' `resolveNext` with their remaining queue then sentinel-marks `done`. Releases the D38 spawn slot once. Removes the entry from `_streamingInflight`.
|
||||||
- On source error: rejects all clients with the error. Does NOT write cache. Releases the D38 spawn slot. Removes entry.
|
- On source error: rejects all clients with the error. Does NOT write cache. Releases the D38 spawn slot. Removes entry.
|
||||||
- On source abort (all clients disconnected): cancels the iterator via AbortController, releases the slot, removes entry. No cache write (partial response not persisted, matches D16 buffered-path SPAWN_FAILED salvage NOT applying to abort).
|
- On source abort (all clients disconnected): cancels the iterator via AbortController, releases the slot, removes entry. No cache write (partial response not persisted, matches D16 buffered-path SPAWN_FAILED salvage NOT applying to abort).
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "olp",
|
"name": "olp",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"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",
|
"main": "server.mjs",
|
||||||
|
|||||||
Reference in New Issue
Block a user