codeburn/packages
iamtoruk 5960ae3535 refactor(core): cursor decode into core, queries and caches host-side (phase 8, stateful tier)
Cursor is the bucket-D stateful multi-store provider: it keeps its bespoke
adapter (no createBridgedProvider) and the host retains every store read.

Tagged-record composition over five query families. The host issues all five
queries in the load-bearing order [1] composerData meta, [2] bubble COUNT,
[3] bubbles (paged or since), [4] agentKv, [5] user messages, preserving the
per-query degradation semantics: [1]/[4]/[5] degrade to empty, [2] to total=0,
and a [3] failure early-returns zero calls while still writing the (empty)
cache and skipping [4]/[5]. decodeCursor() receives the four row sets plus the
host-supplied agentKv timestamp and performs the whole stitched pass — the
pre-pass scan, the agentKv fold, the user-message queue, and all three emit
arms (per-bubble, per-conversation input, stream-only).

The 19-key emitted call shape is a cache-compatibility contract. CURSOR_CACHE_VERSION
stays 6 and PROVIDER_PARSE_VERSIONS['cursor'] is unchanged, so existing
cursor-results.json files on disk are replayed through the new path; adding,
dropping, or undefined-ing any key would poison them. The goldens gate the key
set with Object.keys() on every arm, which is what catches a key present with an
undefined value — toEqual cannot see one, and JSON.stringify drops exactly those
on the way into the cache.

Pricing, bash base-name extraction, display names, project attribution, SQL,
paging, env reads and clock reads all stay host-side; toProviderCall is the
single mapper that re-adds costBasis 'estimated', costIsEstimated true and the
resolved pricing model. No costUSD is ever emitted.

Composer-id / dedup-key envelope finding: composer ids and request ids flow into
sessionId and into the envelope's dedupKeys by design, exactly like every other
provider's machine identifiers, so the content-smuggling block deliberately does
not plant a secret there. Hashing dedup keys uniformly is a schema-wide
follow-up, not a cursor-local change.

Validator fixes on top of the migration:
- relocated the content-smuggling block from cursor-decode.test.ts into
  content-smuggling.test.ts, matching all 25 other providers, and added a probe
  proving each planted secret actually reaches the field it guards
- G11 now gates the undefined-key cache contract it claimed to (toEqual passed
  under an injected extra undefined key; toStrictEqual plus key-set assertions
  catch it)
- restored the CODEBURN_CURSOR_MAX_BUBBLES override in the golden's afterEach so
  G12 cannot leak the scan budget into cursor-large-db-cap.test.ts
- restored the comment rationales that must travel with their code verbatim
  (pos-cursor queue performance note, parseComposerIdFromKey CR/LF signature,
  agentKv stream and pending-flush notes, dedup-key history, costIsEstimated)

The 12 goldens were cross-checked against the pre-migration provider by
restoring it in place: they pass identically on both sides. H2 (queue pop before
skip) and H4 (arm B dedup-key burn before the timestamp check) were mutation
tested and are killed by G8 and C6 respectively.
2026-07-27 08:05:46 -07:00
..
cli refactor(core): cursor decode into core, queries and caches host-side (phase 8, stateful tier) 2026-07-27 08:05:46 -07:00
core refactor(core): cursor decode into core, queries and caches host-side (phase 8, stateful tier) 2026-07-27 08:05:46 -07:00