Skip to content

refactor(core): tail migrations — crush, zcode, zed, forge, goose (phase 8, sqlite batch 1) - #832

Merged
iamtoruk merged 1 commit into
feat/core-extractionfrom
phase8/sqlite-batch1
Jul 27, 2026
Merged

refactor(core): tail migrations — crush, zcode, zed, forge, goose (phase 8, sqlite batch 1)#832
iamtoruk merged 1 commit into
feat/core-extractionfrom
phase8/sqlite-batch1

Conversation

@iamtoruk

Copy link
Copy Markdown
Member

Phase 8 sqlite batch 1 (tracking #809): migrates the row→call decode for crush, zcode, zed, forge, goose into @codeburn/core per the recipe's sqlite variant — the sqlite driver, openDatabase, and all SQL queries stay CLI-side in readRecords; only pure row decode, row types, and tool-name maps move.

Two-tier protocol: cheap-tier draft, then independent arm-by-arm validation against the pre-migration originals with a git-show harness. The validator caught and fixed two real defects the green suites missed:

  • forge: the draft rewrote the tool-name switch into a Record lookup, introducing a prototype-member leak (constructor/toString/__proto__ resolved to inherited values, landing non-strings in tools). Restored the original switch verbatim; pinned with a hostile fixture.
  • zed: the aggregate skipped N unreadable Zed threads stderr warning was silently dropped (bridge discards decode diagnostics). Re-emitted host-side via a decode wrapper; byte-identical to the original.

Adjudicated deviations (accepted, output-equivalent, harness-verified): goose's clock fallback moved to the host boundary ('' from core, || new Date() in toProviderCall); crush's measuredCostUSD carrier with exact original arm order and > 0 threshold.

Goldens: full-object toEqual pins captured from the unmodified providers, independently re-derived via the git-show harness (8/8), including arms the draft fixtures didn't exercise (crush cost-only/child-session rows, zcode skip-slot semantics, zed remainder/no-model rows, forge positional-stableId fallbacks).

Gates: core 233/233; CLI suite (from packages/cli) and root npm test both 2327 passed, 5 skipped; tsc --noEmit clean in both packages. Arch-gate allowlist: zed/forge/goose only (verified crush/zcode carry no userMessage). No parse-version changes.

Known follow-up (pre-existing, untouched): gooseToolNameMap has the same Record prototype hazard as the forge bug, but it predates this migration.

…ase 8, sqlite batch 1)

Category B (sqlite) variant of the bridge migration: the sqlite driver and every
SQL query stay CLI-side. Each provider's `readRecords` opens the database, runs
the same queries as before, and hands the resulting rows (blob and all) to a
pure core decoder; `toProviderCall` maps the rich, cost-free decode back onto
ParsedProviderCall, where cost re-enters via the parser.ts pricing pass.

Per provider:
- crush: session row + dominant-model query -> one combined record. Crush stores
  cost in dollars, so a row with cost > 0 carries `measuredCostUSD` (costBasis
  'measured'); a zero-cost row falls back to token estimation, arm order intact.
- zcode: model_usage + tool_usage row sets -> one composite record. Each turn's
  tools still attach to the first non-skipped usage row of that turn only.
- zed: threads rows handed over compressed; zstd decompression, JSON parsing and
  per-request/cumulative-remainder accounting are pure. The Node >= 22.15 zstd
  capability check stays host-side.
- forge: conversation row handed over with `context` still serialized; JSON
  parsing and per-message decode are pure. Bash base-name extraction (and its
  strip-ansi dependency) stays CLI-side over the decoder's raw command strings.
- goose: session + assistant tool-message + first-user-message rows, BLOB
  columns pre-converted to text host-side, bundled into one composite record.

Validator fixes (original behavior is the authority):
- forge: the draft replaced the pre-migration `mapToolName` switch with an
  object-literal lookup. Tool names come straight from conversation JSON, so
  names colliding with Object.prototype members ("constructor", "toString",
  "__proto__", "hasOwnProperty") resolved to inherited Functions / the prototype
  object and were pushed into `tools` as non-strings instead of falling through
  to the identity default. Restored the switch and pinned the arm in the fixture.
- zed: the draft routed the "skipped N unreadable Zed threads" notice into
  record diagnostics, which the bridge discards, silently dropping a warning the
  pre-migration decode printed. Re-emitted host-side from the diagnostics count
  and pinned with a stderr assertion.
- Fixture coverage extended for the arms that were regression-blind: forge's
  prototype-named tool calls, zed's aggregate stderr line, and goose's
  single-turn `toolSequence` omission plus the unparseable-timestamp fallback.

Parity was verified independently of the bridge tests with a git-show harness
that runs the same fixtures through the pre-migration provider files and asserts
field-for-field equality, including the extra arms above.
@iamtoruk
iamtoruk merged commit 6c64a1b into feat/core-extraction Jul 27, 2026
4 checks passed
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