Skip to content

fix: the projection registry renamed its fields, so the meter went invisible - #13

Merged
lroolle merged 1 commit into
mainfrom
fix/projection-contract-rename
Aug 24, 2026
Merged

fix: the projection registry renamed its fields, so the meter went invisible#13
lroolle merged 1 commit into
mainfrom
fix/projection-contract-rename

Conversation

@lroolle

@lroolle lroolle commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

What broke

@deepseek-ai/dsh-session-projection 0.1.1-rc.1 (2026-08-21) renamed the
projection definition contract:

up to 0.1.0-rc.8 from 0.1.1-rc.1
schema — validates view(state) wire.viewSchema
view — always client-visible wire.view, and wire is optional
(checkpoints stored raw) stateSchema — parses the persisted row on restore

The registry reads the definition field by field and never validates it, so
the old spelling does not throw. It reads as "this projection is host-only":

if (registration.def.wire === void 0) continue;   // lib/index.js:125, :199, :291

The fold kept running. The value never reached the browser.
useProjection('costMeter') returned undefined, CostMeterLine returned
null, and the composer dock line disappeared — no error, no warning, no log
line anywhere
.

The one signal that could have caught it was an unmet peer: ^0.1.0-rc.6 does
not match 0.1.1-rc.2, because npm only admits a prerelease when some
comparator names the same [major, minor, patch]. Nobody reads pnpm's peer
warnings.

The fix

One definition carrying both spellings. Each registry reads the pair it knows
and ignores the other, so a single build is correct on either side of the
rename. The peer range now names both prerelease lines
(^0.1.0-rc.6 || ^0.1.1-rc.1).

stateSchema is genuinely new — it is not the old schema renamed. The old
contract stored checkpoints raw; the new one feeds the persisted row through
stateSchema before folding onto it, so a definition without one throws on the
first resumed session.

Verified

Live against dsh 0.1.1-rc.2 on a real session:

¥0.2185 | off-peak | peak in 14h

The card opens with the per-model split, the counterfactuals, and the account
balance from /dsh-meter/balance. No page errors.

Tests: 98 pass (15 new). The four that matter fail on the old spelling and
pass on this one — each stand-in registry reads exactly the fields its
published lib/index.js reads, because a stand-in weaker than production would
miss this again.

…visible

`@deepseek-ai/dsh-session-projection` 0.1.1-rc.1 split the definition's single
`schema`/`view` pair into a host-side `stateSchema` and an OPTIONAL
`wire: { viewSchema, view }`. The registry reads those fields one by one and
never validates the definition it was handed, so the old spelling does not
fail — it reads as "this projection is host-only". The fold still ran, the
value never reached the browser, `useProjection('costMeter')` returned
undefined, and `CostMeterLine` returned null.

No error, no warning, no log line. The dock line simply stopped rendering,
which is why this looked like the meter "not working" rather than a crash.
`^0.1.0-rc.6` did not even cover the installed 0.1.1-rc.2 — npm excludes a
prerelease whose [major,minor,patch] no comparator names — so the one signal
that could have caught it was an unmet-peer warning nobody reads.

Register both spellings from one definition. Each registry reads the pair it
knows and ignores the other, so a single build is correct on either side of
the rename, and the peer range now names both prerelease lines.

`stateSchema` is new work, not a rename of the old `schema`: the old contract
kept checkpoints raw, the new one parses the persisted row before folding onto
it. Without it a resumed session throws on `def.stateSchema.parse`.

Verified live against dsh 0.1.1-rc.2: the dock renders
`¥0.2185 | off-peak | peak in 14h` on a real session, the card opens with the
per-model split and the account balance, and the tests fail on the old
spelling and pass on this one.
@lroolle
lroolle merged commit 054a83f into main Aug 24, 2026
1 check passed
@lroolle
lroolle deleted the fix/projection-contract-rename branch August 24, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant