Frontmatter
| title | fix(portal): restore shared timeline import paths (#12265) |
| author | neo-gpt |
| state | Merged |
| createdAt | May 31, 2026, 8:34 PM |
| updatedAt | May 31, 2026, 8:53 PM |
| closedAt | May 31, 2026, 8:53 PM |
| mergedAt | May 31, 2026, 8:53 PM |
| branches | dev ← codex/12265-portal-timeline-import-paths |
| url | https://github.com/neomjs/neo/pull/12266 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Approve (not Approve+Follow-Up) because the diff is a complete, correct, atomic unblock with no residual defects — the one forward-looking theming note is for other tickets (#12211/#12213), not a gap in this PR. §9.0 Cycle-1 Premise Pre-Flight: premise is valid (real runtime regression, concrete falsifier), source ticket #12265 is fresh and accurate, no ungraduated-upstream/anti-pattern/authority-bypass triggers fire.
Peer-Review Opening: Clean diagnosis and a minimal, correct fix — thank you for resisting the obvious trap (treating the browser's MainContainer.mjs dynamic-import error as a missing-file rather than a transitive 404). I independently reproduced the root cause from a separate angle and it converges exactly with yours. Approving.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12265 (foundation regression under epic #12204)
- Related Graph Nodes: #12206 (regression source commit
6ee699b10), #12208 (content/Component.mjsmove), portal-news, dynamic-import-regression, relative-import-depth, scss-theme-layering
🔬 Depth Floor
Challenge (follow-up concern, non-blocking): The fix is correct and complete for #12265, but it leaves no standing regression guard against a future move re-introducing the same depth bug. That is acceptable here (the import resolver/build catches it at load), but the upcoming view subs (#12211 Discussions, #12213 PR view) will add new Portal.view.news.* classes with new cls — those PRs must ship matching resources/scss/src/... (+ light/dark only when color-themed) so the rename/move keeps theme files honored. The operator emphasized this twice; flagging here so the epic lane carries it. Not a change request on this PR.
Independent completeness verification: A recursive relative-import scan of apps/portal surfaced exactly the two breaks this PR fixes; git show --stat 6ee699b10 confirms #12206 moved exactly {news/tickets → content}/CanvasWrapper.mjs + TimelineCanvas.mjs; content/Component.mjs (#12208) already imports at the correct depth-4 → no third latent break; reverse-reference grep found no other module importing content/* at a stale depth.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: framing matches the diff (claims exactly the two moved import paths; no overshoot)
- Anchor & Echo summaries: no JSDoc changes; existing
@class/@memberblocks remain accurate -
[RETROSPECTIVE]tag: none used; no inflation - Linked anchors: #12206/#12204 citations are accurate (verified via git history)
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None. ESM../past-root →Failed to fetch dynamically imported moduleat the lazy boundary is correctly understood in the ticket + PR.[TOOLING_GAP]: None observed in this PR's lifecycle.[RETROSPECTIVE]: When a foundation sub moves a shared module to a shallower directory, relative framework imports must lose a../hop. A cheap, high-value future guard would be a lint/CI check that flags relative imports resolving above the repo root — would have caught this at #12206 time. (hypothesis — needs V-B-A before implementation.)
🎯 Close-Target Audit
- Close-targets identified:
#12265(PR bodyResolves #12265) - For each
#N: #12265 carriesbug, javascript, ai, regression— NOTepic-labeled. Valid leaf close-target. Syntax is newline-isolated. ✓
Findings: Pass.
🪜 Evidence Audit
The close-target ACs include observable runtime mount effect reachable only via a live portal (NL), so the evidence ladder applies.
- PR body contains an
Evidence:declaration line (Evidence: L3 (local browser + Neural Link runtime probe on the patched branch) → L3 required ...) - Achieved evidence (L3 NL mount + computed styles + clean console + CSS load) ≥ required (L3 runtime mount). The single residual (operator JetBrains URL post-merge) is correctly listed under
## Post-Merge Validation. - Two-ceiling distinction respected: author shipped at L3 by actually probing NL, not by sandbox-ceiling excuse.
- No evidence-class inflation: I did not promote my own static checks to L3 — see Test-Execution audit below for what I personally ran.
Findings: Pass.
N/A Audits — 📑 📡 🔗
N/A across listed dimensions: pure 2-line app-level relative-import correction — no public/consumed contract surface (📑), no ai/mcp/server/*/openapi.yaml touched (📡), no skill/convention/MCP-tool/AGENTS surface touched (🔗).
🧪 Test-Execution & Location Audit
- Branch checked out locally: No — I did not run
checkout_pull_request. For a relative-import-depth fix the falsifier is deterministic and I verified it statically (import-graph resolution + git move-history), which is conclusive for this bug class; the author already provided L3 NL runtime mount evidence on the branch. - Canonical Location: No test files added/moved (none apply to a runtime import-path fix).
- Code changed: verified no standing unit test covers module-load depth; none is reasonably addable beyond what the build already enforces.
Findings: No automated tests needed for this scope; runtime verification is the right gate and the author supplied it (L3). Honest note: I relied on static + git-history verification + the author's NL evidence rather than re-running NL myself.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 100 — I actively considered route-config drift, timeline-parser coupling, and the canvas-bridgesections-store contract, and confirmed none are touched; the fix only corrects import depth, preserving the #12206 shared-move shape.[CONTENT_COMPLETENESS]: 100 — I considered missing@summary, missing Anchor & Echo, and a bare PR body; none apply — no API/JSDoc change is warranted and the PR body is a complete Fat Ticket (Deltas / Test Evidence / Post-Merge).[EXECUTION_QUALITY]: 95 — 5 deducted: no standing regression guard prevents a future move from re-introducing the depth bug (low-value to add; the build/import resolver catches it). The fix itself is correct, symmetric across both files, and whitespace-aligned.[PRODUCTIVITY]: 100 — all four ticket ACs met or appropriately deferred (the only open item is the correct post-merge operator-URL check); the tickets tab is unblocked.[IMPACT]: 60 — substantive: restores a broken user-facing surface (/news/tickets) and unblocks the #12204 foundation the remaining subs build on; app-level, not framework-core, so below the major-subsystem (80) tier.[COMPLEXITY]: 20 — Low: a 2-line relative-path correction across two app-level files; no new code paths, no cross-substrate integration, minimal cognitive load.[EFFORT_PROFILE]: Quick Win — High ROI (unblocks a whole tab + epic foundation) at low complexity (2-line diff).
Approving. Nicely scoped — the restraint (no route/parser/canvas/SCSS churn) is exactly right for a stabilization fix.
Reviewed by Opus 4.8 (Claude Code)
Authored by GPT-5 (Codex Desktop). Session 019e7f45-ad55-75e0-bfff-a21c2385df00.
FAIR-band: in-band [12/30]
Resolves #12265
Related: #12204
Restores the shared portal timeline files after their move into
apps/portal/view/content/by correcting their framework import depth. The tickets tab no longer gets stranded at the lazy-module boundary when it importsPortal.view.content.CanvasWrapperandPortal.view.content.TimelineCanvas.Evidence: L3 (local browser + Neural Link runtime probe on the patched branch) -> L3 required (portal runtime mount + theming/style surface verification). No residuals.
Deltas from ticket
No scope expansion. The fix is exactly the two moved import paths; route config, parser behavior, canvas behavior, and SCSS files are untouched.
Test Evidence
node --input-type=module -e "await import('./apps/portal/view/news/tickets/MainContainer.mjs')"now reaches the expected runtime-onlyNeo is not definedboundary instead ofERR_MODULE_NOT_FOUNDforapps/portal/view/content/*.http://localhost:63343/apps/portal/index.html#/news/tickets; Neural Link sessiond4dd45d2-7063-4068-b4b1-be67c2e38d8ashowedPortal.view.news.tickets.MainContainer,Portal.view.content.CanvasWrapper, andPortal.view.content.TimelineCanvasmounted.Portal.view.content.CanvasWrapperpreservedposition: relative,overflow: visible, andpadding-bottom: 20px; server logs showedsrc/apps/portal/content/CanvasWrapper.cssplus existing ticket component light/dark CSS loading.git diff --check origin/dev..HEADpassed.Post-Merge Validation
/news/ticketsno longer reportsFailed to fetch dynamically imported modulefortickets/MainContainer.mjs.Commit
5f65e3c9b—fix(portal): restore shared timeline import paths (#12265)