mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-08 17:10:50 -10:00
fix(pet): fail npm run check when committed native artifacts drift
P01-05 (Refs #6557). The committed native copies of the TypeScript core (crates/tui/src/tui/pet_watch/pet-native.js, crates/tui/.../shared.html, pet/ios/Resources/pet-native.js and demo.jsonl, which Android also packages) were only regenerated by `npm run sync`. `npm run check` never compared them, so the owned build stayed green beside a stale embedded core. The CI step `git diff --exit-code` after sync (pet.yml:37) also omits pet_watch/shared.html, which the owner serves via include_str!. scripts/build-pet.mjs gains `--check`: it builds dist as before, regenerates every tracked native output in memory and exits 1 naming each file whose bytes differ (or which is missing). Without --check the same list is written, so sync behaviour is unchanged. `npm run check` now runs the build with --check, and CI already runs `npm --prefix pet run check`. Validation (pet/): - npm run check: typecheck ok; "generated native artifacts match"; ℹ tests 71 / pass 71 / fail 0 - Negative control: appended a comment to public/shared.html -> --check exit 1 "stale: ../crates/tui/src/tui/pet_watch/shared.html"; the previous path (plain build) exit 0 on the same drift. Appended a comment to src/core/pet-world.ts -> --check exit 1 naming both pet-native.js copies. Both files restored byte-identically (cmp), rerun exit 0. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: CodeWhale Bot <[email protected]>
This commit is contained in:
1 parent
998a1811a3
commit
1fceabfe98
3 files changed
+29
-12
No files matched your search
+2
-2
@@ -88,8 +88,8 @@ The Rust particle implementation lives in the product's
|
||||
`crates/tui/src/tui/ambient_life/pet_sim.rs`; this package's runner imports it.
|
||||
Swift and Kotlin particle ports must match its conformance digests. Generated
|
||||
native bundles are committed so the product Rust build needs no Node compiler.
|
||||
Run `npm run sync` after changing core source; the generated-byte check in CI
|
||||
rejects a stale bundle. Local Whalesong consumers use aliases to these same
|
||||
Run `npm run sync` after changing core source; `npm run check` (run by CI)
|
||||
rejects a stale bundle or `shared.html` copy. Local Whalesong consumers use aliases to these same
|
||||
canonical files, not separately maintained source copies.
|
||||
|
||||
The original Whalesong importer, signal model, schema and browser storage code
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
"build": "node scripts/build-pet.mjs",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"test": "node --test tests/*.test.mjs",
|
||||
"check": "npm run typecheck && npm run build && npm test",
|
||||
"check": "npm run typecheck && node scripts/build-pet.mjs --check && npm test",
|
||||
"start": "python3 -m http.server 4632 --bind 127.0.0.1 --directory dist",
|
||||
"sync": "node scripts/build-pet.mjs --tui --apple --study"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/** Local TypeScript build plus deterministic embedded-runtime packaging. */
|
||||
import { readFile, writeFile, cp, mkdir } from 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import ts from 'typescript';
|
||||
const root = fileURLToPath(new URL('../', import.meta.url));
|
||||
@@ -23,11 +24,15 @@ const bundle = `/* Generated from pet/src/core. Run npm --prefix pet run sync. *
|
||||
+ [...modules].map(([id, js]) => `factories[${JSON.stringify(id)}]=function(exports,require){\n${js}\n};\n`).join('')
|
||||
+ `function load(id){id=id.replace(/^\\.\\//,'').replace(/\\.js$/,'');if(cache[id])return cache[id];if(!factories[id])throw Error('Missing core module');const e=cache[id]={};factories[id](e,load);return e;}\nglobal.PetNative=load('pet-native').PetNative;\n})(globalThis);\n`;
|
||||
await writeFile(root + 'dist/pet-native.js', bundle);
|
||||
if (process.argv.includes('--tui')) {
|
||||
// Committed native copies are generated from src/core and public/. `--check`
|
||||
// regenerates them in memory and fails on any byte difference, so a green
|
||||
// `npm run check` cannot sit beside a stale embedded TUI/Apple/Android core.
|
||||
const check = process.argv.includes('--check');
|
||||
const generated = [];
|
||||
if (check || process.argv.includes('--tui')) {
|
||||
const destination = root + '../crates/tui/src/tui/pet_watch/';
|
||||
await mkdir(destination, { recursive: true });
|
||||
await writeFile(destination + 'pet-native.js', bundle);
|
||||
await cp(root + 'public/shared.html', destination + 'shared.html');
|
||||
generated.push([destination + 'pet-native.js', Buffer.from(bundle)],
|
||||
[destination + 'shared.html', await readFile(root + 'public/shared.html')]);
|
||||
}
|
||||
if (process.argv.includes('--study')) {
|
||||
const study = root + 'world/';
|
||||
@@ -44,11 +49,23 @@ if (process.argv.includes('--study')) {
|
||||
compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ES2022 },
|
||||
}).outputText.replace("'./PetSim.ts'", "'./PetSim.js'"));
|
||||
}
|
||||
if (process.argv.includes('--apple')) {
|
||||
if (check || process.argv.includes('--apple')) {
|
||||
const { petDemoEvents } = await import('../dist/core/pet-demo.js');
|
||||
const { compilePetTelemetry, encodePetJSONL } = await import('../dist/core/pet-telemetry.js');
|
||||
await mkdir(root + 'ios/Resources', { recursive: true });
|
||||
await writeFile(root + 'ios/Resources/pet-native.js', bundle);
|
||||
await writeFile(root + 'ios/Resources/demo.jsonl', encodePetJSONL(compilePetTelemetry(petDemoEvents(), 80_000)));
|
||||
generated.push([root + 'ios/Resources/pet-native.js', Buffer.from(bundle)],
|
||||
[root + 'ios/Resources/demo.jsonl', Buffer.from(encodePetJSONL(compilePetTelemetry(petDemoEvents(), 80_000)))]);
|
||||
}
|
||||
console.log(`Built pet viewer and native core (${modules.size} shared modules), entirely local.`);
|
||||
if (check) {
|
||||
const stale = [];
|
||||
for (const [path, bytes] of generated) {
|
||||
const current = await readFile(path).catch(error => { if (error.code === 'ENOENT') return undefined; throw error; });
|
||||
if (!current || !bytes.equals(current)) stale.push(path.slice(root.length));
|
||||
}
|
||||
if (stale.length) {
|
||||
console.error(`Generated native artifacts are stale: ${stale.join(', ')}. Run npm --prefix pet run sync and commit them.`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
for (const [path, bytes] of generated) { await mkdir(dirname(path), { recursive: true }); await writeFile(path, bytes); }
|
||||
}
|
||||
console.log(`Built pet viewer and native core (${modules.size} shared modules), entirely local${check ? '; generated native artifacts match' : ''}.`);
|
||||
Reference in new issue
Block a user