Repository navigation
Conversation
- Stop the run on a Node below engines.node, before collecting a file. Below the floor, failures came from the engine (node:sqlite, Intl.DurationFormat, ICU strings) and looked like code regressions. .node-version names the Node CI uses. - Add a CI job that runs the unit and mock suites on Node 24, the floor engines.node promises but no job ran. - The zh fallback duration unit is now 分钟, the platform's own narrow output, so the meter row reads the same with or without Intl.DurationFormat. The DurationFormat tests restore the engine as they found it, rather than leaving a stand-in installed or asserting the engine ships the constructor. - Move the node:sqlite store fixture out of the helpers that the jsdom tests share, into test/support/opencode-store-fixture.ts. - Add an architecture test that walks the client bundle's runtime import graph from settings-page.tsx. It forbids node built-ins, the cordis runtime, pi, and process.env. Checked by planting a violation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…n discovery - A rejected internal-route mount ran from a `void` IIFE with no catch, so a Google bridge failure became an unhandled rejection, which Node's default mode answers by exiting the process. mountInternalRoutes now owns the mount and its withdrawal, and reports a rejection. - Three early exits in registerResponsesProvider (internalRoutes off, every route declared, no llm-pi-ai) answered `undefined` after the Gemini bridges had already registered. That left them with no disposer, and the next reload failed DUPLICATE_ADAPTER. They now hand back the bridges' disposer. - A mount that failed to start, or that captured nothing, kept its fiber and every route it had registered. Both paths now release the routes and dispose the fiber. - Model discovery was registered on every activation, and the host's duplicate refusal was swallowed, so the first activation's settings answered for the life of the process. It is now registered once per root and answers from the latest activation's settings. Each namespace registers on its own, so one refusal no longer skips the rest. - Move three doc blocks back above the functions they describe. Each fix has a regression test. The two mount tests fail without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…e the suite Request path and meter: - Price a turn on its route's plane. Go-first lookups priced every Zen turn on deepseek-v4-pro at 0.66/1.98 instead of 1.74/3.48. - The listing and model-info patches now act only on the routes this plugin claims. Before, a direct anthropic or openai route lost rows the OpenCode routing called "unservable", and a refused foreign id was answered with OpenCode's catalog. - A relay's Go /models is answered with the Go catalog. The enrichment re-checked the URL against the default gateway markers and fell back to Zen. - The free-model check reads a Request-carried body. That is how DSH sends a turn, and every keyless free turn was reported as a missing credential. The body is now read once for both uses. - The meter's session fallback is the session that most recently ran a turn, not the most recently created one. - A captured key's tier comes from the observed URL, then the route, and never the key's prefix. OpenCode issues oc_sk_ keys for Go, so a working Go key was filed under Zen. An OpenAI sk- key on a claimed relay was filed under Go. Suite isolation: - The unit and mock suites refuse non-loopback requests. Each unit run sent 54 requests to models.opencode.ai through the catalog's background revalidation, so on a networked runner a result could depend on the vendor's live catalog. - Captured keys, session spend and the live catalog are reset after every test (resetCatalogState is new). Shuffled runs failed catalog cases on seeds 42 and 1234. test:shuffle runs the suite in random order, and the Node 24 CI job uses it. Each behaviour change has a test that fails without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…egration - The card's store-inspection row called remote.opencodeStore.inspect, but no client contribution carried that namespace's descriptor. The row reported "unavailable" on a host that had the service. storeRemote now carries it, with a whitelist codec, and the client mounts it. - The host/client parity test missed this because it matched only a string literal in super(ctx, "name"), and the store passes a constant. It now resolves constants, and checks every declared Remote method against a client descriptor, not just every namespace. - inspectStore parses through the whitelist instead of a cast, so a field the host did not mean to send (a token) is dropped. An ok:false envelope reports the remote's own message. - The credential reader's legacy-row fallback was uncorrelated: one flagged opencode-go row hid every legacy opencode row, and the Zen key disappeared. The fallback is now per integration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
… keeps - AGENTS.md's repo map described nine modules this build does not have (the Console login, token store, org cache and sign-in row). They are replaced with one line saying sign-in is v2 work. The go-limits duplication note is gone, because attachAllowance calls allowanceFor. adapter-replacement.ts is marked as not wired. The client-bundle line names the boundary test. - CONTRIBUTING.md documents the engine floor, test:shuffle and test:mock, the offline guard, the per-test state reset, where host-only fixtures live, and that a regression test must fail without its fix. - The no-credential warning no longer tells the reader to "sign in through the settings card", which this build does not have. It points at readOpencodeStore instead, and a test asserts the advice. - CLIENT_BUDGET is raised from 128 to 132 KB for the store descriptor and its parser (about 1.2 KB of source, not a dependency), following the gate's own instruction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
docs/improvement-plan.md groups the review's findings by cause and orders the fixes in nine phases after this one. Each phase lists its problems, its steps, the test that has to fail first, its acceptance criteria and any decision the owner needs to make. Findings are marked "measured" (reproduced) or "traced" (read in the code). Among the measured ones: the picker and dispatch derive reasoning levels differently for 9 of 95 catalog models. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Replace docs/improvement-plan.md with the plan of record. It now holds: - the owner's decisions (D1-D11); - what the DeepSeek Harness host supports, with references into packages/llm, llm-pi-ai, session-controller, gateway and ui-settings-models; - the defects this audit found that are not yet fixed; - the target architecture and the phases, one PR each, with a status table that each PR updates. The decisions that change the code: - Settings offers the whole catalog, and the composer offers only the declared models. - The plugin never writes the user's profile and follows the user's configuration at dispatch. - The adapter patch exists to merge provider modes and nothing else. It is generalized to every mode, and its catalog fill is removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Investigation of the host's source and of the pi catalog it pins (1.1.0) changed the routing design. - llm-pi-ai resolves `api` and `baseUrl` per model, and pi's installed `opencode` catalog already spans Anthropic, Google, Completions and Responses with per-protocol endpoints. One route serves every mode for every model pi knows. - The plugin fills only three gaps: models newer than pi's catalog (including all Gemini on Go), endpoint drift, and profile-level `api`/`baseURL` collapsing the modes. - The new design is one unregistered catalog adapter per plane, keyed by the user's route id, and the adapter patch (merge-modes) delegates only gap models to it. That deletes the hidden routes, the listing hide, the stream redirect, the child mount and the Gemini bridge registration. - A real-host test harness (P-T1) comes before any of it. - One upstream change (per-entry `api`/`baseURL` in llm-pi-ai, U1) would remove the routing layer entirely. It would also let Settings save a model pi doesn't know, which pi-ai's strict write validation rejects today. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
pi-ai registers exactly the providers in its resolved config, and the fiber keeps whatever the internal/config waterfall returns, while the config editor writes the raw value. A prepended listener that resolves pi-ai's config without opencode/opencode-go therefore keeps pi-ai from claiming them, without touching the user's file, and the plugin registers its own PiAiAdapter under the same ids through the public API. Measured on the real host with pi 1.1.0 and the harness's patch: both routes held by the plugin, pi-ai's other routes unchanged, every protocol on both planes (Gemini on Go included) sent to its own endpoint, a catalog-unknown model id saved, listed and dispatched, and both routes handed back to pi-ai on release. Replaces the upstream asks (no upstream changes) and the save-gate design, which is kept only as the fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
A nine-lens review of the routing design, with two independent skeptics per finding (78 of 82 upheld), changed five things before any code moves: - Settings reads pi-ai's resolved config, so a read-only wrapper on settings.describe puts the plane entries back into the displayed value; writes were never affected, the Models page edits by path. - The route claim gets an explicit lifecycle: commits are told from validations by identity, reconcile runs on commit, mount and teardown are ordered, and pi-ai restarts at most once per transition. - The plugin's adapter is built from public pieces only, with pi-ai's credential rule and no captured keys on the adapter path. - The protocol comes from the catalog map, never from a guess at the model's name; metadata and levels are catalog first. - Releases stay on 1.x, phases land as stacked pull requests, and a real host harness plus a binary e2e job pin the behaviour first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
- The deprecated @viztor/dsh-opencode wrapper re-exported a `default` the
barrel does not have, an ESM link error on every host load. It now
forwards `export *` only, written by one shared helper that a test links
against the built barrel in a real Node process.
- isZenProvider("opencode-google") answered false: "go" inside "google"
read as the Go plane. It now uses the plane rule the catalog already has.
- enrichModelsResponse answered a 401, 403, 429 or 5xx with a 200 catalog.
Those statuses now pass through; a 404 is still filled from the catalog,
because the Go plane's inference base has no /models of its own.
- The warning colour named a token the host does not define, so warnings
rendered as caption text. They now use --dsw-alias-state-warn-label.
- The settings spinner only animated while the meter was mounted; the
settings surface now carries its own keyframes.
- The stream hook wrote debugFile with debug off. debug is the switch and
debugFile only where it writes, the same gate the fetch patch uses.
- The purge row reported the host's own { ok: false } failure as "not a
purge result" and cast the answer; it now shows the host's message and
parses through the contract's whitelisting parser.
- The endpoint copy described modern as /inference/v1, which the plugin
never sends. It now names the per-protocol inference family, and auto as
its alias, which is what the code already did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
- Delete adapter-replacement.ts and its test. Nothing imported it, and deleting another plugin's registry entry is not a host API; the engineering notes record why, and what the plugin does instead. A gate fails the build if src/ writes the llm registry map directly. - Delete the stream hook's `prepared` handling: the host passes the prepared dispatch as its own argument and never reads options.prepared. - Untrack .freebuff/ and ignore it. - The settings partition test walks Config.dict, which is how debugFile went missing from it; a manifest test checks cordis.patch.yml against the schema and the field registry, and the manifest's phantom showUsagePrice, wrong marker text and incomplete lists are fixed. - utils/retry.ts takes its timer and logger as parameters, and the utils purity gate now also rejects console and global timers, walking the folder recursively. - tool-fallback reads free-tier ids from the request's own plane (Go iff opencode-go or opencode-go-*) and loses its unreachable Anthropic branch. A Zen-only free model is no longer treated as free on Go. - test/support/src.ts is the one door tests use into src/, so later module moves touch one file; CONTRIBUTING.md states the rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
This was referenced Oct 23, 2026
The vendor added kimi-k3.1-pro to the Go plane, so `catalog freshness` went red on every branch of this stack. This takes the two generated files exactly as the nightly refresh produced them (#111), with no hand edits, and updates the counts that hard-code the catalog's size: the Go shim test (28 -> 29), the plane table in redirect-planes.md (Go served 28 -> 29, the no-SDK Go cell 17 -> 18), and the Go completions list in both READMEs. The listed half of "29 served / 33 listed" is models.dev's count, inferred from the one added entry, because models.dev cannot be reached from here. It no-ops once main carries #111. P-T2 turns these counts into invariants so a refresh stops needing this. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The vendor renamed the Go plane's one Gemini model (dropping its contributor suffix, halving its price and publishing an allowance for it where the limits table had none) and added a free model with no SDK, so `catalog freshness` went red on every branch of this stack. This takes the two generated files exactly as the nightly refresh produced them (#111), with no hand edits, and follows them: - the Go Gemini fixtures in six test files (attachment-services, catalog, go-google, go-google-prepare, models-discovery, responses-routes) now name the renamed id, since each means "the Go Gemini model the catalog serves"; - the usage panel test built its unknown allowance from the table's one unpriced row, which the vendor has now priced, so it builds the `Number.NaN` allowance the generator emits itself; - the Go shim count in catalog.test.ts (29 -> 30); - redirect-planes.md: Go 29 -> 30 served, the no-SDK Go cell 18 -> 19, and "0 of 29" -> "0 of 30" in the prose; - both READMEs: the renamed Gemini id, and the new model in the Go completions list, since it declares no SDK. The listed half of "30 served / 34 listed" is models.dev's count, inferred from one rename (no change) and one addition (+1), because models.dev cannot be reached from here. The dated S0 measurement row in improvement-plan.md keeps the id it was measured with. It no-ops once main carries #111. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The live routing suite picks its free-tier subjects from the catalog by asking the gateway, but it counted "400 Upstream request failed: Model is unavailable" as an observable answer. The upstream withdrew nemotron-3-ultra-free while the catalog still lists it, so the picker chose it and two cases asserted on a model the gateway no longer serves; the reachability case also failed on a 429 throttle. A withdrawn model (that 400, or a 410) is now skipped like a throttled one. The free-tier routing case only accepts a candidate whose answer is the free-tier gate it asserts, so an unmetered model cannot become its subject, and the reachability walk moves past gated, withdrawn and throttled candidates before it reports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The vendor moves its model catalog, its Go limits page and its CLI version almost daily. Each move turned every open pull request red, although none of them caused it: vendor drift is not a regression of the change under test. A pull request now fails a freshness check only when its diff changes that check's generator code: the script, every local module it loads, transitively, and the pinned version file for the CLI check. scripts/freshness-scope.ts derives those inputs from the sources and makes the call, so a new import moves them without a list to edit. Any other pull request reports drift as a warning, as a push to main already did. The offline check that every copy of the CLI version agrees with the pin still gates every pull request, since only the repository can break it. The gates fail closed: a lost scope answer gates rather than skips. The nightly run still regenerates the two tables and proposes the refresh as its own pull request, and warns on the CLI version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The vendor retired `deepseek-v4-flash` from the Zen plane (it stays on Go). This pull request changes the catalog generator's own code, so under the freshness scoping it carries the refresh itself. This takes `src/catalog-data.ts` exactly as the nightly refresh produced it (#111), with no hand edits; `src/go-limits-data.ts` did not change. It then updates the counts that still hard-code the catalog's size: - the Zen shim count in catalog.test.ts (82 -> 81); - redirect-planes.md: Zen served 82 -> 81, the no-SDK Zen cell 25 -> 24, and "0 of 82" -> "0 of 81" in the prose; - protocol-routing-and-merge.md: the per-protocol shares now read "of 81", with completions at 24; - both READMEs: the no-SDK row is 24 and the active total is 81. The Chinese table had read 27 before this change, and now matches the English one. "127 listed" is unchanged, because the vendor retires a model by marking it `status: "deprecated"`, which keeps it listed. This could not be confirmed against models.dev, which cannot be reached from here. It no-ops once main carries #111. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…-mendel-bctz9n-p1b
The walk's fixture held the text `await import("../src/lazy.ts")`. The
test tree's own architecture gate, which starts on the next branch of
this stack, reads a dynamic `src` import anywhere in a test file's text,
including inside a string. It counted that fixture line as a test
bypassing `test/support/src.ts`, so every branch above this one failed
the gate once this pull request was merged into it.
The case is about the dynamic form, not about `src`, so the import now
names `./lazy.ts` beside the script. The walk resolves it from the
importing file's own directory, which is the same rule, and the expected
inputs follow it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…-mendel-bctz9n-p1b
The copy scan's file filter lived in the top-level script, where nothing could exercise it. It now sits in scripts/vendor-version.ts beside the other rules, with cases of its own, and a test keeps its list equal to freshness-scope's. Because the script imports that module, it is now an input of the cli:version check, and the strict input list says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The live suite's local modelGone rule gave way to main's verdict module in the merge. Its one shape main lacked, a 400 whose body says the upstream withdrew the model, now lives in retiredAtTheGateway with a unit case, so the free-tier walk and the subject pickers skip it instead of failing on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Main's test-system page predates the offline guard, the per-test reset and the engine floor: it placed the store fixture in the shared helpers and called the plane-lookup world per file. It now says where the store fixture lives and why, that a live-catalog world is installed per test, and what the CLI-version rules cover. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Taking main's usableAsSubject rule in the merge dropped the picker's accept argument, so the free-tier case could pick an unmetered model and assert the gate on a 200. The case's own narrowing now applies after the shared rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Main moved to 1.8.0 and onto the harness's alpha track while the stack was open, and landed several things the plan had scheduled. The plan of record now says so: D14' and D22' replace the pi 1.1.0 and rc.2 pins, D17 restates pi-ai's new defaults, D23 records the freshness scoping, D24 and D25 adopt main's debug gate and tool-fallback plane, and D9, D16 and D19 stand with notes. F10 is gone on pi 1.3. A new phase P-R3 (honest refusals) follows P-T3, each phase has its restack adjustment, the status table shows the restack, and the two community plugins' lessons are a ranked table with what not to adopt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Main and this branch each raised the tripwire from 128 to 132 KB, each measured without the other's surface. Merged, the client is 135604 bytes, about 0.4 KB over; the owner's standing rule for growth like this is to raise the ceiling, not cut content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Close the restack review's findings on #105. Every change is prose, a comment or a log line; no behaviour moves, so no test is added. - ci.yml: the pnpm/action-setup comment no longer quotes a pnpm version; it names the `packageManager` field, which main's bump had made stale. release.yml carries the same stale sentence on main and is left to a main-side follow-up. - scripts/freshness-scope.ts: the GENERATED_OUTPUTS and dataInputs docs name scripts/vendor-version.ts (GENERATED_TABLES, PINNED_VERSION), where the copy and the regular expression now live. - test/e2e/protocol-routing.e2e.ts: the free-tier walk's report names the causes that can reach it (gated, withdrawn, refused for the account, never answered); a throttled walk skips, so "throttled" is gone. - README pair: the Chinese file now says what the English says about 403 FreeTierError (the headers are not its cause and the patch does not open the free tier), carries the Auto Review route clause and the two paragraphs on the API-key-only build and the host restart; the English yaml fence drops the nonexistent hiddenModels key. - README pair: the compatibility section restates the typert peer range package.json declares and what its two clauses admit. - docs/improvement-plan.md: F2, G1 and G2 carry the pi 1.1.0 restack note; the sources line names both harness tags; the P1a-P2 test matrix says the wrapper is retired; P0's status row counts ten defect fixes. - docs/protocol-routing-and-merge.md, docs/redirect-planes.md: the count tables are dated 2026-10-31 (the shipped shim), apart from the documents' measurement stamps; both READMEs name `catalog:shim -- --write` as the regeneration command. - AGENTS.md: the What-moved table names src/utils/retry.ts; the coverage line points at vite.config.ts instead of quoting stale thresholds. - CONTRIBUTING.md: the restart check names CARD_FIELDS rather than a field count. - docs/testing.md: rule 1 counts an upstream's 400 "Model is unavailable" as a retirement, and rule 2 says the body, not the status, makes it one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Close the second review round's findings on the restacked P0. Docs only; no generated file is touched. - both-kept-2-R2-1: docs/deep-dive.md no longer names the retired ids the shim was said to suppress (main's regenerated shim serves one of them on Zen). It states the rule instead: a retired model is a row the registry marks deprecated, the generator drops it per plane, and ids are not restated; the enrichment item says "registry-deprecated rows". - rules-docs-2-R2-1: the PR body is replaced at push time from the updated draft, with the verification rows re-measured on this head and a restack section (what merged from main, what this PR dropped, the main-side follow-ups). Nothing is pushed here. - rules-docs-2-R2-2: the plan's defects table is retitled to where each defect now stands; the four rows main fixed are struck with the fix named, the purge row keeps only what is still open (a RemoteError object shows the generic message, P1a), and D19 records that the README's hiddenModels was removed in P0. - rules-docs-2-R2-3: README.zh-CN.md's merge rule follows the English and the code: a row is dropped only when the registry marks it deprecated, not when a per-provider list names it. One sentence, so the pairing gate's counts are unchanged. - rules-docs-2-R2-4: CONTRIBUTING.md no longer contradicts the repository: warnings are reported and gate in P12 (as its own command list says); a manual release creates the GitHub Release and never touches CHANGELOG.md; the release step points at the "Verified on DeepSeek Harness" line in both READMEs; the e2e section lists all five files. - rules-docs-2-R2-5: both READMEs drop the test total nothing pinned; engineering-notes.md's "every count" paragraph records it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The third review round of the P0 restack. Each outcome: - The meter mock-ups in both READMEs and both quota-meter guides paired one model with another model's monthly allowance. They now name the model whose row the figures are, and the panel mock-up's rate line prints that model's catalog rates in the format the panel uses. A new catalog test reads every "<id> Go $a · Plus $b" figure in the four documents back against the generated allowance table; it failed on the old mock-ups and holds a known minimum of matches, so a regex that stops matching cannot pass as clean. - engineering-notes: the "deeper half" measurement is scoped to the Go plane it was taken on. Both ids are Zen rows and neither has a row in the Go catalog, which is what the plane-aware lookup misses; the sentence no longer claims they are absent from both shims. - deep-dive: the two "up to" figures for context window and max output are dropped, per the same file's rule that counts which move with the vendor are not restated. - docs/README.md indexes every document in the directory: the test system guide, upstream findings, the CLI API note, the parity plan, and the plugin page pair, whose two languages the opening sentence now names. No generated file moves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…nto claude/vigilant-mendel-bctz9n-p1a Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The merge resolution read the RemoteError's message by property access, which the lint gate's prefer-destructuring rule rejects as an error, and left the merged host-tokens test unformatted. Same behaviour, now through the gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Outcomes of the merge review: - both-kept-1-F1, resolutions-1-P1A-2, rules-docs-1-P1A-DOCS-1: docs/redirect-planes.md now states D19 (`auto`, the default, is an alias of `modern`; `legacy` pins the zen family) instead of "follows the catalog". The models-discovery repair comment is left for P-R1, which deletes that block, and is named in the PR's follow-ups. - resolutions-1-P1A-1: the catalog's refusal describe gains the Zen-plane 404 fill, the non-JSON 200 answer, and a retry-after header that must survive the passthrough (mutation-checked). - resolutions-1-P1A-3: the plan's defect row for the RemoteError purge message is struck as fixed by P1a. - rules-docs-1-P1A-DOCS-2: the plan's status and restack rows name the warning token's dropped fallback, matching the build-order item. - rules-docs-1-P1A-DOCS-4: the host-tokens header names usage-pill among the meter files the card scan leaves out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
- fixed: rules-docs-2-P1A-1 — the host-tokens header drops the template clause (no meter file builds a token name from a template) and names the measured reasons: usage-pill.tsx would pass the scan; usage-ui.ts and usage-panel.tsx each spell the `--dsw-alias-state-*` wildcard in prose, and usage-ui.ts names `--dsw-radius-full` behind a literal 999px fallback. CARD_FILES is unchanged. - fixed: rules-docs-2-P1A-2 — the plan's status row, struck defect row, build-order item and restack row name the three refusal-passthrough test cases P1a adds (the Zen-plane 404 fill, the non-JSON 200 answer, the retry-after passthrough); the passthrough itself is on main (#133). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…a' into claude/vigilant-mendel-bctz9n-p1b Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
P1b's divergent-catalog seed and main's synthetic rows (#138) built the same thing twice, and main's copy imported src directly. They are now one module, test/support/catalogs.ts, which reaches src through test/support/src.ts: the seed is built from main's payload builder, and the plane-lookup and plane-divergence tests take their src names from the door too (coreToolDecision is added to it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The settings registry and the manifest still said the file is written only while debug is on. Under main's rule, which this stack adopted as D24, naming debugFile writes both halves of the log and debug governs the console alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
ultracite 8.1.0, which main brought in, reports a then() callback that returns nothing as an error. The backoff case awaits the sleep in an async callback instead; what it asserts is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The status table and the P1b section say what the merge of P1a kept: main's tool-fallback plane rule (D25) with only the Anthropic schemas deleted, and one catalogue fixture behind the door. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
The id is the test's data; the comment describes the rule it shows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Closes the review of the restacked P1b head. - free-tier-contract: the comment states D25 (the injector reads its plane from the URL, with the plane-blind row as fallback), not the dropped route rule. No assertion changes. - tool-fallback: the shipped-shim fallback case asserts its premise (the id is free on Zen and absent from the Go catalog), so a regeneration that lists it on Go fails loudly instead of leaving the case vacuous. Checked by seeding the id onto Go: the premise assertion fails. - improvement-plan: the six defect rows P1b resolves are struck and marked "Fixed by P1b", with the pre-fix locations kept. - AGENTS.md: the retry.ts row is in the past tense; it no longer says P1b has yet to move the timer and console out. - testing.md and the catalogs fixture: "like every other support module" becomes "like the other fixtures"; the setup file names the defining modules directly because it also loads in the jsdom files. CONTRIBUTING's exception list is left to P2, which names the setup file in its gate. - The #107 body (item 6, the behaviour-change section, the model id and the verification table) is rewritten after step 11 with the other bodies, as the restack plan schedules; nothing in the tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…try points - fixed: both-kept-2-P1B-R3-2 and rules-docs-2-P1B-R3-DOC-2 (applied once): CONTRIBUTING.md's door-rule exception list gains P2's clause verbatim, "and the setup file `test/support/reset-process-state.ts`, which runs before the jsdom tests too", so it agrees with test/support/catalogs.ts and docs/testing.md. The plan's P2 restack row records that the merge conflict on that line resolves to P2's line. - fixed: rules-docs-2-P1B-R3-DOC-1: docs/testing.md's lead-in says "Three entry points", matching the three bullets the fixture exports. Wording only; no code or test changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Outcomes of the P1b restack review: - both-kept-3-P1B-R4-2, resolutions-3-P1B-R3-CH-1, rules-docs-3-P1B-R3b-1 (one item): no code or decision change on P1b. D14' and D22' stay as P0 wrote them; the P-T1a restack row now records the open question (one verified channel against a both-channel goal), that the owner decides it as D14''/D22'', the cheapest coverage (a per-channel HOST_VERSIONS and an rc row in the e2e-host matrix, floating first, pinned only once the latest rc tag's pi is confirmed), and that the 1.1.0 patch is kept until then. - both-kept-3-P1B-R4-1, rules-docs-3-P1B-R3b-2 (one item): no tree change. The pull request body predates the restack; at push, one PR comment line says so, and the body is rewritten (no behaviour change, the plane rule is main's D25, the shim case named by its premise, test/support/catalogs.ts, the restacked gate's numbers). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
Owner
Author
|
Restacked onto The description was written before the restack and has now been rewritten. It no longer claims a behaviour change, item 6 follows D25, and the verification table holds this head's gate numbers. Conflicts and how they were resolvedTool fallback (D25)
Tests and fixtures
Docs
Dropped
Review rounds
Live re-measures still owedNone from this branch. No change here touches the wire, the routes or the credentials. The scheduled live probe suites only need to stay green on this head. All reviews ran on the dedicated reviewer. None fell back to the general model. Generated by Claude Code |
The vendor added a free Zen model, `pulse-alpha-free`, after main's 2026-10-31 regeneration, and `catalog freshness` gates this pull request because it changes the generator's code. `src/catalog-data.ts` is taken exactly as the nightly refresh produced it (0f22c3e on chore/generated-refresh), with no hand edits; `src/go-limits-data.ts` did not move. The counts that restate the catalog follow it: - Zen 80 -> 81 served, no SDK 23 -> 24, free 8 -> 9 (catalog.test.ts, redirect-planes.md, protocol-routing-and-merge.md, both READMEs); - the registry's listed total 130 -> 131, since an added model is listed as well as served; - the count dates move to 2026-11-03. It no-ops once main carries the same refresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…del-bctz9n-p1a Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
…-mendel-bctz9n-p1b Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141fKp5k6hiaJcP5ovhGtSD
viztor
force-pushed
the
claude/vigilant-mendel-bctz9n-p1a
branch
from
November 4, 2026 19:37
894fa6e to
e7ad3df
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase P1b of
docs/improvement-plan.md. It is stacked on #106 (P1a), which is stacked on #105.Hygiene only. It removes dead code and adds gates. There are no user-facing behaviour changes.
adapter-replacement.tsand its test are deleted. Nothing imported them.docs/engineering-notes.mdgains a section on two points. First, deleting another plugin's registry entry is not a host API:registerAdapteris all-or-nothing, and only the owner'shandle.replacemoves routes. Second, the plugin keeps pi-ai from claiming the planes through the config waterfall instead (D13).architecture.test.tsfails the build if anything insrc/'s import graph writes the llm registry map (adapters.set/delete/clear, including optional chaining).preparedhandling is gone. In the host'sllm/src/index.ts,stream(options)passes the prepared dispatch as a separate argument, which onlyprepareCall's one-shot stream supplies.options.preparedis never read..freebuff/is untracked and ignored. It held a per-machine agent workspace id.Config.dict. It usedConfig({}), which drops keys with no default, and that is howdebugFilewent missing from it.debugFileis now registered as config-only, and described by the gatemainchose (D24): naming it writes both halves whether or notdebugis on, anddebuggoverns the console. A new manifest test checkscordis.patch.ymlagainst the schema and the field registry. That surfaced the phantomshowUsagePrice, the wrongfreeModelMarker: ''text and the incomplete field lists, all now fixed.utils/retry.tstakes its timer and logger as parameters. The utils purity gate now also rejectsconsoleand global timers: called or passed as values, bare or throughglobalThis./window./global./self.. It walksutils/recursively.tool-fallback's unreachable Anthropic schemas are deleted. The plane rule ismain's (D25): the request URL decides the plane, with a plane-blind lookup as the fallback.test/support/src.tsis the one door tests use intosrc/, so later module moves touch one file. This phase converts the files it touches, P2 converts the rest, andCONTRIBUTING.mdstates the rule (with the setup file as a named exception). The synthetic catalogue rows and the plane-divergent seed are one fixture,test/support/catalogs.ts, behind the door.Restacked onto main 1.8.0
The branch now carries
main1.8.0 through its parent (P1a), which is an ancestor of this head.Scope after the restack. Deletes
src/adapter-replacement.tsand its test (with an engineering note and a registry-write gate), the stream hook's deadpreparedhandling, and the tracked.freebuff/. The settings partition test walksConfig.dict, and a manifest test holdscordis.patch.ymlto the schema and the field registry, withdebugFiledescribed by D24.utils/retry.tstakes its timer and logger as parameters, and the utils purity gate also rejectsconsoleand global timers, walking recursively.tool-fallbackloses its unreachable Anthropic schemas.test/support/src.tsis the one door intosrc.Dropped because
mainnow does it.routeoption onmaybeInjectCoreTools, and a plane lookup by route with no plane-blind fallback).main's feat(test): a fixture harness for the worlds the vendor has not produced #138 rule supersedes it (D25).test/support/catalog-fixture.ts, folded intotest/support/catalogs.tstogether withmain'stest/fixtures/catalogs.ts.Decisions applied.
debugFileis described by the gatemainchose, insrc/settings-fields.tsandcordis.patch.yml.docs/improvement-plan.md, for the owner to decide before P-T1a starts. The committed install and lockfile stay as they are.Live re-measures CI must confirm. None are new: no change on this branch touches the wire, the routes or the credentials. CI's unit, shuffled and mock suites and the bundle gate cover the head. The scheduled live probe suites only need to stay green on it.
Review
The change went through three review lenses (correctness and host contracts, tests, repository rules). Two independent skeptics checked each finding. Over three rounds before the restack:
The restack had three more rounds of review. Their counts are in the restack comment on this pull request.
Verification
From the restacked head's gate:
pnpm run checktest:mockThe diff contains no local paths.
Generated by Claude Code