From a86a801784c8964426e91f3ffe4371d1c84cac67 Mon Sep 17 00:00:00 2001 From: coreci-chat-po Date: Sat, 31 Oct 2026 00:27:25 +0000 Subject: [PATCH 1/4] ci: build the control-plane app in the gate (next build) - the app build was never machine-verified (coreci-chat#10) The M2 acceptance gate requires both jobs GREEN, but no step in either job ran `next build`: the workflow builds the eight library packages and typechecks and lints the app, so the App Router tree itself was never compiled by a machine. This adds the build as a gate step, after the package build and the @coreci/mcp dist build, because the app resolves @coreci/db, @coreci/auth, @coreci/secrets and @coreci/mcp through their published dist/*.d.ts. coreci-chat#10 closes on a green app build on main. --- .gitea/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index cdf296a..e3167fd 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -97,6 +97,14 @@ jobs: - name: Build (mcp package — dist for the smoke imports) run: pnpm --filter @coreci/mcp build + # The app build is the M2 gate's missing leg (coreci-chat#10): `next + # build` is the only check that proves the App Router tree (root layout, + # route handlers, pages) compiles. The workspace packages are built + # above because the app resolves @coreci/db, @coreci/auth, + # @coreci/secrets and @coreci/mcp through their published dist/*.d.ts. + - name: Build (control-plane app - next build) + run: pnpm --filter @coreci/control-plane build + - name: "[G-018,R-008] Import guard (no @coreci/llm-mock in prod source)" run: pnpm check:llm-mock-guard -- 2.43.0 From a77b2dc9c245b1eef91ae2a112fd6f8a922bf924 Mon Sep 17 00:00:00 2001 From: coreci-chat-po Date: Sat, 31 Oct 2026 00:27:31 +0000 Subject: [PATCH 2/4] ci: tolerate the coverage upload leg alone - the runner's artifact endpoint is refused (coreci-chat#1) The artifact endpoint the runner hands the job answers ECONNREFUSED from the shared pool - the cache restore warns with the identical text and the identical hint, so it is one runner value behind both. That reddens the pglite job on its LAST step and nothing else, which is why "both jobs GREEN" has never been reachable on this lane. This adds continue-on-error to ONE step: the pglite coverage upload. The postgres job runs no coverage step, so its upload matches no files and never calls the endpoint - it needs no tolerance. Every code step in both jobs still gates, and the app-build step in this branch still gates. This is @coreci-cpo's scope call, asked on coreci-chat#1: the merge of this merge request is the approval of that one-step tolerance. --- .gitea/workflows/ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index e3167fd..fb15aa8 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -138,6 +138,14 @@ jobs: - name: Upload coverage artifacts uses: actions/upload-artifact@v4 if: always() + # @coreci-cpo's one-step tolerance, scoped to THIS step only + # (coreci-chat#1): the runner's artifact endpoint answers + # ECONNREFUSED from the shared pool, so the upload leg - and + # only the upload leg - reds the job. The postgres job runs no + # coverage step and its upload matches no files, so it never + # calls the endpoint. Every other step in both jobs still + # gates. + continue-on-error: true with: name: coverage-pglite path: | -- 2.43.0 From b17e009dd59075d816256f3792d4c5d6b8ac8403 Mon Sep 17 00:00:00 2001 From: coreci-chat-po Date: Sat, 31 Oct 2026 00:27:32 +0000 Subject: [PATCH 3/4] fix(control-plane): drop the phantom @coreci/audit from transpilePackages `@coreci/audit` names a package that does not exist in this repo: the audit code ships as @coreci/db/audit (packages/db/src/audit.ts, exported through packages/db's exports map) and @coreci/db is already in this list. Measured on the whole tree at main - 354 blobs - the only occurrence of the string "coreci/audit" in the repository is this line. Next.js resolves every transpilePackages entry at build time, so the phantom is a build-time failure waiting to happen the moment the app is built in CI - which is what this branch adds. Removing it costs nothing: no import anywhere references it. --- apps/control-plane/next.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/control-plane/next.config.mjs b/apps/control-plane/next.config.mjs index 794afe5..aeee737 100644 --- a/apps/control-plane/next.config.mjs +++ b/apps/control-plane/next.config.mjs @@ -1,5 +1,5 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - transpilePackages: ["@coreci/db", "@coreci/auth", "@coreci/audit", "@coreci/secrets", "@coreci/config", "@coreci/runtime", "@coreci/byom"], + transpilePackages: ["@coreci/db", "@coreci/auth", "@coreci/secrets", "@coreci/config", "@coreci/runtime", "@coreci/byom"], }; export default nextConfig; \ No newline at end of file -- 2.43.0 From 410e62bd305bc714c76b09d45f520f41db843b16 Mon Sep 17 00:00:00 2001 From: coreci-chat-po Date: Sat, 31 Oct 2026 01:14:05 +0000 Subject: [PATCH 4/4] fix(app): teach the bundler the repo's .js -> .ts import convention The control-plane app follows the repo-wide ESM convention - a './x.js' specifier for a './x.ts' source - in all 79 of its relative imports. TypeScript resolves that (moduleResolution: bundler), webpack does not, so the new `next build` gate step failed with "Module not found: Can't resolve '../../../../lib/db.js'" on the first app build this repo ever ran. resolve.extensionAlias maps a '.js' request to the '.ts'/'.tsx' source behind it, so the bundler honours the same convention the type-checker and the packages already do. One resolver-level change, no import churn. Evidence: run 69747, job 72065 - the app-build step fails to compile with 5 module-not-found errors across 4 route files. --- apps/control-plane/next.config.mjs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/control-plane/next.config.mjs b/apps/control-plane/next.config.mjs index aeee737..ecf8de3 100644 --- a/apps/control-plane/next.config.mjs +++ b/apps/control-plane/next.config.mjs @@ -1,5 +1,22 @@ /** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ["@coreci/db", "@coreci/auth", "@coreci/secrets", "@coreci/config", "@coreci/runtime", "@coreci/byom"], + // The app follows the repo-wide ESM import convention - a "./x.js" specifier + // for a "./x.ts" source - like every package in this repo. TypeScript + // resolves that convention (moduleResolution: bundler); the bundler does + // not, so `next build` failed with "Module not found: Can't resolve + // '../../../../lib/db.js'". resolve.extensionAlias maps a ".js" request to + // the ".ts"/".tsx" source behind it, so the bundler honours the same + // convention the type-checker and the packages already do - one + // resolver-level change, no import churn. + webpack: (config) => { + config.resolve.extensionAlias = { + ...config.resolve.extensionAlias, + ".js": [".ts", ".tsx", ".js"], + ".mjs": [".mts", ".mjs"], + ".cjs": [".cts", ".cjs"], + }; + return config; + }, }; -export default nextConfig; \ No newline at end of file +export default nextConfig; -- 2.43.0