Skip to content

[codex] Fix panel chunk TDZ startup crash#3943

Merged
koala73 merged 1 commit into
mainfrom
codex/fix-panel-chunk-tdz
May 28, 2026
Merged

[codex] Fix panel chunk TDZ startup crash#3943
koala73 merged 1 commit into
mainfrom
codex/fix-panel-chunk-tdz

Conversation

@koala73

@koala73 koala73 commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • keep panel component modules in the single panels chunk to avoid the core-panels/full-panels ESM TDZ startup crash
  • remove the unused staged panel-cluster map after review feedback
  • strengthen chunk guard tests so variant/domain panel chunks cannot be re-enabled silently while top-level service clients remain

Tradeoff

This is an explicit stability-first rollback of the panel chunk split from #3113. The merged build still statically imports/modulepreloads the unified panels chunk, so the whole panel bundle downloads eagerly at boot and one-panel edits invalidate that shared chunk for all users. That cost is accepted here because the split was crashing production.

Follow-up

Track the performance recovery in #3944: lazy-initialize panel service-client singletons, then re-split panel chunks and relax/update the guard tests once the TDZ risk is removed.

Validation

  • node --test tests/chunk-assignment.test.mjs
  • git diff --check
  • npm run build:full
  • production preview smoke with Playwright: HTTP 200, no page errors, no ReferenceError
  • ./.husky/pre-push

@vercel

vercel Bot commented May 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment May 28, 2026 5:08am

Request Review

@koala73
koala73 marked this pull request as ready for review May 28, 2026 04:54
@greptile-apps

