diff --git a/scripts/ensure-source-resources.cjs b/scripts/ensure-source-resources.cjs index a857ee2b9..ce164d750 100644 --- a/scripts/ensure-source-resources.cjs +++ b/scripts/ensure-source-resources.cjs @@ -90,3 +90,71 @@ if (shouldRebuild()) { process.exit(result.status ?? 1); } } + +/** + * Auto-rebuild workspace packages whose src/ is newer than dist/. + * + * Without this, edits to packages/coding-agent/src/* (or any other workspace + * package src) silently land while the dist stays stale — agents continue + * loading the old compiled JS and operators see "why didn't my edit take + * effect?" symptoms (observed 2026-05-17 with the AST tools wire-in). + * + * Skipped: + * - native: Rust build takes 5–10 min; trigger manually via + * `node rust-engine/scripts/build.js --dev` instead. + * - any package set in SF_SKIP_WORKSPACE_AUTOBUILD (comma-separated names). + * + * Override the whole step with SF_SKIP_WORKSPACE_AUTOBUILD=all. + */ +const WORKSPACE_AUTOBUILD_PACKAGES = [ + "agent-core", + "ai", + "coding-agent", + "daemon", + "google-gemini-cli-provider", + "openai-codex-provider", + "rpc-client", + "tui", +]; + +function packageNeedsRebuild(pkgName) { + const pkgDir = join(root, "packages", pkgName); + const pkgSrc = join(pkgDir, "src"); + const pkgDist = join(pkgDir, "dist"); + if (!existsSync(pkgSrc) || !existsSync(pkgDist)) return false; + const srcMtime = latestMtimeMs(pkgSrc); + const distMtime = latestMtimeMs(pkgDist); + // Add a small grace window so files written within the same second as a + // dist sync don't trigger redundant rebuilds. + return srcMtime > distMtime + 100; +} + +function rebuildWorkspacePackagesIfStale() { + const skip = (process.env.SF_SKIP_WORKSPACE_AUTOBUILD || "") + .split(",") + .map((s) => s.trim()) + .filter(Boolean); + if (skip.includes("all")) return; + + const stale = WORKSPACE_AUTOBUILD_PACKAGES.filter( + (pkg) => !skip.includes(pkg) && packageNeedsRebuild(pkg), + ); + if (stale.length === 0) return; + + console.error( + `[forge] Workspace src newer than dist for: ${stale.join(", ")} — rebuilding...`, + ); + for (const pkg of stale) { + const result = spawnSync( + "npm", + ["run", "build", "-w", `@singularity-forge/${pkg}`], + { cwd: root, stdio: "inherit", env: process.env }, + ); + if (result.status !== 0) { + console.error(`[forge] FAILED to rebuild packages/${pkg}`); + process.exit(result.status ?? 1); + } + } +} + +rebuildWorkspacePackagesIfStale();