From 37565b53f7e31217885c22e8634fad258b92ab9c Mon Sep 17 00:00:00 2001 From: core-fe Date: Sat, 16 May 2026 01:38:57 -0700 Subject: [PATCH 1/7] perf(canvas): wire @next/bundle-analyzer harness + optimizePackageImports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Establishes the bundle-measurement harness (audit item #5) and enables build-time barrel tree-shaking for the canvas. - next.config.ts: add experimental.optimizePackageImports for the barrel-re-export deps the canvas imports via their package root (@radix-ui/react-{alert-dialog,dialog,tabs,tooltip}, @xyflow/react, react-markdown, remark-gfm). Build-time transform only; runtime and the default `next build` output (output:"standalone") are unchanged. - next.config.ts: wire @next/bundle-analyzer behind ANALYZE=1. When ANALYZE is unset withBundleAnalyzer is the identity function and the dep is never require()'d — default/prod image build is untouched. - package.json: add @next/bundle-analyzer ^15.5.18 to devDependencies (lockstep with next ^15.x); package-lock.json regenerated. Audit baseline (route /): 358 kB First Load JS reported / 1,245.9 KB raw / 350.3 KB gzip actual; /page chunk 505.5 KB raw. Post-change measured locally: / First Load JS 360 kB, app/page chunk 524,809 B raw, total client JS 2,034,348 B raw / 568,167 B gzip. ANALYZE=1 verified to emit .next/analyze/{client,nodejs,edge}.html; default build verified NOT to emit them. 3300 vitest tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- canvas/next.config.ts | 44 ++++++- canvas/package-lock.json | 260 ++++++++++++++++++++++++++++++++++----- canvas/package.json | 1 + 3 files changed, 272 insertions(+), 33 deletions(-) diff --git a/canvas/next.config.ts b/canvas/next.config.ts index 351fd84a6..ddafeb696 100644 --- a/canvas/next.config.ts +++ b/canvas/next.config.ts @@ -2,6 +2,25 @@ import type { NextConfig } from "next"; import { existsSync, readFileSync } from "node:fs"; import { dirname, join } from "node:path"; +// Dev-only bundle-analyzer, gated behind ANALYZE=1 so the default +// `next build` (and the production canvas Docker image build) is +// completely unaffected: when ANALYZE is unset, withBundleAnalyzer is +// the identity function and @next/bundle-analyzer is never require()'d +// at build time. Run `ANALYZE=1 pnpm --filter canvas build` (or +// `ANALYZE=1 npm run build` inside canvas/) to emit the client/server +// treemap HTML under canvas/.next/analyze/. +// +// require() (not import) so the dev-only dependency is resolved lazily: +// a production-only install that omits devDependencies never reaches +// the require because the ANALYZE guard short-circuits first. +const withBundleAnalyzer = + process.env.ANALYZE === "1" + ? // eslint-disable-next-line @typescript-eslint/no-require-imports + (require("@next/bundle-analyzer") as typeof import("@next/bundle-analyzer"))( + { enabled: true }, + ) + : (config: NextConfig): NextConfig => config; + // Load NEXT_PUBLIC_* vars from the monorepo root .env so a fresh // `pnpm dev` works without a per-developer canvas/.env.local. Next.js // only auto-loads .env from the project root by default — but our @@ -38,9 +57,32 @@ checkAdminTokenPair(); const nextConfig: NextConfig = { output: "standalone", + experimental: { + // Tree-shake barrel re-export packages so importing one symbol + // does not pull the package's entire index into the route chunk. + // Each entry is a package the canvas imports via its barrel (the + // package root, not a deep path) and which ships a large index: + // - @radix-ui/react-* — each re-exports its full primitive set + // - @xyflow/react — large flow-graph barrel (heaviest dep) + // - react-markdown / remark-gfm — markdown pipeline barrels + // Every entry is a package.json dependency the canvas imports via + // its barrel root. Measured impact is reported in the PR body via + // the ANALYZE=1 treemap baseline. This is a build-time transform + // only; runtime behaviour and the default `next build` output path + // are unchanged. + optimizePackageImports: [ + "@radix-ui/react-alert-dialog", + "@radix-ui/react-dialog", + "@radix-ui/react-tabs", + "@radix-ui/react-tooltip", + "@xyflow/react", + "react-markdown", + "remark-gfm", + ], + }, }; -export default nextConfig; +export default withBundleAnalyzer(nextConfig); function loadMonorepoEnv() { const root = findMonorepoRoot(__dirname); diff --git a/canvas/package-lock.json b/canvas/package-lock.json index e575c232a..bef1a93e8 100644 --- a/canvas/package-lock.json +++ b/canvas/package-lock.json @@ -26,6 +26,7 @@ "zustand": "^5.0.0" }, "devDependencies": { + "@next/bundle-analyzer": "^15.5.18", "@playwright/test": "^1.59.1", "@tailwindcss/postcss": "^4.0.0", "@testing-library/jest-dom": "^6.6.0", @@ -119,7 +120,6 @@ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", @@ -300,6 +300,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" }, @@ -348,30 +349,19 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=20.19.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" + "engines": { + "node": ">=10.0.0" } }, "node_modules/@emnapi/wasi-threads": { @@ -976,6 +966,16 @@ "@emnapi/runtime": "^1.7.1" } }, + "node_modules/@next/bundle-analyzer": { + "version": "15.5.18", + "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-15.5.18.tgz", + "integrity": "sha512-v5/UNFwYbBlRQg/Bt+wU65XuxCxPu1AeCOI6s4s6Cludsj7FdVO9E9uzr7GIj8OykSrYtGuEQAUX0Ulje8W2yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "webpack-bundle-analyzer": "4.10.1" + } + }, "node_modules/@next/env": { "version": "15.5.15", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.15.tgz", @@ -1126,6 +1126,7 @@ "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "playwright": "1.59.1" }, @@ -1136,6 +1137,13 @@ "node": ">=18" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, "node_modules/@radix-ui/primitive": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", @@ -2406,8 +2414,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/chai": { "version": "5.2.3", @@ -2530,6 +2537,7 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -2539,6 +2547,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2549,6 +2558,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2597,6 +2607,7 @@ "integrity": "sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.5", @@ -2801,13 +2812,38 @@ "d3-zoom": "^3.0.0" } }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -2818,7 +2854,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -3008,6 +3043,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3111,6 +3156,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3173,6 +3219,13 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true, + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -3253,8 +3306,14 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true, + "license": "MIT" }, "node_modules/enhanced-resolve": { "version": "5.21.0", @@ -3387,6 +3446,22 @@ "dev": true, "license": "ISC" }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3539,6 +3614,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -3600,8 +3685,7 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/jsdom": { "version": "29.1.1", @@ -3609,6 +3693,7 @@ "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@asamuzakjp/css-color": "^5.1.11", "@asamuzakjp/dom-selector": "^7.1.1", @@ -3931,7 +4016,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -4834,6 +4918,16 @@ "node": ">=4" } }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4949,6 +5043,16 @@ ], "license": "MIT" }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -5006,6 +5110,7 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -5093,7 +5198,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -5128,6 +5232,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -5137,6 +5242,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -5149,8 +5255,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-markdown": { "version": "10.1.0", @@ -5463,6 +5568,21 @@ "dev": true, "license": "ISC" }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5598,7 +5718,8 @@ "version": "4.2.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.4.tgz", "integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.3.3", @@ -5678,6 +5799,16 @@ "dev": true, "license": "MIT" }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tough-cookie": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", @@ -5940,6 +6071,7 @@ "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", @@ -6033,6 +6165,7 @@ "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.1.5", "@vitest/mocker": "4.1.5", @@ -6140,6 +6273,47 @@ "node": ">=20" } }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", + "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "is-plain-object": "^5.0.0", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/whatwg-mimetype": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", @@ -6182,6 +6356,28 @@ "node": ">=8" } }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", diff --git a/canvas/package.json b/canvas/package.json index b66efbf13..f9a27614b 100644 --- a/canvas/package.json +++ b/canvas/package.json @@ -29,6 +29,7 @@ "zustand": "^5.0.0" }, "devDependencies": { + "@next/bundle-analyzer": "^15.5.18", "@playwright/test": "^1.59.1", "@testing-library/jest-dom": "^6.6.0", "@testing-library/react": "^16.1.0", -- 2.52.0 From 31f658cafdf5babd7006412017ab3064c67d99ff Mon Sep 17 00:00:00 2001 From: core-fe Date: Sat, 16 May 2026 02:15:40 -0700 Subject: [PATCH 2/7] ci: re-trigger orphaned run 55590 (storm residue: canvas-deploy-reminder + all-required registered pending, no container ever scheduled; zombie pool now fully drained) [no-op] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empty commit — canonical Gitea-1.22.6 rerun mechanism. PR diff unchanged (next.config.ts + package.json + lockfile only). canvas-build and platform-build were already green on the prior SHA; only the aggregator + deploy-reminder were storm-orphaned. Co-Authored-By: Claude Opus 4.7 (1M context) -- 2.52.0 From 177b5f41e33f79c349413cea5166d061d48d7729 Mon Sep 17 00:00:00 2001 From: core-fe Date: Sat, 16 May 2026 02:38:30 -0700 Subject: [PATCH 3/7] =?UTF-8?q?ci:=20re-trigger=20run=2055811=20(INFRA=20f?= =?UTF-8?q?ailure,=20not=20logic=20=E2=80=94=20disk-GC=20pruned=20containe?= =?UTF-8?q?rd=20blobs=20mid-job:=20"blob=20not=20found"=20+=20"lstat=20/va?= =?UTF-8?q?r/lib/docker:=20no=20such=20file=20or=20directory"=20on=20post-?= =?UTF-8?q?build=20artifact/cleanup=20steps;=20host=20disk=20was=2088%>85%?= =?UTF-8?q?=20GC=20trigger;=20daemon=20since=20recovered,=20runner=20queue?= =?UTF-8?q?=20idle)=20[no-op]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Canvas build itself succeeded in the failed run (server-rendered output printed) before the post-build steps hit the vanished Docker storage backend. All sibling "Failing after 0s" jobs share the same root cause (container could not be mounted). Local repro is clean: default + ANALYZE build pass, 3300 vitest pass. Diff unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) -- 2.52.0 From 7194194ffc269b6ba4a667acb20aee7c6b0ce84a Mon Sep 17 00:00:00 2001 From: devops-engineer Date: Sat, 16 May 2026 03:13:29 -0700 Subject: [PATCH 4/7] ci: re-trigger CI on recovered runners (post data-root rollback 2026-05-16 09:54Z; prior checks stale-failed on pre-recovery 'blob not found' infra wall, not logic) [no-op] -- 2.52.0 From a31ef073e009690c1df0a768ea936a30b0363dfb Mon Sep 17 00:00:00 2001 From: devops-engineer Date: Sat, 16 May 2026 03:41:14 -0700 Subject: [PATCH 5/7] =?UTF-8?q?ci:=20fresh=20rerun=20=E2=80=94=20run=20563?= =?UTF-8?q?87=20orchestrator=20wedged=20(jobs=2098705/98707=20stuck=20stat?= =?UTF-8?q?us=3D5/7,=20no=20action=5Ftask=20ever=20materialized=20despite?= =?UTF-8?q?=20needs=20satisfied=20+=2020=20runners=20idle-polling;=20storm?= =?UTF-8?q?-era=20run-graph=20corruption,=20not=20logic)=20[no-op]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 2.52.0 From 5626f213ba639f0cb7dd4e4d546353479f53956b Mon Sep 17 00:00:00 2001 From: devops-engineer Date: Sat, 16 May 2026 04:36:51 -0700 Subject: [PATCH 6/7] =?UTF-8?q?ci:=20rerun=20=E2=80=94=20sop-checklist=20t?= =?UTF-8?q?ask=20110817=20individually=20orphaned=20(status=3D5=20runner?= =?UTF-8?q?=5Fid=3D0=2046min=20while=2019=20sibling=20sop=20runs=20succeed?= =?UTF-8?q?ed=20fleet-wide);=20fresh=20run=20schedules=20normally=20[no-op?= =?UTF-8?q?]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 2.52.0 From 0ef00841e04d883c6f91da2e5bceddee9c99b72b Mon Sep 17 00:00:00 2001 From: devops-engineer Date: Sat, 16 May 2026 05:58:32 -0700 Subject: [PATCH 7/7] ci: re-trigger after #468 crawler-overload mitigation (RunnerService RPC p95 11741ms->1273ms, dispatch recovered); prior run dispatch-starved, code unchanged [no-op] -- 2.52.0