greptile-apps Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a startup ReferenceError (temporal dead zone crash) caused by a circular ESM evaluation cycle (core-panels → full-panels → core-panels) from splitting panel components into multiple variant-specific chunks. The fix collapses all *Panel.ts modules back into a single panels chunk, removes the five variant *_PANEL_FILES sets, and replaces the old granular tests with new guardrail tests that prevent the problematic splitting patterns from being silently re-enabled.

  • vite.config.ts: Replaces multi-set panel routing (CORE/HAPPY/FINANCE/FULL/TECH) with a single return 'panels' for all src/components/*Panel.ts modules; marks PANEL_CLUSTER as staged-only.
  • tests/chunk-assignment.test.mjs: Drops file-system–based panel assignment tests in favour of three source-text regex guards asserting the unified chunk is present and variant/domain chunk names cannot be re-enabled.

Confidence Score: 4/5

The core vite.config.ts consolidation is low-risk and correctly removes the circular chunk dependency; the test guardrails are directionally right but have a robustness gap that could let the protections silently degrade.

The vite.config.ts change is a clean rollback of the problematic splitting logic. The tests introduce a useful guardrail pattern, but the doesNotMatch assertions pass vacuously on an empty manualChunksSource string — if the sentinel comment shifts, a future developer re-enabling variant chunks would see all tests green with no real enforcement.

tests/chunk-assignment.test.mjs — the manualChunksSource extraction and the two negative-assertion tests warrant a closer look before merging.

Important Files Changed

Filename Overview
vite.config.ts Removes variant panel chunk sets and replaces complex routing with a single panels return for all *Panel.ts files; PANEL_CLUSTER is now entirely unused dead code not flagged by TypeScript since vite.config.ts is outside the tsconfig include scope.
tests/chunk-assignment.test.mjs New guardrail tests are sound in the happy path, but the manualChunksSource extraction falls back to '' via ?? ''; the two doesNotMatch assertions silently pass on an empty string, making guards 2 and 3 vacuous if the sentinel comment ever changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["manualChunks(id)"] --> B{id in node_modules?}
    B -- Yes --> C[Route to vendor chunks]
    B -- No --> D{"id.includes('/src/components/')
&& id.endsWith('Panel.ts')"}
    D -- Yes --> E["return 'panels'\n(single unified chunk)"]
    D -- No --> F{id matches locale?}
    F -- Yes --> G["return 'locale-XX'"]
    F -- No --> H[undefined - Vite default chunking]

    subgraph STAGED ["STAGED - not wired in"]
        PC["PANEL_CLUSTER map\n(panels-markets, panels-energy..."]
    end

    style STAGED fill:#fef9c3,stroke:#ca8a04
    style E fill:#dcfce7,stroke:#16a34a
Loading

Comments Outside Diff (1)

  1. vite.config.ts, line 35-102 (link)

    P2 PANEL_CLUSTER is never referenced in any executable code path after this PR — it appears only in a comment on line 1025. Because vite.config.ts is outside tsconfig.json's include: ["src"] scope, noUnusedLocals: true will not flag it. The ~67-line map adds maintenance surface area and may mislead a future contributor into thinking it is already wired into the build.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "fix(build): keep panel modules in one ch..." | Re-trigger Greptile

Comment on lines +13 to +14
describe('panel chunk assignment guardrails', () => {
it('keeps panel component modules in one chunk until TDZ-prone singletons are removed', () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 The doesNotMatch assertions on tests 2 and 3 pass vacuously whenever manualChunksSource is an empty string. If the sentinel comment // Give lazy-loaded locale chunks is ever renamed or reformatted, the ?? '' fallback silently activates and both negative guards become no-ops — a future developer re-enabling a variant chunk would see green tests with no real coverage. Adding an explicit non-empty assertion at the top of the suite makes the extraction failure visible before the guards even run.

Suggested change
describe('panel chunk assignment guardrails', () => {
it('keeps panel component modules in one chunk until TDZ-prone singletons are removed', () => {
describe('panel chunk assignment guardrails', () => {
it('extracts the manualChunks body successfully (sentinel comment must remain intact)', () => {
assert.match(
manualChunksSource,
/\S/,
'manualChunksSource is empty — the sentinel comment "// Give lazy-loaded locale chunks" may have been renamed or moved.',
);
});
it('keeps panel component modules in one chunk until TDZ-prone singletons are removed', () => {

it('does not re-enable variant panel chunks that create circular ESM evaluation', () => {
assert.doesNotMatch(
manualChunksSource,
/return\s+'(?:core|full|finance|happy|tech)-panels'/,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The guard regex only matches single-quoted string literals. Vite config is TypeScript, and either 'core-panels' or "core-panels" is valid. A developer re-enabling variant chunks with double-quoted return values would slip past this check.

Suggested change
/return\s+'(?:core|full|finance|happy|tech)-panels'/,
/return\s+['"](?:core|full|finance|happy|tech)-panels['"]/,

Comment thread tests/chunk-assignment.test.mjs Outdated
'The silent catch-all that routes unassigned panels to core-panels must not exist. ' +
'Use the throw-on-unassigned pattern instead.'
manualChunksSource,
/PANEL_CLUSTER\s*(?:\.|\[)|return\s+'panels-[a-z-]+'/,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Same quote-style gap in the PANEL_CLUSTER guard: return 'panels-[a-z-]+' only covers single-quoted values, so return "panels-markets" (double quotes) would not be caught.

Suggested change
/PANEL_CLUSTER\s*(?:\.|\[)|return\s+'panels-[a-z-]+'/,
/PANEL_CLUSTER\s*(?:\.|\[)|return\s+['"]panels-[a-z-]+['"]/,

@koala73
koala73 force-pushed the codex/fix-panel-chunk-tdz branch from 4632b7e to 6b97c39 Compare May 28, 2026 05:04
@koala73
koala73 merged commit bae846b into main May 28, 2026
11 checks passed
@koala73
koala73 deleted the codex/fix-panel-chunk-tdz branch May 28, 2026 05:12
koala73 added a commit that referenced this pull request May 28, 2026
…ry) (#3947)

Production was rolled back (Vercel deployment promotion) to the #3941 build
after #3942 + #3113 broke the dashboard: panels out of order, most panels
stuck on "Loading...", Live News never loaded, panel layout not persisting,
and repeated /api/user-prefs 409s. The deployment rollback fixed the live
app, but git main still pointed at #3945 — so any merge/redeploy of main
would silently reintroduce the entire breakage.

This commit makes main's tree identical to the #3941 build that is currently
serving production, undoing the net effect of:
  - #3939 (ML worker → Hugging Face Transformers)
  - #3942 (cloud panel-order sync)
  - #3113 (barrel elimination + variant panel chunks + SW precache change)
  - #3943 (single panels chunk follow-up)
  - #3945 (panel preference sync stabilization)

Nothing is permanently discarded — this is a revert. The genuinely valuable
pieces will be re-landed as separate, isolated, individually-verifiable PRs:
  - cloud-prefs upload coalescing (#3945) + dead-key fix (#3942), WITHOUT
    syncing panel-order (panel order stays local-only)
  - barrel-file elimination (#3113), measured, on its own
  - ML worker migration (#3939), on its own
The variant chunk split + SW precache change stay parked until panel modules'
top-level service clients are lazy-initialized.
zeisuke added a commit to zeisuke/worldmonitor that referenced this pull request May 29, 2026
* 'main' of https://github.com/koala73/worldmonitor: (163 commits)
  perf(mcp): disable rate-limiter Redis retries to unblock test suite (koala73#3963)
  ci: add defensibility smoke gates (koala73#3962)
  Freeze verified pc resilience snapshot (koala73#3960)
  Align resilience methodology docs (koala73#3961)
  Fix resilience reference edition audit artifacts (koala73#3959)
  fix resilience validation artifacts (koala73#3958)
  Clarify AGPL commercial-use terms (koala73#3957)
  fix(auth): remove duplicate header settings gear for signed-in users (koala73#3950)
  revert: restore main to koala73#3941 deployed-good baseline (incident recovery) (koala73#3947)
  fix(ui): stabilize panel preference sync (koala73#3945)
  fix(build): keep panel modules in one chunk (koala73#3943)
  feat: eliminate barrel file, split panels into variant-based chunks (koala73#3113)
  [codex] fix cloud preference panel sync (koala73#3942)
  [codex] migrate ML worker to Hugging Face Transformers (koala73#3939)
  [codex] fix panel drag reorder semantics (koala73#3941)
  fix(ui): enforce safe html sinks (koala73#3940)
  chore(blog-site): drop unused direct fast-xml-builder dep (koala73#3938)
  docs(widget): justify sandbox postMessage target (koala73#3937)
  [codex] Live Reliability / Variant Smoke (koala73#3925)
  [codex] Recalibrate CII severity and salience scoring (koala73#3927)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant