From 5a4e62f6c66d56f00e04947727dfa55479530490 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Tue, 28 Jul 2026 22:15:18 -0700 Subject: [PATCH] fix(build): build @loopover/contract in both deploy paths so a clean checkout can deploy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cloudflare Workers Builds is the deploy path for BOTH workers — no GitHub Actions workflow runs `wrangler deploy` (ui-deploy.yml only validates) — and both have failed on every recent commit. Production has consequently been serving stale code: #9574's `fleetAccuracy.basis` and #9594's anchor-payload auth exemption both landed on main and neither is live. One root cause, two scripts: nothing builds `@loopover/contract` before something needs its `dist/`. `@loopover/engine` does not depend on it, so building engine alone leaves it unemitted. loopover-ui — `npm run ui:build` runs `turbo run build --filter=@loopover/engine`, then `ui:openapi`, whose `scripts/write-ui-openapi.ts` reaches `src/openapi/schemas.ts` and imports `@loopover/contract/dist/public-api.js`: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/opt/buildhome/repo/node_modules/@loopover/contract/dist/public-api.js' loopover-api — `npm run deploy:api` builds only `@loopover/engine`, then `wrangler deploy` bundles `src/index.ts`, which reaches `@loopover/contract` from src/mcp/*, src/openapi/schemas.ts and src/orb/broker-client.ts: ✘ [ERROR] Build failed with 8 errors: ✘ [ERROR] Could not resolve "@loopover/contract" Both pass in `test:ci` only by accident of ordering: `npm run typecheck` runs first, and the `//#typecheck` turbo task already carries an explicit `@loopover/contract#build` edge — added for exactly this failure mode, and documented in turbo.json as "the root package.json dependency does NOT create a build edge for a root task". Neither deploy command runs a typecheck ahead of itself, so the incidental ordering never applies. Adding the same edge to each deploy path's own turbo invocation, which is the level that actually owns the dependency. `deploy:api` also moves from a bare `npm --workspace ... run build` to turbo so both paths express it identically. Verified against a genuinely clean tree (package dists and .tsbuildinfo files removed, TURBO_FORCE=1 to defeat the shared worktree cache — the first two reproduction attempts were masked by a stale tsbuildinfo and then by a turbo cache replay). ui:build: exit 1 -> exit 0. wrangler deploy --dry-run: 8 unresolved "@loopover/contract" imports -> 0, exit 0. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c24722a91a..b77c15b808 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "scripts": { "dev": "wrangler dev", "deploy": "wrangler deploy", - "deploy:api": "npm --workspace @loopover/engine run build && wrangler d1 migrations apply loopover --remote && wrangler deploy", + "deploy:api": "turbo run build --filter=@loopover/engine --filter=@loopover/contract && wrangler d1 migrations apply loopover --remote && wrangler deploy", "selfhost:postgres:migrate": "tsx scripts/migrate-selfhost-sqlite-to-postgres.ts", "selfhost:env-reference": "node --experimental-strip-types scripts/gen-selfhost-env-reference.ts", "selfhost:env-reference:check": "node --experimental-strip-types scripts/gen-selfhost-env-reference.ts --check", @@ -59,7 +59,7 @@ "lint:composite-actions": "node --experimental-strip-types scripts/lint-composite-actions.ts", "ui:dev": "npm run ui:preview", "ui:kit:build": "npm run build --workspace @loopover/ui-kit", - "ui:build": "npm run ui:kit:build && turbo run build --filter=@loopover/engine && npm run ui:openapi && npm --workspace @loopover/ui run build && npm --workspace @loopover/ui-miner run build", + "ui:build": "npm run ui:kit:build && turbo run build --filter=@loopover/engine --filter=@loopover/contract && npm run ui:openapi && npm --workspace @loopover/ui run build && npm --workspace @loopover/ui-miner run build", "ui:preview": "npm run ui:build && wrangler dev --config apps/loopover-ui/dist/server/wrangler.json --ip 127.0.0.1 --port 4173 --local", "ui:lint": "npm run ui:kit:build && npm --workspace @loopover/ui-kit run format:check && npm --workspace @loopover/ui run format:check && npm --workspace @loopover/ui run lint && npm --workspace @loopover/ui-miner run format:check && npm --workspace @loopover/ui-miner run lint", "ui:typecheck": "npm run ui:kit:build && npm --workspace @loopover/ui run typecheck && npm --workspace @loopover/ui-miner run typecheck",