Repository navigation
Make the project install and typecheck from a clean clone - #8
Conversation
Two independent breakages meant a fresh clone could neither install nor typecheck, and nothing in the repo would have told you. npm install failed outright. wrangler@^4.20.0 now floats to 4.127.1, which peer-depends on @cloudflare/workers-types@^5, while package.json pinned ^4 — an unsatisfiable pair, and drift rather than anything anyone did. Bumping the types package to ^5.20260828.1 makes a plain npm install exit 0 again. tsc --noEmit reported four errors. VOICES is `as const`, so VOICE_IDS inferred as Set<"luna" | "orion" | …> and rejected .has() on the arbitrary strings that actually arrive from tool arguments; the Set is now typed Set<string>, widening the type rather than the data. In tts.ts the model declares a fixed speaker union, so an arbitrary voiceId is asserted across — the value is already validated against VOICES upstream. The last error was the interesting one. The published type for the TTS model claims a string return, which makes `result instanceof ArrayBuffer` unreachable and would tempt a reader into "fixing" the audio handling. That would be a mistake: live output through the Response path is a valid MP3 (verified against production, ff f3 frame sync, 291KB). So `result` is widened to unknown to keep both branches live and the runtime path untouched — the emitted JavaScript for tts.ts is byte-identical to before. Adds a typecheck script and a CI workflow that runs it, since none of the above surfaced anywhere: build is `echo 'no build step'` and wrangler deploy bundles with esbuild without full type checking. CI runs a plain npm install on purpose — that failing is exactly what this is here to catch. Also adds a .gitignore, which the repo lacked, so a successful install no longer litters git status. Closes #4 Closes #5
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
rapbattle | d9e0138 | Sep 01 2026, 09:32 PM |
Without a lockfile every install re-resolves from scratch, which is how #4 happened: wrangler floated to a version whose peer range no longer matched the pinned types package, and nothing recorded the set that had last worked. Generated fresh from the corrected package.json — 95 packages, all resolved from registry.npmjs.org, no credentials. CI now runs npm ci rather than npm install. It installs exactly this tree, and it fails loudly if package.json and the lockfile ever drift apart, which is the failure mode worth catching early. Verified locally: npm ci exits 0 and typecheck reports no errors against it.
|
Lockfile now committed, per your call — this supersedes the "one decision left to you" section in the description above.
CI switched from |
Closes #4. Closes #5.
Both on one branch because both touch
package.json— as two PRs they would conflict with each other.#4 —
npm installfailed outrightwrangler@^4.20.0now floats to4.127.1, which peer-depends on@cloudflare/workers-types@^5, whilepackage.jsonpinned^4. Unsatisfiable. This is drift, not anything anyone did — it installed cleanly when the pins were written.Bumped the types package to
^5.20260828.1. Verified: a plainnpm install, no flags, now exits 0, andwrangler deploy --dry-runstill bundles with all five bindings intact (271 KiB / 61 KiB gzip).#5 — 4 type errors, and nothing ran the typechecker
Now zero. Causes and fixes:
VOICE_IDS(3 errors).VOICESisas const, so the Set inferred asSet<"luna" | "orion" | …>and rejected.has()on the arbitrary strings that actually arrive from tool arguments. Typed itSet<string>— widening the type, not the data.speakerintts.ts. The model declares a fixed speaker union; an arbitraryvoiceIdis now asserted across it. Safe because the value is already validated againstVOICESupstream — I diffed all 10 house voices against the 40 the model accepts, and every one is valid.The fourth error was a trap, and I want to flag it explicitly
The published type for the TTS model claims a
stringreturn, which makesresult instanceof ArrayBufferunreachable. The obvious "fix" is to rewrite the audio handling — that would break working TTS.I checked production before touching it:
Valid MP3. The runtime value is not a plain string — the published type is just wrong. So
resultis widened tounknownto keep both branches live, and the runtime path is untouched.Proof the audio path is unchanged: I compiled
tts.tsbefore and after and diffed the emitted JavaScript. After stripping comments it is byte-identical. Every change in that file is type-level only.Prevention
Added
"typecheck": "tsc --noEmit"and a CI workflow that runs it on push and PR. None of the above surfaced anywhere before:buildisecho 'no build step', andwrangler deploybundles via esbuild without full type checking. CI runs a plainnpm installon purpose — that failing is exactly what the workflow exists to catch. I ran both steps locally (install exit 0, typecheck 0 errors); I obviously can't run Actions from here, so the workflow itself is unproven until it runs on GitHub.Also added a
.gitignore(the repo had none), so a successful install no longer littersgit statuswithnode_modules/.One decision left to you
I did not commit a lockfile. It's the thing that would actually stop this class of drift from recurring, but it's a policy call for the repo — and a large diff. If you want it:
CI would then be safe to switch from
npm installtonpm ci. Happy to do it if you'd prefer.Relationship to the other PRs
Independent of #6 and #7 — different files, no conflicts, merges in any order.
🤖 Generated with Claude Code