chore(release): v3.26.0 (#212)

* chore(release): v3.26.0 — maxTokens tells the truth, SPOT schema, release-job fix, ltBoot harness

Version 3.25.0 -> 3.26.0 (package.json; server.mjs reads VERSION from it, so /health and
/v1/models follow automatically). CHANGELOG's Unreleased section becomes v3.26.0.

Contents — five merged PRs, each with an independent fresh-context reviewer:

  #208  maxTokens aligned to the CLI registry (#195)      <- the only fleet-visible change
  #205  models.schema.json + CI validation (#196)
  #206  release.yml no-CHANGELOG path fix (#202)
  #204  ltBoot harness hardening + diagnostics (#199, #209)
  #207  cache-key guard comments (#200), AGENTS.md harness docs (#197)

The only user-visible change is advertised metadata: OpenClaw and other clients that read
maxTokens will see 64000/32000 instead of a uniform 16384. OCP's behavior is unchanged --
buildCliArgs passes no output-token flag, and max_completion_tokens appears nowhere in this
repo. No new endpoint, env var, CLI subcommand, or cli.js wire behavior. server.mjs is
untouched across the whole release, so ALIGNMENT.md requires no cli.js citation.

release_kit (Iron Rule 5.5) walked:
  - version_source package.json          bumped
  - changelog CHANGELOG.md               v3.26.0 section written
  - new file / SPOT / schema             models.schema.json documented in README
                                         (Available Models) and AGENTS.md (Key files)
  - Available Models table               no change needed; it carries no maxTokens column
  - Environment Variables / Endpoints    no additions this release
  - bootstrap_quirk_policy               no new one-time migration quirk

Remaining v3.25.0 mentions in README/docs are historical (describing what changed in that
release) and are correct as written; verified rather than bulk-replaced.

Suite: 462 passed, 0 failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gbqUZ8HfBZpjjbzQ85oH8

* docs(release): correct a false claim in the v3.26.0 notes and disclose three gaps

Release review found four problems, all in the CHANGELOG text — which for a release PR
IS the deliverable, since release.yml copies it verbatim into the GitHub Release body.

1. "instead of a uniform 16384" was FALSE.

    git show v3.25.0:models.json  ->  six entries 16384, claude-haiku-4-5-20251001 8192
    distinct prior values: [8192, 16384]     uniform? False

Issue #195's own title says "for every Opus/Sonnet entry" — it never claimed haiku. The
framing also understated haiku, which moved from a lower base. Corrected, and stated: every
model except claude-sonnet-4-6 (1.95x) moves by the same 3.91x, haiku included.

(Review called haiku "the largest change in the release". Verified: it is a TIE at 3.91x,
not the largest alone — 16384->64000 is the same multiplier. The entry says so.)

2. models.schema.json contradicted this release's own notes.

It shipped in this release (#205) saying maxTokens "bounds request and compaction budgets".
The CHANGELOG correctly says maxTokens does not affect behavior. The schema's compaction
half is wrong: in OpenClaw 2026.7.1 both the compaction trigger and the summarisation chunk
size derive from contextWindow (minus reserveTokensFloor / softThreshold), never from
maxTokens. Fixed the schema rather than the CHANGELOG, since the CHANGELOG was right.

This makes the release PR touch one non-version file. Deliberate: shipping two canonical
documents that contradict each other is worse than a slightly wider release diff, and the
schema is published in this same release.

3. #203 was omitted, and the ltBoot entry read as "harness flakiness fixed".

42/200 -> 200/200 is true and #203 is still OPEN — with four sightings, one of them on #205
INSIDE this release. The entry made exactly this disclosure for ocp-connect (#210) and not
for the bug the harness was built to chase. Now states it is not fixed, and points at #211.

4. contextWindow is wrong by the same registry this release cites.

    claude-opus-5 / -4-8 / -4-7 / claude-sonnet-5   registry window:1e6   models.json 200000

Publishing "the SPOT tells the truth" with a 5x understatement in the adjacent field is the
kind of thing that ages badly. Unlike maxTokens it is NOT a safe metadata fix —
derivePromptCharBudget takes max(contextWindow) x 3 across ALL entries, so one 1M model
takes MAX_PROMPT_CHARS from 600k to 3M for every model including a genuinely-200k haiku.
Filed as #213 (needs per-model budgets, ADR-level) and disclosed in the notes.

Also: `claude-haiku-4-5` appeared where the models.json id is `claude-haiku-4-5-20251001` —
the exact legacyAlias-vs-id confusion #208's test file exists to prevent. All three
occurrences now use the full id.

Verified: models.schema.json still parses; suite 462 passed, 0 failed; release.yml's awk
extraction on the corrected file yields 6348 bytes, correct section, terminating at v3.25.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gbqUZ8HfBZpjjbzQ85oH8

* docs(release): state the correction as fact, not as edit history

Review's style point, taken. The v3.26.0 section has never been published — no tag
exists — so release.yml's copy into the GitHub Release body is the FIRST time any
reader sees this text. "as an earlier draft of this entry claimed" corrects a claim
they never saw; it is internal editing history leaking into a public artifact. The
correction belongs in the commit record, where it already is in full.

Also split the 3.91x ratio into its own sentence — as an appositive it had to reach
back across an interrupting clause to find what it modified.

No factual change. Suite: 462 passed, 0 failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gbqUZ8HfBZpjjbzQ85oH8

---------

Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dtzp555-max
2026-07-27 21:28:18 +10:00
committed by GitHub
co-authored by taodeng Claude Opus 5
parent 92787dcced
commit b0bcfe0767
3 changed files with 25 additions and 3 deletions
+23 -1
View File
@@ -2,9 +2,31 @@
## Unreleased ## Unreleased
## v3.26.0 — 2026-07-27
Maintenance release. One user-visible change — advertised `maxTokens` now tells the truth — and four rounds of repairs to the machinery that is supposed to catch mistakes: a schema for the model SPOT, a release-job bug that would have shipped an empty release body, and the integration-test harness that had been failing 4 runs in 5 without anyone noticing.
Every PR carried an independent fresh-context reviewer (Iron Rule 10). Two reviewers refuted the author's stated rationale while the change itself stood; in both cases the rationale was rewritten rather than the finding waved off, and one reviewer retracted its own earlier finding after the evidence was re-derived. `server.mjs` is untouched in this release, so no `cli.js` citation applies.
### Changed ### Changed
- **`maxTokens` now matches the CLI registry instead of a uniform 16384 (#195).** Every Opus entry and `claude-sonnet-5` go to **64000**, `claude-sonnet-4-6` and `claude-haiku-4-5` to **32000** — the `max_output_tokens.default` each model declares in the compiled CLI 2.1.220 registry. This corrects **advertised metadata only**: `models.json` is the SPOT (ADR 0003) and every value in it should be the truth about the model. **It changes nothing about how OCP behaves.** OCP never enforces `maxTokens``buildCliArgs` passes no output-token flag to the CLI at all — and OpenClaw addresses a local OCP over `openai-completions`, whose request field (`max_completion_tokens`) appears nowhere in this repo. The value is consumed only by clients that choose to honour it, via `setup.mjs` / `scripts/sync-openclaw.mjs` / `ocp-connect`. **Expect no change in answer length or quota burn.** `ocp-connect`'s independent family table moves to the floor over each family's current `models.json` members (opus 64000, sonnet 32000, haiku 32000), since prefixes cannot distinguish versions. Its unknown-id fallback stays at **8192** — the registry's global minimum, held by `claude-3-5-haiku` and `claude-3-5-sonnet`, which are the only real ids that reach it (`claude-3-5-*` matches no family prefix). - **`maxTokens` now matches the CLI registry (#195).** The previous values were not uniform: six entries were 16384 and `claude-haiku-4-5-20251001` was 8192. Every Opus entry and `claude-sonnet-5` go to **64000**, `claude-sonnet-4-6` and `claude-haiku-4-5-20251001` to **32000** — the `max_output_tokens.default` each model declares in the compiled CLI 2.1.220 registry. Every model except `claude-sonnet-4-6` (1.95x) moves by the same 3.91x — haiku included, from its lower base. This corrects **advertised metadata only**: `models.json` is the SPOT (ADR 0003) and every value in it should be the truth about the model. **It changes nothing about how OCP behaves.** OCP never enforces `maxTokens``buildCliArgs` passes no output-token flag to the CLI at all — and OpenClaw addresses a local OCP over `openai-completions`, whose request field (`max_completion_tokens`) appears nowhere in this repo. The value is consumed only by clients that choose to honour it, via `setup.mjs` / `scripts/sync-openclaw.mjs` / `ocp-connect`. **Expect no change in answer length or quota burn.** `ocp-connect`'s independent family table moves to the floor over each family's current `models.json` members (opus 64000, sonnet 32000, haiku 32000), since prefixes cannot distinguish versions. Its unknown-id fallback stays at **8192** — the registry's global minimum, held by `claude-3-5-haiku` and `claude-3-5-sonnet`, which are the only real ids that reach it (`claude-3-5-*` matches no family prefix).
### Added
- **`models.schema.json` — the model SPOT now has a schema, enforced in CI (#196).** `models.json` declares it via `$schema`, and `test-features.mjs` validates the SPOT against it using the repo's **own** `validateJsonSchema` from `lib/structured-output.mjs` — no new dependency. A malformed entry now fails the build instead of surfacing downstream in OpenClaw. The schema's description names exactly which keywords that validator enforces and which it **silently ignores** (`minimum`, `maxLength`, `pattern`, `uniqueItems`, …), so nobody adds a constraint that buys nothing; those go in `test-features.mjs` instead. Guard tests cover 8 distinct corruptions plus uniqueness and whitespace on every name field.
### Fixed
- **`release.yml` would have produced an empty release body on any repo state without `CHANGELOG.md` (#202).** The no-changelog branch set an output pointing at a notes file it never wrote, and the create step then read a missing path. Rare, but it fails exactly when you least want it to — during a release. The branch now writes the file.
- **The `ltBoot` integration harness was failing 4 runs in 5 (#199, #209).** Measured with a control arm — full suite × 4 concurrent × 50 rounds against unmodified `main` and against the fix — clean runs went **42/200 → 200/200**, with `EADDRINUSE` **246 → 0**. Four distinct races: two tests gated on a stdout marker and then asserted on a **stderr** line written 12 `console.log` calls later (different pipes, nothing ordering them); every fixed port replaced with `ltFreePort()` (the old 3932139364 range sits *inside* Linux's default ephemeral range, so CI was more exposed than a Mac); `close` instead of `exit` where a test reads a buffer after termination; and retrying teardown against grandchildren still writing into the temp dir. **#203 is NOT fixed and remains open** — it has never reproduced on macOS (0 across both 200-run arms) and all four sightings are Linux CI, one of them on #205 inside this very release. #211 adds a manual `workflow_dispatch` harness to hunt it on Linux with a pre-#204 positive control. Diagnostics now print exit/signal/closed/elapsed/Node version plus a head+tail sample of both streams — sized so the sample provably reaches the one line that distinguishes "booted" from "refused", with a test pinning that budget so it cannot silently degrade.
### Internal
- **Guard comments on the asymmetric cache-key construction (#200)** — `structuredHash` and `dedupKey` carry deliberately different guards, and the resemblance invites a "cleanup" that would collapse them. Now documented at the site.
- **`AGENTS.md` § "Testing: reaching faults inside `server.mjs`" (#197)** — writes up the fault-injection method these fixes needed, including the `--stack-size` lever and why running a flaky scenario *in isolation* removes the very concurrency that causes it.
- **`ocp-connect` documentation corrections.** Its family table is the floor over each family's *current* `models.json` members — not over the registry family — and its unknown-id fallback stays at 8192, the registry's global minimum. Both had comments asserting otherwise. Its model table and fallback remain **untested**; tracked as #210.
- **Known gap, deliberately not fixed here: `contextWindow` does *not* match the registry (#213).** The same CLI 2.1.220 bundle declares `window:1e6, native_1m:true` for `claude-opus-5`/`-4-8`/`-4-7` and `claude-sonnet-5`, while `models.json` says 200000. Unlike `maxTokens`, this cannot be corrected as metadata: `derivePromptCharBudget` takes `max(contextWindow) × 3` across **all** entries, so one 1M model would raise `MAX_PROMPT_CHARS` from 600k to 3M for every model — including `claude-haiku-4-5-20251001`, which really is 200k native — turning clean OCP-side truncation into upstream API rejections. Fixing it needs per-model prompt budgets (ADR-level). Recorded so this release's "the SPOT tells the truth" claim is not read as covering it.
## v3.25.0 — 2026-07-27 ## v3.25.0 — 2026-07-27
+1 -1
View File
@@ -46,7 +46,7 @@
}, },
"maxTokens": { "maxTokens": {
"type": "integer", "type": "integer",
"description": "Advertised output cap. OCP does not enforce it; it is propagated to OpenClaw (via setup.mjs / scripts/sync-openclaw.mjs) where it bounds request and compaction budgets." "description": "Advertised output cap. OCP does not enforce it: buildCliArgs passes no output-token flag to the CLI. It is propagated to OpenClaw (via setup.mjs / scripts/sync-openclaw.mjs) where it bounds REQUEST budgets only. It does NOT affect compaction: both the compaction trigger and the summarisation chunk size derive from contextWindow (minus reserveTokensFloor / softThreshold), never from this field. Verified against OpenClaw 2026.7.1."
} }
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "open-claude-proxy", "name": "open-claude-proxy",
"version": "3.25.0", "version": "3.26.0",
"description": "OCP (Open Claude Proxy) — use your Claude Pro/Max subscription as an OpenAI-compatible API for any IDE. Works with Cline, OpenCode, Aider, Continue.dev, OpenClaw, and more.", "description": "OCP (Open Claude Proxy) — use your Claude Pro/Max subscription as an OpenAI-compatible API for any IDE. Works with Cline, OpenCode, Aider, Continue.dev, OpenClaw, and more.",
"type": "module", "type": "module",
"bin": { "bin": {