Skip to content

De-sprawl: retire Sutta Studio shims, single Gemini SDK, delete dead code - #186

Merged
anantham merged 5 commits into
mainfrom
claude/pensive-volta-5nyx9k
Sep 24, 2026
Merged

anantham merged 5 commits into
mainfrom
claude/pensive-volta-5nyx9k

Conversation

@anantham

@anantham anantham commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Owner-approved simplification pass from a review of open issues and the DESPRAWL roadmap. It is mostly behavior-preserving; the three Gemini request/response changes listed under "Behavior changes" are the exceptions.

Changes

1. Sutta Studio shims retired (CONSOLIDATION Phase 4, partial)

  • services/compiler/*, services/sutta-studio/prompts/skeleton.ts, benchmark scripts and tests import services/sutta-studio/{llm,prompts,schemas,utils,passes} directly.
  • Deleted the six pure re-export shims: services/suttaStudioPass{Prompts,Runners}.ts, services/compiler/{llm,prompts,schemas,utils}.ts.
  • schemas-canonical.test.ts: the cross-location identity check becomes a canonical-export check. The wordRange/refrainId guards are unchanged.
  • services/compiler/{index,skeleton}.ts stay; retiring them depends on Phase 2d and decision D2.

2. Single Gemini SDK (@google/genai)

  • GeminiAdapter (translate + chatJSON), the Gemini image branch in imageService.ts and the Gemini response schemas move off the legacy @google/generative-ai.
  • Abort signals travel in config.abortSignal. Cancellation was checked with a loopback HTTP test during review.
  • Both adapter entry points share responseTextOrThrow, which keeps the legacy SDK's rule: text from a candidate whose finishReason is SAFETY, RECITATION or LANGUAGE is rejected. The new SDK's text getter would otherwise return it. Review found this in 0207fdb; c174b18 fixes it, and the regression tests fail without the fix.

3. Dead code and dependencies

  • Deleted migrateFromLocalStorage, isMigrationCompleted and resetMigrationState, which had zero importers (DESPRAWL T2.4b).
  • Deleted services/audio/storage/{cache,opfs}.ts. They had zero importers and were committed with literal \n escapes, so they needed exclusions in tsconfig.json, vitest.config.ts and eslint.config.mjs. Those exclusions are removed, along with a stale pinning.ts entry.
  • services/audio/storage/utils.ts stays because AudioPlayer.tsx uses formatDuration.
  • Deleted public/debug-chapter2.js, a one-off console diagnostic that was shipped to every user.
  • Dropped @google/generative-ai, @types/jszip (jszip ships its own types) and ts-prune (unused).

Behavior changes (all Gemini; confirmed in review)

  1. Empty responses now name the block or finish reason, e.g. Empty response from Gemini API (SAFETY), and blocked candidates raise Gemini response blocked (<reason>).
  2. additionalProperties is stripped from chatJSON schemas by the new SDK's processJsonSchema. This includes Sutta Studio's string-valued ripples map constraint. The difference in the request payload is proven; the effect on Google's output is untested.
  3. Gemini 2.0 image-generation models: responseModalities moves from the request's top level into generationConfig, which is the location Google's API reference documents. This is likely a correction, but it is still a change.

Verification

  • Base vs PR on Node 24.21.0, run by an independent reviewer: install, typecheck, lint, build and integrity checks pass on both. Tests: 9,562 passed on base and 9,563 on the PR at 0207fdb, with 347 skipped each. No existing test changed status.
  • After the fix (c174b18), run in a Node 22 container: typecheck passes, lint has 0 errors, the build passes, and 9,567 tests pass (5 are new). The one failure, in indrasNetImageProvider.test.ts, is specific to this Node 22 environment; it passes on Node 24.
  • Not verified: live Gemini calls. Worth one real translation, one Sutta Studio compile on Gemini (because of behavior change 2), and one Gemini image generation before merge.

Follow-ups (not in this PR)

  • The hand-maintained Gemini schema variants in translationResponseSchema.ts (~130 lines) and the provider branch in translationService.ts could be dropped, because the new SDK accepts the JSON schemas directly. This needs a live test first.
  • If the ripples map constraint matters to Gemini output, pass it through responseJsonSchema instead of responseSchema.
  • Seven now-unused exports in services/audio/storage/utils.ts.

🤖 Generated with Claude Code

https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W

… shims

The compiler, benchmark scripts and tests now import services/sutta-studio/
{llm,prompts,schemas,utils,passes} directly. The six Phase-4 shims
(suttaStudioPass{Prompts,Runners}.ts, compiler/{llm,prompts,schemas,utils}.ts)
have no remaining importers. The schema test's cross-location identity check
becomes a canonical-export check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
migrateFromLocalStorage, isMigrationCompleted and resetMigrationState had
zero importers (DESPRAWL T2.4b). The live model-field repair is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
GeminiAdapter (translate + chatJSON), the Gemini image branch and the Gemini
response schemas move off the legacy @google/generative-ai SDK. Abort signals
travel in config.abortSignal. The new SDK returns empty text for blocked
responses instead of throwing, so the empty-response error now names the
block/finish reason.

Drops @google/generative-ai plus two unused packages (@types/jszip — jszip
ships its own types — and ts-prune).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
- Six Sutta Studio re-export shims with no importers (CONSOLIDATION Phase 4).
- services/audio/storage/{cache,opfs}.ts: zero importers and committed with
  literal \n escapes, so tsconfig/vitest/eslint had to exclude them; those
  exclusions (and a stale pinning.ts entry) go too.
- public/debug-chapter2.js: one-off console diagnostic shipped to every user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
lexicon-forge Ready Ready Preview Sep 24, 2026 1:41pm UTC

@google/genai's text getter returns text from candidates whose finishReason
is SAFETY, RECITATION or LANGUAGE; the legacy SDK's text() threw for these.
translate and chatJSON now share responseTextOrThrow, which restores that
rejection. Found in review of #186; regression tests fail without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011d1MbSabs9nA9d9w8pxP1W
@anantham
anantham merged commit 5e88259 into main Sep 24, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — c174b18f Deployed Sep 24, 2026 by vercel[bot]
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.

2 participants