@rubytech/create-maxy-code 0.1.478 → 0.1.480
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1789-reseat-channel-row-fork.md +1244 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1818-loop-gate-app-routes.md +462 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1819-top-level-label-allowlist.md +321 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1829-platform-ui-typecheck.md +830 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1831-data-portal-class-derived-allowlist.md +2177 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1789-reseat-channel-row-fork-design.md +201 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1818-loop-gate-app-routes-design.md +217 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1819-top-level-label-allowlist-design.md +80 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1829-platform-ui-typecheck-design.md +163 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1831-data-portal-class-derived-allowlist-design.md +163 -0
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +22 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +6 -0
- package/payload/platform/lib/graph-style/src/index.ts +20 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +155 -12
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +3 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +68 -28
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
- package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +194 -16
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +74 -29
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +13 -1
- package/payload/platform/plugins/cloudflare/PLUGIN.md +26 -1
- package/payload/platform/plugins/cloudflare/bin/d1-http.mjs +80 -0
- package/payload/platform/plugins/cloudflare/bin/portal-enrol.mjs +17 -2
- package/payload/platform/plugins/cloudflare/bin/portal-index-push.mjs +357 -0
- package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +103 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +2 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/d1-http.test.ts +96 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-directory-listing.test.ts +120 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +59 -4
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-push.test.ts +176 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-state-contract.test.ts +75 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-indexed-download.test.ts +131 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-sign.test.ts +68 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/schema-exposed-dirs.test.ts +88 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +39 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +68 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +30 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/portal-sign.mjs +87 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +8 -4
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/types.ts +10 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/download.ts +107 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/files.ts +82 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/index.html +9 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.css +56 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.js +98 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +12 -0
- package/payload/platform/plugins/docs/references/cloudflare.md +12 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js +41 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/device-flow.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js +249 -2
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/graph-client.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js +127 -3
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/token-store.test.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts +17 -0
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js +26 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/device-flow.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts +37 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js +126 -5
- package/payload/platform/plugins/outlook/mcp/dist/auth/token-store.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts +18 -0
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js +123 -18
- package/payload/platform/plugins/outlook/mcp/dist/lib/graph-client.js.map +1 -1
- package/payload/platform/plugins/outlook/references/auth.md +45 -2
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.js +66 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.d.ts +41 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.js +75 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +122 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/server/{chunk-3XLLTG6R.js → chunk-REWXLAPC.js} +30 -10
- package/payload/server/package.json +1 -1
- package/payload/server/public/activity.html +7 -6
- package/payload/server/public/assets/{AdminLoginScreens-DR5eLF-a.js → AdminLoginScreens-DXYJWXaX.js} +1 -1
- package/payload/server/public/assets/AdminShell-UDgNN4CA.js +2 -0
- package/payload/server/public/assets/Checkbox-C08Ulc_a.js +1 -0
- package/payload/server/public/assets/activity-06gsRDVv.js +1 -0
- package/payload/server/public/assets/admin-BhiHyORH.js +1 -0
- package/payload/server/public/assets/{arc-BrHWN2Kr.js → arc-BHXuzTwg.js} +1 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-Ct5q6ks1.js +1 -0
- package/payload/server/public/assets/{architectureDiagram-Q4EWVU46-Clt9NOr0.js → architectureDiagram-Q4EWVU46-DsN_vxau.js} +1 -1
- package/payload/server/public/assets/{blockDiagram-DXYQGD6D-BOe_jmXi.js → blockDiagram-DXYQGD6D-CvNat1uB.js} +1 -1
- package/payload/server/public/assets/browser-Cz4IKS47.js +1 -0
- package/payload/server/public/assets/{c4Diagram-AHTNJAMY-B64FaKMV.js → c4Diagram-AHTNJAMY-E9yqTPTW.js} +1 -1
- package/payload/server/public/assets/calendar-D0xtNqH8.js +1 -0
- package/payload/server/public/assets/channel-PE9vBKEQ.js +1 -0
- package/payload/server/public/assets/chat-DwLJ830n.js +1 -0
- package/payload/server/public/assets/chevron-left-Cv-TFuEf.js +1 -0
- package/payload/server/public/assets/{chunk-2KRD3SAO-BGAUfWvM.js → chunk-2KRD3SAO-DpzI_0EY.js} +1 -1
- package/payload/server/public/assets/{chunk-336JU56O-PFi6uQZ0.js → chunk-336JU56O-eR_I9Eu4.js} +2 -2
- package/payload/server/public/assets/chunk-426QAEUC-BDNZtJsz.js +1 -0
- package/payload/server/public/assets/{chunk-4BX2VUAB-CkxXXCiF.js → chunk-4BX2VUAB-D-6xk1t8.js} +1 -1
- package/payload/server/public/assets/{chunk-4TB4RGXK-B-7tN4IA.js → chunk-4TB4RGXK-BkqUcFpL.js} +1 -1
- package/payload/server/public/assets/{chunk-55IACEB6-CBkNmqrt.js → chunk-55IACEB6-ChCl2pSP.js} +1 -1
- package/payload/server/public/assets/{chunk-5FUZZQ4R-wa9ujn7i.js → chunk-5FUZZQ4R-DasGsg54.js} +1 -1
- package/payload/server/public/assets/{chunk-5PVQY5BW-DIk-xBaE.js → chunk-5PVQY5BW-DXlHUX1h.js} +1 -1
- package/payload/server/public/assets/{chunk-67CJDMHE-BbMV1lgW.js → chunk-67CJDMHE-BZfVpTsE.js} +1 -1
- package/payload/server/public/assets/{chunk-7N4EOEYR-C49Mv-nQ.js → chunk-7N4EOEYR-C6U5TIgT.js} +1 -1
- package/payload/server/public/assets/{chunk-AA7GKIK3-Dy_pJOp_.js → chunk-AA7GKIK3-CA7cVDmw.js} +1 -1
- package/payload/server/public/assets/{chunk-BSJP7CBP-Ce-OmPqn.js → chunk-BSJP7CBP-DxN2GC3p.js} +1 -1
- package/payload/server/public/assets/{chunk-CIAEETIT-tnjq-APC.js → chunk-CIAEETIT-C0-4wA8y.js} +1 -1
- package/payload/server/public/assets/{chunk-EDXVE4YY-Bvv_deZ2.js → chunk-EDXVE4YY--kyb1rLc.js} +1 -1
- package/payload/server/public/assets/{chunk-ENJZ2VHE-CmxCPKyU.js → chunk-ENJZ2VHE-FBN6hR7V.js} +1 -1
- package/payload/server/public/assets/{chunk-FMBD7UC4-Top6y08S.js → chunk-FMBD7UC4-Lpge4M5g.js} +1 -1
- package/payload/server/public/assets/{chunk-FOC6F5B3-B9LPNCUS.js → chunk-FOC6F5B3-CM1rwOou.js} +1 -1
- package/payload/server/public/assets/{chunk-ICPOFSXX-Bi-_c351.js → chunk-ICPOFSXX-JdYLY3yu.js} +2 -2
- package/payload/server/public/assets/{chunk-K5T4RW27-DAnRM04h.js → chunk-K5T4RW27-DCUblGBr.js} +1 -1
- package/payload/server/public/assets/{chunk-KGLVRYIC-C0QYcbLe.js → chunk-KGLVRYIC-BP_cide2.js} +1 -1
- package/payload/server/public/assets/{chunk-LIHQZDEY-BjvA5ykt.js → chunk-LIHQZDEY-DjMa1lOl.js} +1 -1
- package/payload/server/public/assets/{chunk-ORNJ4GCN-Cs46Gj7z.js → chunk-ORNJ4GCN-D51eJAoV.js} +1 -1
- package/payload/server/public/assets/{chunk-OYMX7WX6-BBpimab5.js → chunk-OYMX7WX6-4hWIO544.js} +1 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-B_Hris8x.js +1 -0
- package/payload/server/public/assets/{chunk-U2HBQHQK-CQUSBHoK.js → chunk-U2HBQHQK-BwdQf9cS.js} +1 -1
- package/payload/server/public/assets/{chunk-X2U36JSP-Dm8TevG0.js → chunk-X2U36JSP-DmDxwLOg.js} +1 -1
- package/payload/server/public/assets/{chunk-XPW4576I-B10QuxYb.js → chunk-XPW4576I-JQyAB7ND.js} +1 -1
- package/payload/server/public/assets/{chunk-YZCP3GAM-vaGsu4Wk.js → chunk-YZCP3GAM-BonLdCzI.js} +1 -1
- package/payload/server/public/assets/{chunk-ZZ45TVLE-D1Qi22bL.js → chunk-ZZ45TVLE-BXKB2wSk.js} +1 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-D8Q05iMI.js +1 -0
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-Dm3hAxfm.js +1 -0
- package/payload/server/public/assets/clone-C-wOwvpY.js +1 -0
- package/payload/server/public/assets/{cose-bilkent-S5V4N54A-CRDvLRXs.js → cose-bilkent-S5V4N54A-BDnd4Blw.js} +1 -1
- package/payload/server/public/assets/{dagre-CEmqJTt3.js → dagre-BmexzuER.js} +1 -1
- package/payload/server/public/assets/{dagre-KV5264BT-LXMTo7Fp.js → dagre-KV5264BT-D4WVuwPj.js} +1 -1
- package/payload/server/public/assets/data-DUDJfnjI.js +1 -0
- package/payload/server/public/assets/{diagram-5BDNPKRD-zyis6nPt.js → diagram-5BDNPKRD-Bbf4mT8a.js} +1 -1
- package/payload/server/public/assets/{diagram-G4DWMVQ6-BiU0XAAD.js → diagram-G4DWMVQ6-BpqVTUmx.js} +1 -1
- package/payload/server/public/assets/{diagram-MMDJMWI5-rGFiz1SX.js → diagram-MMDJMWI5-DY-k5k6r.js} +1 -1
- package/payload/server/public/assets/{diagram-TYMM5635-B0wak1ZJ.js → diagram-TYMM5635-CXHxwacS.js} +1 -1
- package/payload/server/public/assets/{erDiagram-SMLLAGMA-D8AUxLyX.js → erDiagram-SMLLAGMA-BNKEc3l8.js} +1 -1
- package/payload/server/public/assets/{flatten-naJ5PJ4f.js → flatten-jn8bZgcI.js} +1 -1
- package/payload/server/public/assets/{flowDiagram-DWJPFMVM-BtdUf68b.js → flowDiagram-DWJPFMVM-CbAeuJsi.js} +1 -1
- package/payload/server/public/assets/{ganttDiagram-T4ZO3ILL-C-lkzDmf.js → ganttDiagram-T4ZO3ILL-CeeNnL4l.js} +1 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-BBHsY16R.js +1 -0
- package/payload/server/public/assets/{gitGraphDiagram-UUTBAWPF-DRUKumq2.js → gitGraphDiagram-UUTBAWPF-DG8RCtfg.js} +1 -1
- package/payload/server/public/assets/{graph-DRloNic4.js → graph-BAoktBcx.js} +19 -19
- package/payload/server/public/assets/graph-labels-LeIhl7ZG.js +1 -0
- package/payload/server/public/assets/{graphlib-zRsaoFEC.js → graphlib-BkDExPQi.js} +1 -1
- package/payload/server/public/assets/info-OMHHGYJF-C1j5I_zx.js +1 -0
- package/payload/server/public/assets/infoDiagram-42DDH7IO-ZWkwHWEu.js +2 -0
- package/payload/server/public/assets/{isEmpty-Bnpg7b8f.js → isEmpty-Dkk6_L-B.js} +1 -1
- package/payload/server/public/assets/{ishikawaDiagram-UXIWVN3A-BguMgoR8.js → ishikawaDiagram-UXIWVN3A-D_iMHV64.js} +1 -1
- package/payload/server/public/assets/{journeyDiagram-VCZTEJTY-CXhyK1n-.js → journeyDiagram-VCZTEJTY-BvPRpulx.js} +1 -1
- package/payload/server/public/assets/{kanban-definition-6JOO6SKY-C0UCWVx-.js → kanban-definition-6JOO6SKY-CkWaXWo2.js} +1 -1
- package/payload/server/public/assets/{line--uhS9YDE.js → line-BGQT9unx.js} +1 -1
- package/payload/server/public/assets/{linear-CAOWPodQ.js → linear-DzrYI8-8.js} +1 -1
- package/payload/server/public/assets/{maximize-2-CzDaBugs.js → maximize-2-2MgPSwlx.js} +1 -1
- package/payload/server/public/assets/{mermaid-parser.core-D6kPx7vc.js → mermaid-parser.core-DrMY7FMe.js} +2 -2
- package/payload/server/public/assets/{mermaid.core-CTd4DS6O.js → mermaid.core-BWdf6fZ7.js} +3 -3
- package/payload/server/public/assets/{mindmap-definition-QFDTVHPH-_AyvyG8C.js → mindmap-definition-QFDTVHPH-CgqM9h97.js} +1 -1
- package/payload/server/public/assets/operator-CZifmNhp.js +1 -0
- package/payload/server/public/assets/{ordinal-Wx4m9zHk.js → ordinal-DuJYM7p1.js} +1 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-CGiTbe0N.js +1 -0
- package/payload/server/public/assets/{page-ef-6rRPL.js → page-B4kllGd_.js} +6 -6
- package/payload/server/public/assets/page-DbfE7QwJ.js +1 -0
- package/payload/server/public/assets/{pdf-render-CeX6d2v7.js → pdf-render-riHufgrn.js} +1 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-BrK023dE.js +1 -0
- package/payload/server/public/assets/{pieDiagram-DEJITSTG-6TsUDkkQ.js → pieDiagram-DEJITSTG-BeUGoYS7.js} +1 -1
- package/payload/server/public/assets/public-VtmyYz8E.js +1 -0
- package/payload/server/public/assets/{quadrantDiagram-34T5L4WZ-CWw9gOI4.js → quadrantDiagram-34T5L4WZ-CX82WgKy.js} +1 -1
- package/payload/server/public/assets/radar-PYXPWWZC-p7NRamXX.js +1 -0
- package/payload/server/public/assets/{reduce-BUmc8RDR.js → reduce-COyotL2V.js} +1 -1
- package/payload/server/public/assets/{requirementDiagram-MS252O5E-DCOlxNvx.js → requirementDiagram-MS252O5E-CzqebQXj.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-DXEKUhXP.js → rotate-ccw-DaZdB2cz.js} +1 -1
- package/payload/server/public/assets/{sankeyDiagram-XADWPNL6-CW4Xbir3.js → sankeyDiagram-XADWPNL6-CaHi1yzU.js} +1 -1
- package/payload/server/public/assets/{sequenceDiagram-FGHM5R23-vhb_pBLG.js → sequenceDiagram-FGHM5R23-BF2AeiKW.js} +1 -1
- package/payload/server/public/assets/{stateDiagram-FHFEXIEX-Cb1WExEX.js → stateDiagram-FHFEXIEX-DtUCA8Ih.js} +1 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-a4FvB3L8.js +1 -0
- package/payload/server/public/assets/tasks-CvqVDbfO.js +1 -0
- package/payload/server/public/assets/{time-entry-format-CsYAjplS.js → time-entry-format-TD-PPEIu.js} +1 -1
- package/payload/server/public/assets/{timeline-definition-GMOUNBTQ-BAHTf_AF.js → timeline-definition-GMOUNBTQ-D3Q1YrKY.js} +1 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CoWk8VoG.js +1 -0
- package/payload/server/public/assets/treemap-W4RFUUIX-BhWeGj8Y.js +1 -0
- package/payload/server/public/assets/{triangle-alert-0lSBIUg-.js → triangle-alert-BaLhVNnn.js} +1 -1
- package/payload/server/public/assets/useCopyFeedback-BhjPzRa3.js +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CWRpVt1-.css +1 -0
- package/payload/server/public/assets/{useSubAccountSwitcher-BZnzc5C3.js → useSubAccountSwitcher-HEVLb6Z9.js} +2 -2
- package/payload/server/public/assets/useVoiceRecorder-CfGgj3vm.js +2 -0
- package/payload/server/public/assets/{vennDiagram-DHZGUBPP-DtEttvW4.js → vennDiagram-DHZGUBPP-DnjzQDGf.js} +1 -1
- package/payload/server/public/assets/wardley-RL74JXVD-C0q3Hqng.js +1 -0
- package/payload/server/public/assets/{wardleyDiagram-NUSXRM2D-K06y6CVJ.js → wardleyDiagram-NUSXRM2D-T3WHrUvi.js} +1 -1
- package/payload/server/public/assets/{xychartDiagram-5P7HB3ND-D66c40lp.js → xychartDiagram-5P7HB3ND-2Efyv4h2.js} +1 -1
- package/payload/server/public/brand-defaults.css +1 -0
- package/payload/server/public/browser.html +4 -5
- package/payload/server/public/calendar.html +5 -6
- package/payload/server/public/chat.html +12 -13
- package/payload/server/public/data.html +11 -12
- package/payload/server/public/graph.html +10 -11
- package/payload/server/public/index.html +14 -15
- package/payload/server/public/operator.html +14 -15
- package/payload/server/public/privacy.html +1 -0
- package/payload/server/public/public.html +12 -13
- package/payload/server/public/tasks.html +7 -5
- package/payload/server/public/vnc-popout.html +1 -0
- package/payload/server/server.js +833 -389
- package/payload/server/{src-XQ63FPRE.js → src-JJ6PHO5I.js} +1 -1
- package/payload/server/public/assets/AdminShell-D9zaUxPd.js +0 -2
- package/payload/server/public/assets/Checkbox-DcbbAIe5.js +0 -1
- package/payload/server/public/assets/activity-C9P5NjEZ.js +0 -1
- package/payload/server/public/assets/admin-D2KLZnQW.js +0 -1
- package/payload/server/public/assets/architecture-YZFGNWBL-CZQzGRSM.js +0 -1
- package/payload/server/public/assets/browser-CDWqEiCD.js +0 -1
- package/payload/server/public/assets/calendar-BG7fOpbB.js +0 -1
- package/payload/server/public/assets/channel-zDUAN9Ks.js +0 -1
- package/payload/server/public/assets/chat-RyH-WYQC.js +0 -1
- package/payload/server/public/assets/chevron-left-DmXCr6nB.js +0 -1
- package/payload/server/public/assets/chunk-426QAEUC-iJnqNRug.js +0 -1
- package/payload/server/public/assets/chunk-QZHKN3VN-Qlc2PFAj.js +0 -1
- package/payload/server/public/assets/classDiagram-6PBFFD2Q-CFsKL52p.js +0 -1
- package/payload/server/public/assets/classDiagram-v2-HSJHXN6E-BWBUUCiO.js +0 -1
- package/payload/server/public/assets/clone-h5XhkDUL.js +0 -1
- package/payload/server/public/assets/data-BaY_LkLR.js +0 -1
- package/payload/server/public/assets/gitGraph-7Q5UKJZL-CBZPQJLj.js +0 -1
- package/payload/server/public/assets/graph-labels-DD-GqS4v.js +0 -1
- package/payload/server/public/assets/info-OMHHGYJF-1vIoX-kP.js +0 -1
- package/payload/server/public/assets/infoDiagram-42DDH7IO-KHcXRaan.js +0 -2
- package/payload/server/public/assets/operator-BZeeyait.js +0 -1
- package/payload/server/public/assets/packet-4T2RLAQJ-CTU0gCGb.js +0 -1
- package/payload/server/public/assets/page-B0obcg3b.js +0 -1
- package/payload/server/public/assets/pie-ZZUOXDRM-D-EEHxhC.js +0 -1
- package/payload/server/public/assets/public-9D3MMOkC.js +0 -1
- package/payload/server/public/assets/radar-PYXPWWZC-DHXATZGB.js +0 -1
- package/payload/server/public/assets/stateDiagram-v2-QKLJ7IA2-CxOIKvXh.js +0 -1
- package/payload/server/public/assets/tasks-BB0L7e5a.js +0 -1
- package/payload/server/public/assets/treeView-SZITEDCU-CC7ouMFd.js +0 -1
- package/payload/server/public/assets/treemap-W4RFUUIX-CaCg27im.js +0 -1
- package/payload/server/public/assets/useCopyFeedback-jTBQ2h0V.js +0 -1
- package/payload/server/public/assets/useSelectionMode-BooArySZ.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-D9knHOKq.css +0 -1
- package/payload/server/public/assets/useVoiceRecorder-PUT8q_sm.js +0 -2
- package/payload/server/public/assets/wardley-RL74JXVD-bMPsqQZ7.js +0 -1
- /package/payload/server/public/assets/{_baseFor-k8hYPe-U.js → _baseFor-Bjj9It3Q.js} +0 -0
- /package/payload/server/public/assets/{array-BFDiaBgf.js → array-BrrxEo12.js} +0 -0
- /package/payload/server/public/assets/{cytoscape.esm-Ch0xptA4.js → cytoscape.esm-CTWJxUxo.js} +0 -0
- /package/payload/server/public/assets/{defaultLocale-ZeknFqNe.js → defaultLocale-CFDbRV4k.js} +0 -0
- /package/payload/server/public/assets/{dist-B2N0v8hZ.js → dist-BATfy7Sn.js} +0 -0
- /package/payload/server/public/assets/{init-0VJVrkRJ.js → init-dXCzGgLP.js} +0 -0
- /package/payload/server/public/assets/{katex-Br7bH10N.js → katex-CHA1JFYJ.js} +0 -0
- /package/payload/server/public/assets/{path-INs8XTPH.js → path-CCRpdXhK.js} +0 -0
- /package/payload/server/public/assets/{preload-helper-D_sPnjeL.js → preload-helper-CH6UZRzu.js} +0 -0
- /package/payload/server/public/assets/{rough.esm-DU9bZLvZ.js → rough.esm-Bud4g4fh.js} +0 -0
- /package/payload/server/public/assets/{src-DHSQDYx-.js → src-DNdBRXXx.js} +0 -0
|
@@ -0,0 +1,830 @@
|
|
|
1
|
+
# Task 1829 — package-wide typecheck for `platform/ui` (implementation plan)
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Make a type error anywhere in `platform/ui` fail the build, with an empty ignore list.
|
|
6
|
+
|
|
7
|
+
**Architecture:** The gate is built first and used as the measuring instrument for every
|
|
8
|
+
subsequent task — it starts red at 70 errors and each task drives the count down. It is wired into
|
|
9
|
+
`prebuild` only in the final task, so the build is never left broken mid-plan. Every error is
|
|
10
|
+
removed at source; none is suppressed.
|
|
11
|
+
|
|
12
|
+
**Tech Stack:** TypeScript 5.7, `tsc --noEmit`, Node 22.22.0, vitest 4, plain `.mjs` gate scripts
|
|
13
|
+
invoked from `prebuild`.
|
|
14
|
+
|
|
15
|
+
## Global Constraints
|
|
16
|
+
|
|
17
|
+
- Work in `maxy-code/platform/ui` inside the worktree at
|
|
18
|
+
`/Users/neo/getmaxy/maxy-code/.claude/worktrees/task-1829-platform-ui-typecheck`.
|
|
19
|
+
- Node 22.22.0. Confirm with `node -v` before any `tsc` or `vitest` run.
|
|
20
|
+
- `platform/node_modules` and `platform/ui/node_modules` are symlinks into the parent checkout.
|
|
21
|
+
Never run `npm install` in `platform/ui` — it would mutate the parent's dependency tree. The
|
|
22
|
+
neo4j-driver change in Task 2 is applied to the shadow tree instead; the recipe is in that task.
|
|
23
|
+
- The sibling `platform/lib/*/dist` artefacts must exist before `tsc` runs. `npm run build:lib`
|
|
24
|
+
from `platform/` produces them, clean, in about 24 seconds.
|
|
25
|
+
- Baseline: **80 errors**, measured after `build:lib` with `platform/ui` still resolving
|
|
26
|
+
neo4j-driver to v6. Task 2 takes it to 70. Every task states the count it must leave behind, and
|
|
27
|
+
they chain: 80 → 70 → 62 → 59 → 20 → 0.
|
|
28
|
+
- No error is ever silenced with `@ts-ignore`, `@ts-expect-error`, `any`, or a `tsconfig` exclusion.
|
|
29
|
+
If a fix looks like it needs one, stop and raise it.
|
|
30
|
+
- Commit after each task with a `Session: 25c26868-c975-4386-b247-a6aa53f33090` trailer and
|
|
31
|
+
`Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### Task 1: The gate script — the failing test
|
|
36
|
+
|
|
37
|
+
Build the instrument before the work. It must be observed red at 70 before anything is fixed.
|
|
38
|
+
|
|
39
|
+
**Files:**
|
|
40
|
+
- Create: `platform/ui/scripts/check-types.mjs`
|
|
41
|
+
- Modify: `platform/ui/package.json` (add `typecheck` script only; prebuild is untouched until Task 9)
|
|
42
|
+
|
|
43
|
+
**Interfaces:**
|
|
44
|
+
- Produces: `scripts/check-types.mjs`, runnable as `node scripts/check-types.mjs` from
|
|
45
|
+
`platform/ui`. Exit 0 when `tsc --noEmit` emits no diagnostic; exit 1 otherwise.
|
|
46
|
+
|
|
47
|
+
- [ ] **Step 1: Write the gate**
|
|
48
|
+
|
|
49
|
+
Create `platform/ui/scripts/check-types.mjs`:
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
#!/usr/bin/env node
|
|
53
|
+
|
|
54
|
+
// Task 1829 — prebuild gate: the whole package must typecheck.
|
|
55
|
+
//
|
|
56
|
+
// Nothing in platform/ui ran the TypeScript compiler until this gate existed.
|
|
57
|
+
// `npm run build` is `vite build && tsup`, both esbuild-backed, and esbuild
|
|
58
|
+
// strips types without reading them. There is no lint script and no CI job that
|
|
59
|
+
// runs the compiler, so a type error in this package shipped.
|
|
60
|
+
//
|
|
61
|
+
// This replaces scripts/check-loop-contract-types.mjs (Task 1825), which ran the
|
|
62
|
+
// compiler and then discarded every error outside six named files. That was the
|
|
63
|
+
// right scope for one page's contract and the wrong shape for a package: six
|
|
64
|
+
// files were gated and roughly three hundred were not. Two gates asserting the
|
|
65
|
+
// same invariant at different scopes is the drift 1825 exists to prevent, so
|
|
66
|
+
// that gate is deleted rather than kept alongside this one.
|
|
67
|
+
//
|
|
68
|
+
// THE IGNORE LIST IS EMPTY, and this gate says so on every run. A gate that
|
|
69
|
+
// starts life with a long ignore list is a gate nobody trusts. The ignored count
|
|
70
|
+
// is printed so that if one is ever added, its growth is visible in build logs
|
|
71
|
+
// rather than inferred.
|
|
72
|
+
|
|
73
|
+
import { spawnSync } from 'node:child_process'
|
|
74
|
+
import { existsSync } from 'node:fs'
|
|
75
|
+
import { resolve, dirname } from 'node:path'
|
|
76
|
+
import { fileURLToPath } from 'node:url'
|
|
77
|
+
|
|
78
|
+
const UI_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
|
79
|
+
|
|
80
|
+
// Pre-flight 1: the sibling lib artefacts this package imports.
|
|
81
|
+
//
|
|
82
|
+
// platform/ui imports built sibling libs by relative path into `dist/`. Those
|
|
83
|
+
// are build outputs, gitignored, and absent in a fresh clone or worktree. With
|
|
84
|
+
// them missing the compiler reports fourteen unresolved-import errors that look
|
|
85
|
+
// like source defects and are not — the fix is a build order, not a code change.
|
|
86
|
+
// Checking the artefacts directly turns that into one actionable line.
|
|
87
|
+
const REQUIRED_LIB_DISTS = ['active-rules', 'graph-style', 'graph-trash', 'graph-write', 'ledger-core']
|
|
88
|
+
const missingDists = REQUIRED_LIB_DISTS.filter(
|
|
89
|
+
(lib) => !existsSync(resolve(UI_ROOT, '..', 'lib', lib, 'dist', 'index.js')),
|
|
90
|
+
)
|
|
91
|
+
if (missingDists.length > 0) {
|
|
92
|
+
console.error(
|
|
93
|
+
`[check-types] error lib-dist-missing libs=${missingDists.join(',')}\n` +
|
|
94
|
+
' These are build outputs, not source. Run `npm run build:lib` from platform/ first.\n' +
|
|
95
|
+
' Without them tsc reports unresolved-import errors that are a build order problem,\n' +
|
|
96
|
+
' not a type error, and this gate will not guess which it is looking at.',
|
|
97
|
+
)
|
|
98
|
+
process.exit(1)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Pre-flight 2: the compiler itself.
|
|
102
|
+
const tsc = resolve(UI_ROOT, 'node_modules', '.bin', 'tsc')
|
|
103
|
+
if (!existsSync(tsc)) {
|
|
104
|
+
console.error(
|
|
105
|
+
`[check-types] error tsc-not-found path=${tsc}\n` +
|
|
106
|
+
' Run `npm install` in platform/ui. This gate cannot check types without the compiler.',
|
|
107
|
+
)
|
|
108
|
+
process.exit(1)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const run = spawnSync(tsc, ['--noEmit'], { cwd: UI_ROOT, encoding: 'utf8' })
|
|
112
|
+
|
|
113
|
+
if (run.error) {
|
|
114
|
+
console.error(`[check-types] error tsc-spawn-failed ${run.error.message}`)
|
|
115
|
+
process.exit(1)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// tsc writes diagnostics to stdout. A per-file diagnostic is
|
|
119
|
+
// `path(line,col): error TSxxxx: msg`. A configuration or invocation failure
|
|
120
|
+
// (TS5058, TS18003, a malformed tsconfig) has no `path(line,col)` prefix, and
|
|
121
|
+
// when tsc cannot find a project at all it prints help text and emits no
|
|
122
|
+
// diagnostics whatsoever.
|
|
123
|
+
//
|
|
124
|
+
// That distinction is what stops this gate passing blind, and exit status cannot
|
|
125
|
+
// carry it: tsc exits 2 on a normal run that found type errors, and 1 when it
|
|
126
|
+
// cannot locate tsconfig.json. A gate keyed on the status code would read the
|
|
127
|
+
// catastrophe as the milder case. What separates them is whether the compiler
|
|
128
|
+
// produced any parseable diagnostic — a run that found nothing to say AND failed
|
|
129
|
+
// did not typecheck anything.
|
|
130
|
+
const DIAGNOSTIC = /^(.+?)\((\d+),(\d+)\): error TS\d+: /
|
|
131
|
+
const lines = `${run.stdout ?? ''}${run.stderr ?? ''}`.split('\n')
|
|
132
|
+
const errorLines = lines.filter((l) => DIAGNOSTIC.test(l))
|
|
133
|
+
const fatalLines = lines.filter((l) => / error TS\d+: /.test(l) && !DIAGNOSTIC.test(l))
|
|
134
|
+
|
|
135
|
+
if (fatalLines.length > 0) {
|
|
136
|
+
console.error('[check-types] error tsc-configuration-failed')
|
|
137
|
+
for (const l of fatalLines) console.error(` ${l}`)
|
|
138
|
+
console.error(
|
|
139
|
+
'\n The compiler reported an error with no source location, which means it failed before\n' +
|
|
140
|
+
' typechecking rather than while typechecking. The package has NOT been checked.',
|
|
141
|
+
)
|
|
142
|
+
process.exit(1)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (run.status !== 0 && errorLines.length === 0) {
|
|
146
|
+
console.error(
|
|
147
|
+
`[check-types] error tsc-produced-no-diagnostics status=${run.status}\n` +
|
|
148
|
+
' tsc exited non-zero and emitted no parseable diagnostic, so it did not typecheck the\n' +
|
|
149
|
+
' package — most likely tsconfig.json is missing or the invocation is wrong. The package\n' +
|
|
150
|
+
' has NOT been checked.',
|
|
151
|
+
)
|
|
152
|
+
if (run.stdout) console.error(` first output line: ${run.stdout.split('\n')[0]}`)
|
|
153
|
+
process.exit(1)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (errorLines.length > 0) {
|
|
157
|
+
console.error(`[check-types] FAIL errors=${errorLines.length} ignored=0`)
|
|
158
|
+
for (const l of errorLines) console.error(` ${l}`)
|
|
159
|
+
console.error(
|
|
160
|
+
'\n platform/ui does not typecheck. Fix the type — do not widen it, cast it away, or add\n' +
|
|
161
|
+
' an ignore entry to this gate.',
|
|
162
|
+
)
|
|
163
|
+
process.exit(1)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
console.log(`[check-types] ok errors=0 ignored=0 tsc-status=${run.status}`)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- [ ] **Step 2: Add the `typecheck` script**
|
|
170
|
+
|
|
171
|
+
In `platform/ui/package.json`, add to `scripts`, immediately after `"tokens"`:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
"typecheck": "node scripts/check-types.mjs",
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Leave `prebuild` alone. It still ends in `check-loop-contract-types.mjs` until Task 9.
|
|
178
|
+
|
|
179
|
+
- [ ] **Step 3: Restore the v6 driver so the baseline is honest**
|
|
180
|
+
|
|
181
|
+
The investigation left `platform/ui/node_modules` as a shadow tree with the v6 driver omitted, to
|
|
182
|
+
prove the downgrade clears 10 errors without installing into the parent. Task 2 is where that
|
|
183
|
+
becomes real. For this task's baseline, put it back to the plain parent symlink:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
cd maxy-code/platform/ui
|
|
187
|
+
rm -rf node_modules
|
|
188
|
+
ln -sfn /Users/neo/getmaxy/maxy-code/platform/ui/node_modules node_modules
|
|
189
|
+
node -p "require.resolve('neo4j-driver', {paths:[process.cwd()+'/app/lib']})"
|
|
190
|
+
```
|
|
191
|
+
Expected: the resolve path ends `platform/ui/node_modules/neo4j-driver/lib/index.js` — the v6 copy.
|
|
192
|
+
|
|
193
|
+
- [ ] **Step 4: Build the sibling libs, then run the gate to verify it fails**
|
|
194
|
+
|
|
195
|
+
Run:
|
|
196
|
+
```bash
|
|
197
|
+
cd maxy-code/platform && npm run build:lib
|
|
198
|
+
cd ../ui && npm run typecheck
|
|
199
|
+
```
|
|
200
|
+
Expected: exit 1, first line `[check-types] FAIL errors=80 ignored=0`.
|
|
201
|
+
|
|
202
|
+
If the count is not 80, stop — the baseline has moved and the rest of this plan's counts are wrong.
|
|
203
|
+
|
|
204
|
+
- [ ] **Step 5: Verify the dist pre-flight fires**
|
|
205
|
+
|
|
206
|
+
Run:
|
|
207
|
+
```bash
|
|
208
|
+
mv ../lib/graph-style/dist ../lib/graph-style/dist.bak && npm run typecheck; echo "exit=$?"
|
|
209
|
+
mv ../lib/graph-style/dist.bak ../lib/graph-style/dist
|
|
210
|
+
```
|
|
211
|
+
Expected: exit 1, `[check-types] error lib-dist-missing libs=graph-style`, and no tsc diagnostics printed.
|
|
212
|
+
|
|
213
|
+
- [ ] **Step 6: Commit**
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
git add maxy-code/platform/ui/scripts/check-types.mjs maxy-code/platform/ui/package.json
|
|
217
|
+
git commit -m "feat(1829): package-wide typecheck gate, not yet wired into prebuild"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### Task 2: Align `neo4j-driver` onto v5 — clears 10
|
|
223
|
+
|
|
224
|
+
`platform/ui` declares `^6.0.1`; the seventeen other packages and everything `platform/lib/*`
|
|
225
|
+
compiles against declare `^5.28.1`. `platform/ui` hands v5-typed lib functions its v6 `Session`
|
|
226
|
+
objects, which is the eight `TS2739` and two `TS2345`.
|
|
227
|
+
|
|
228
|
+
**Files:**
|
|
229
|
+
- Modify: `platform/ui/package.json:39`
|
|
230
|
+
|
|
231
|
+
**Interfaces:**
|
|
232
|
+
- Produces: `platform/ui` resolving `neo4j-driver` to the same 5.28.3 copy at
|
|
233
|
+
`platform/node_modules` that `platform/lib/*` compiles against.
|
|
234
|
+
|
|
235
|
+
- [ ] **Step 1: Change the declared version**
|
|
236
|
+
|
|
237
|
+
In `platform/ui/package.json`, change:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
"neo4j-driver": "^6.0.1",
|
|
241
|
+
```
|
|
242
|
+
to:
|
|
243
|
+
```json
|
|
244
|
+
"neo4j-driver": "^5.28.1",
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
- [ ] **Step 2: Make the installed tree match the declaration**
|
|
248
|
+
|
|
249
|
+
`npm install` here would write into the parent checkout, because `platform/ui/node_modules` is a
|
|
250
|
+
symlink to it. Build a shadow instead: a real directory of per-entry symlinks into the parent, with
|
|
251
|
+
the three v6 driver packages omitted so resolution walks up to `platform/node_modules` and finds
|
|
252
|
+
5.28.3. This is worktree-local and leaves the parent untouched.
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
cd maxy-code/platform/ui
|
|
256
|
+
P=/Users/neo/getmaxy/maxy-code
|
|
257
|
+
rm node_modules && mkdir node_modules
|
|
258
|
+
for e in "$P/platform/ui/node_modules"/*; do
|
|
259
|
+
b=$(basename "$e")
|
|
260
|
+
case "$b" in neo4j-driver|neo4j-driver-core|neo4j-driver-bolt-connection) continue;; esac
|
|
261
|
+
ln -s "$e" "node_modules/$b"
|
|
262
|
+
done
|
|
263
|
+
for e in "$P/platform/ui/node_modules"/.[!.]*; do
|
|
264
|
+
ln -s "$e" "node_modules/$(basename "$e")" 2>/dev/null || true
|
|
265
|
+
done
|
|
266
|
+
node -p "require.resolve('neo4j-driver', {paths:[process.cwd()+'/app/lib']})"
|
|
267
|
+
```
|
|
268
|
+
Expected: the resolve path ends `platform/node_modules/neo4j-driver/lib/index.js`.
|
|
269
|
+
|
|
270
|
+
This shadow is a worktree artefact, not a deliverable. On a real checkout the equivalent is
|
|
271
|
+
`npm install` honouring the changed `package.json`. Say so in the debrief — the landed change is one
|
|
272
|
+
line of `package.json`, and whoever installs next gets v5 from npm.
|
|
273
|
+
|
|
274
|
+
- [ ] **Step 3: Run the gate**
|
|
275
|
+
|
|
276
|
+
Run: `npm run typecheck`
|
|
277
|
+
Expected: exit 1, `[check-types] FAIL errors=70 ignored=0`. Confirm no `TS2739` or `TS2345`
|
|
278
|
+
mentioning `neo4j-driver-core` remains.
|
|
279
|
+
|
|
280
|
+
- [ ] **Step 4: Verify against a running Neo4j, not just the compiler**
|
|
281
|
+
|
|
282
|
+
A dependency change that only ever passed a typecheck has not been shown to work. Exercise the
|
|
283
|
+
driver against the live database:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
cd maxy-code/platform/ui
|
|
287
|
+
npx vitest run app/lib/__tests__/graph-write-gate.test.ts app/lib/__tests__/graph-health-audits.test.ts
|
|
288
|
+
```
|
|
289
|
+
Expected: all pass.
|
|
290
|
+
|
|
291
|
+
Then drive a real query through the v5 driver using the same API surface `platform/ui` uses
|
|
292
|
+
(`neo4j.driver`, `neo4j.auth`, `neo4j.int`, `session.run`):
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
node --input-type=module -e "
|
|
296
|
+
import neo4j from 'neo4j-driver'
|
|
297
|
+
const uri = process.env.NEO4J_URI ?? 'bolt://127.0.0.1:7687'
|
|
298
|
+
const d = neo4j.driver(uri, neo4j.auth.basic(process.env.NEO4J_USER ?? 'neo4j', process.env.NEO4J_PASSWORD))
|
|
299
|
+
const s = d.session()
|
|
300
|
+
const r = await s.run('RETURN \$n AS n', { n: neo4j.int(42) })
|
|
301
|
+
console.log('driver', neo4j.driver.name ? 'ok' : 'ok', 'value=', r.records[0].get('n').toString())
|
|
302
|
+
await s.close(); await d.close()
|
|
303
|
+
"
|
|
304
|
+
```
|
|
305
|
+
Expected: `value= 42`. If the local Neo4j is not running or credentials are absent, say so
|
|
306
|
+
explicitly in the debrief rather than recording this step as passed.
|
|
307
|
+
|
|
308
|
+
- [ ] **Step 5: Commit**
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
git add maxy-code/platform/ui/package.json
|
|
312
|
+
git commit -m "fix(1829): align platform/ui onto neo4j-driver v5, matching the libs it calls"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### Task 3: Production type-truth fixes — clears 8
|
|
318
|
+
|
|
319
|
+
Three of these are defects the compiler found, not annotations. Read each before changing it.
|
|
320
|
+
|
|
321
|
+
**Files:**
|
|
322
|
+
- Modify: `platform/ui/app/components/ChannelIcon.tsx:8,14`
|
|
323
|
+
- Modify: `platform/ui/app/Sidebar.tsx:1499`
|
|
324
|
+
- Modify: `platform/ui/app/lib/webchat/gateway/webchat-gateway.ts:83`
|
|
325
|
+
- Modify: `platform/ui/server/routes/admin/sidebar-sessions.ts:283`
|
|
326
|
+
- Modify: `platform/ui/server/routes/admin/sessions.ts:638,667,702`
|
|
327
|
+
- Modify: `platform/ui/server/routes/whatsapp-reader.ts:1144`
|
|
328
|
+
|
|
329
|
+
- [ ] **Step 1: Fix the `ChannelIcon` crash**
|
|
330
|
+
|
|
331
|
+
`GLYPHS` is `Record<ReaderChannel, …>` but holds two of the three channels. `ReaderChannel` is
|
|
332
|
+
`'whatsapp' | 'telegram' | 'webchat'`. A webchat row at `Sidebar.tsx:1499` makes `GLYPHS['webchat']`
|
|
333
|
+
undefined and `g.fill` throw.
|
|
334
|
+
|
|
335
|
+
Do not invent a webchat brand path. `ChannelIcon` renders brand glyphs by design, which is why
|
|
336
|
+
`BRAND_CHANNELS` in the same file maps only two. Narrow its type instead.
|
|
337
|
+
|
|
338
|
+
In `app/components/ChannelIcon.tsx`, add the brand-channel type above `GLYPHS` and use it:
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
// ChannelIcon renders inlined brand marks, and only WhatsApp and Telegram have
|
|
342
|
+
// one. Webchat and any future channel are the SessionChannelBadge's job — it
|
|
343
|
+
// routes webchat to a globe and unknown tokens to a neutral bubble. Typing
|
|
344
|
+
// GLYPHS as Record<ReaderChannel, …> claimed a webchat glyph existed; it did
|
|
345
|
+
// not, and a webchat row reaching here threw on `g.fill`.
|
|
346
|
+
type BrandChannel = Extract<ReaderChannel, 'whatsapp' | 'telegram'>
|
|
347
|
+
|
|
348
|
+
const GLYPHS: Record<BrandChannel, { fill: string; path: string; label: string }> = {
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
and change the component's prop type:
|
|
352
|
+
|
|
353
|
+
```tsx
|
|
354
|
+
export function ChannelIcon({ channel, size = 16 }: { channel: BrandChannel; size?: number }) {
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
and the badge's lookup map, which was already brand-only in fact:
|
|
358
|
+
|
|
359
|
+
```tsx
|
|
360
|
+
const BRAND_CHANNELS: Record<string, BrandChannel> = { whatsapp: 'whatsapp', telegram: 'telegram' }
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
- [ ] **Step 2: Route the conversation row through the badge**
|
|
364
|
+
|
|
365
|
+
`Sidebar.tsx:1499` passes `c.channel`, typed `ReaderChannel`, which now no longer fits.
|
|
366
|
+
`SessionChannelBadge` is the component built for the all-three case and delegates brand channels to
|
|
367
|
+
`ChannelIcon` at the same size, so whatsapp and telegram render unchanged.
|
|
368
|
+
|
|
369
|
+
In `app/Sidebar.tsx:1499`, change:
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
<ChannelIcon channel={c.channel} size={14} />
|
|
373
|
+
```
|
|
374
|
+
to:
|
|
375
|
+
```tsx
|
|
376
|
+
<SessionChannelBadge channel={c.channel} size={14} />
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
`SessionChannelBadge` is already imported on line 6. Leave line 1031 alone — it maps over
|
|
380
|
+
`READER_CHANNELS`, which is whatsapp+telegram, and that call site is correct.
|
|
381
|
+
|
|
382
|
+
- [ ] **Step 3: Widen `dispatchFor` to match the reviewer it calls**
|
|
383
|
+
|
|
384
|
+
The shared type at `app/lib/channel-pty-bridge/public-session-end-review.ts:41` is
|
|
385
|
+
`'eviction' | 'exit'`. The local callback type narrowed it to `'eviction'`, so the documented
|
|
386
|
+
public-exit path at line 422 could not be expressed. The type is the bug; the value is correct.
|
|
387
|
+
|
|
388
|
+
In `app/lib/webchat/gateway/webchat-gateway.ts:83`, change:
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
dispatchFor: 'eviction'
|
|
392
|
+
```
|
|
393
|
+
to:
|
|
394
|
+
```ts
|
|
395
|
+
dispatchFor: 'eviction' | 'exit'
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
- [ ] **Step 4: Fix the `port` type**
|
|
399
|
+
|
|
400
|
+
`requirePortEnv` returns a number; the local was declared `string`. It is only interpolated into a
|
|
401
|
+
URL, so runtime is unaffected, but the declaration is a lie.
|
|
402
|
+
|
|
403
|
+
In `server/routes/admin/sidebar-sessions.ts`, change `let port: string` to:
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
let port: number
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
- [ ] **Step 5: Annotate the five implicit-`any` parameters**
|
|
410
|
+
|
|
411
|
+
These are callback params on arrays whose element type the compiler can already see; they only
|
|
412
|
+
needed writing down. Read each line and give the parameter the element type in scope — do not
|
|
413
|
+
reach for `any`.
|
|
414
|
+
|
|
415
|
+
- `server/routes/admin/sessions.ts:638` — params `c` and `i`
|
|
416
|
+
- `server/routes/admin/sessions.ts:667` — param `c`
|
|
417
|
+
- `server/routes/admin/sessions.ts:702` — param `c`
|
|
418
|
+
- `server/routes/whatsapp-reader.ts:1144` — param `r`
|
|
419
|
+
|
|
420
|
+
- [ ] **Step 6: Run the gate**
|
|
421
|
+
|
|
422
|
+
Run: `npm run typecheck`
|
|
423
|
+
Expected: exit 1, `[check-types] FAIL errors=62 ignored=0`, and no remaining diagnostic in a file
|
|
424
|
+
outside `__tests__`. Every error left in the package is now in a test file.
|
|
425
|
+
|
|
426
|
+
- [ ] **Step 7: Prove the ChannelIcon fix with a test**
|
|
427
|
+
|
|
428
|
+
Add to `app/components/__tests__/ChannelIcon.test.tsx`:
|
|
429
|
+
|
|
430
|
+
```tsx
|
|
431
|
+
it('renders a webchat row through the badge without throwing', () => {
|
|
432
|
+
const { container } = render(<SessionChannelBadge channel="webchat" size={14} />)
|
|
433
|
+
expect(container.querySelector('.channel-icon')).not.toBeNull()
|
|
434
|
+
})
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Import `SessionChannelBadge` alongside `ChannelIcon` on line 4.
|
|
438
|
+
|
|
439
|
+
Run: `npx vitest run app/components/__tests__/ChannelIcon.test.tsx`
|
|
440
|
+
Expected: PASS.
|
|
441
|
+
|
|
442
|
+
- [ ] **Step 8: Commit**
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
git add maxy-code/platform/ui/app maxy-code/platform/ui/server
|
|
446
|
+
git commit -m "fix(1829): production type defects — ChannelIcon webchat crash, dispatchFor, port type"
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
### Task 4: Contract drift the tests exposed — clears 3
|
|
452
|
+
|
|
453
|
+
In both of these the test is right about the wire and the type is wrong. Fix the type.
|
|
454
|
+
|
|
455
|
+
**Files:**
|
|
456
|
+
- Modify: `platform/ui/app/Sidebar.tsx:49-60`
|
|
457
|
+
- Modify: `platform/ui/server/routes/channel/__tests__/schedule-inject.test.ts:180,186`
|
|
458
|
+
|
|
459
|
+
- [ ] **Step 1: Add the fields the 503 refusal actually sends**
|
|
460
|
+
|
|
461
|
+
`server/routes/admin/claude-sessions.ts:115` returns
|
|
462
|
+
`{ error: 'claude-auth-dead', auth_status: auth.status, expiresAt: auth.expiresAt ?? null }`.
|
|
463
|
+
`RcSpawnResponseBody` declares neither `auth_status` nor `expiresAt`, so
|
|
464
|
+
`resolveRcSpawnOutcome.test.ts:69` — which passes the real body — does not typecheck.
|
|
465
|
+
|
|
466
|
+
In `app/Sidebar.tsx`, add to `RcSpawnResponseBody` before the closing brace:
|
|
467
|
+
|
|
468
|
+
```ts
|
|
469
|
+
/** Task 1407 — the 503 claude-auth-dead refusal (refuseIfClaudeAuthDead,
|
|
470
|
+
* server/routes/admin/claude-sessions.ts) carries the token's health and
|
|
471
|
+
* expiry alongside `error`. Both were on the wire and absent from this type,
|
|
472
|
+
* so a caller reading them had no compiler help. */
|
|
473
|
+
auth_status?: string
|
|
474
|
+
expiresAt?: string | null
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
- [ ] **Step 2: Make the no-seat assertions non-vacuous**
|
|
478
|
+
|
|
479
|
+
`schedule-inject.test.ts:180,186` assert `.scheduledSessionId` is undefined on the inbound. No
|
|
480
|
+
inbound type declares that property and no source file mentions it, so the assertion is true by
|
|
481
|
+
construction and would stay true if the route started threading a seat under any other name. It
|
|
482
|
+
tests nothing.
|
|
483
|
+
|
|
484
|
+
The intent (Task 1746: no per-firing seat is threaded) is worth keeping. Express it against the
|
|
485
|
+
object so it stays meaningful if the field is ever added.
|
|
486
|
+
|
|
487
|
+
Change line 180 to:
|
|
488
|
+
|
|
489
|
+
```ts
|
|
490
|
+
expect('scheduledSessionId' in (waHandleInbound.mock.calls[0][0] as object)).toBe(false)
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
and line 186 to:
|
|
494
|
+
|
|
495
|
+
```ts
|
|
496
|
+
expect('scheduledSessionId' in (tgHandleInbound.mock.calls[0][0] as object)).toBe(false)
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
- [ ] **Step 3: Run the gate and the touched tests**
|
|
500
|
+
|
|
501
|
+
Run:
|
|
502
|
+
```bash
|
|
503
|
+
npm run typecheck
|
|
504
|
+
npx vitest run app/__tests__/resolveRcSpawnOutcome.test.ts server/routes/channel/__tests__/schedule-inject.test.ts
|
|
505
|
+
```
|
|
506
|
+
Expected: gate reports `errors=59`; both test files pass.
|
|
507
|
+
|
|
508
|
+
- [ ] **Step 4: Commit**
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
git add maxy-code/platform/ui/app/Sidebar.tsx maxy-code/platform/ui/server/routes/channel/__tests__/schedule-inject.test.ts
|
|
512
|
+
git commit -m "fix(1829): type the auth-refusal wire fields, de-vacuum the no-seat assertions"
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
### Task 5: Type the mock implementations — clears 39
|
|
518
|
+
|
|
519
|
+
One root cause produces most of the remaining errors: `vi.fn()` given an implementation that
|
|
520
|
+
declares no parameters. The mock's type becomes `Mock<() => R>`, so `.mock.calls[0]` is the empty
|
|
521
|
+
tuple `[]` (`TS2493` on any index, `TS2339` on any property of the resulting `never`), and any
|
|
522
|
+
callback over `.mock.calls` gets an implicit-`any` parameter (`TS7006`). Casting the resulting
|
|
523
|
+
`undefined` is `TS2352`.
|
|
524
|
+
|
|
525
|
+
The fix is the same everywhere: declare the parameters the caller actually passes. That is
|
|
526
|
+
truthful — the production call site already passes them — and it makes every downstream index and
|
|
527
|
+
callback infer correctly.
|
|
528
|
+
|
|
529
|
+
**Files:**
|
|
530
|
+
- Modify: `app/components/__tests__/SessionReseatControl.test.tsx` (5)
|
|
531
|
+
- Modify: `app/lib/__tests__/graph-write-gate.test.ts` (8)
|
|
532
|
+
- Modify: `app/components/__tests__/UsageModal.test.tsx` (2)
|
|
533
|
+
- Modify: `app/tasks/__tests__/tasks-page.test.tsx` (4)
|
|
534
|
+
- Modify: `app/whatsapp/__tests__/ReplyComposer.test.tsx` (2)
|
|
535
|
+
- Modify: `app/__tests__/AdminShell-operator-conversations.test.tsx` (2)
|
|
536
|
+
- Modify: `app/lib/__tests__/adminuser-self-heal.test.ts` (4)
|
|
537
|
+
- Modify: `app/lib/__tests__/graph-health-audits.test.ts` (3)
|
|
538
|
+
- Modify: `app/lib/whatsapp/__tests__/baileys-debug-window.test.ts` (3)
|
|
539
|
+
- Modify: `server/routes/admin/__tests__/browser-launch.test.ts` (6)
|
|
540
|
+
|
|
541
|
+
- [ ] **Step 1: Type the fetch-shaped mocks**
|
|
542
|
+
|
|
543
|
+
Wherever a mock stands in for `adminFetch` or `fetch` and the test later reads `mock.calls[0][1]`,
|
|
544
|
+
declare both parameters. In `app/components/__tests__/SessionReseatControl.test.tsx:30`, change:
|
|
545
|
+
|
|
546
|
+
```tsx
|
|
547
|
+
const adminFetch = vi.fn(async () => new Response(JSON.stringify({ target: '/chat?session=new' }), { status: 200 }))
|
|
548
|
+
```
|
|
549
|
+
to:
|
|
550
|
+
```tsx
|
|
551
|
+
const adminFetch = vi.fn(async (_url: string, _init?: RequestInit) =>
|
|
552
|
+
new Response(JSON.stringify({ target: '/chat?session=new' }), { status: 200 }))
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
This clears the three `TS2493` and two `TS2339` in that file, and the `init!` non-null assertion on
|
|
556
|
+
line 45 becomes correct rather than accidental. Apply the same shape to the identical mocks in
|
|
557
|
+
`UsageModal.test.tsx`, `tasks-page.test.tsx` and `ReplyComposer.test.tsx`, matching each call site's
|
|
558
|
+
real argument list — `tasks-page` and `ReplyComposer` currently infer `[url: string]`, so they need
|
|
559
|
+
the second parameter added.
|
|
560
|
+
|
|
561
|
+
- [ ] **Step 2: Type the console-spy mocks**
|
|
562
|
+
|
|
563
|
+
Wherever a test reads `logSpy.mock.calls.map((c) => String(c[0]))`, the spy's parameters are
|
|
564
|
+
unstated. Declare them so `c` infers. In `app/lib/__tests__/graph-write-gate.test.ts`, the spy
|
|
565
|
+
should be created as:
|
|
566
|
+
|
|
567
|
+
```ts
|
|
568
|
+
const logSpy = vi.spyOn(console, 'error').mockImplementation((..._args: unknown[]) => {})
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
The six `TS7006` in that file then resolve without touching the assertions. Apply the same to
|
|
572
|
+
`graph-health-audits.test.ts`, `baileys-debug-window.test.ts`, `browser-launch.test.ts`,
|
|
573
|
+
`adminuser-self-heal.test.ts` and `AdminShell-operator-conversations.test.tsx`.
|
|
574
|
+
|
|
575
|
+
- [ ] **Step 3: Type the Neo4j session mock**
|
|
576
|
+
|
|
577
|
+
`graph-write-gate.test.ts:201` destructures `session.run.mock.calls[0]`. Give `makeSession`'s `run`
|
|
578
|
+
its real parameters:
|
|
579
|
+
|
|
580
|
+
```ts
|
|
581
|
+
run: vi.fn(async (_cypher: string, _params?: Record<string, unknown>) => ({ records: [] as unknown[] })),
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
- [ ] **Step 4: Run the gate**
|
|
585
|
+
|
|
586
|
+
Run: `npm run typecheck`
|
|
587
|
+
Expected: exit 1, `[check-types] FAIL errors=20 ignored=0`.
|
|
588
|
+
|
|
589
|
+
- [ ] **Step 5: Run every touched test file**
|
|
590
|
+
|
|
591
|
+
Run:
|
|
592
|
+
```bash
|
|
593
|
+
npx vitest run app/components/__tests__/SessionReseatControl.test.tsx app/lib/__tests__/graph-write-gate.test.ts \
|
|
594
|
+
app/components/__tests__/UsageModal.test.tsx app/tasks/__tests__/tasks-page.test.tsx \
|
|
595
|
+
app/whatsapp/__tests__/ReplyComposer.test.tsx app/__tests__/AdminShell-operator-conversations.test.tsx \
|
|
596
|
+
app/lib/__tests__/adminuser-self-heal.test.ts app/lib/__tests__/graph-health-audits.test.ts \
|
|
597
|
+
app/lib/whatsapp/__tests__/baileys-debug-window.test.ts server/routes/admin/__tests__/browser-launch.test.ts
|
|
598
|
+
```
|
|
599
|
+
Expected: all pass. A mock that now declares parameters must still receive the same arguments — if
|
|
600
|
+
an assertion breaks, the mock's declared shape is wrong, not the assertion.
|
|
601
|
+
|
|
602
|
+
- [ ] **Step 6: Commit**
|
|
603
|
+
|
|
604
|
+
```bash
|
|
605
|
+
git add maxy-code/platform/ui/app maxy-code/platform/ui/server
|
|
606
|
+
git commit -m "test(1829): declare mock parameters so call-tuple reads typecheck"
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
---
|
|
610
|
+
|
|
611
|
+
### Task 6: Stale fixtures and handler types — clears 20
|
|
612
|
+
|
|
613
|
+
These are not one root cause. Each is a fixture or handler that drifted from the type it stands in
|
|
614
|
+
for.
|
|
615
|
+
|
|
616
|
+
**Files:**
|
|
617
|
+
- Modify: `app/components/__tests__/session-list-lite.test.tsx` (8)
|
|
618
|
+
- Modify: `app/lib/channel-pty-bridge/__tests__/follower.test.ts` (8)
|
|
619
|
+
- Modify: `app/lib/whatsapp/gateway/__tests__/wa-gateway-source.test.ts` (3)
|
|
620
|
+
- Modify: `app/lib/__tests__/power-health.test.ts` (1)
|
|
621
|
+
|
|
622
|
+
- [ ] **Step 1: Add the two props the session-list fixture lost**
|
|
623
|
+
|
|
624
|
+
All eight `TS2739` are the same fixture missing `newPermMode` and `setNewPermMode`, which the
|
|
625
|
+
component gained and the fixture never followed. Find the shared props object in
|
|
626
|
+
`session-list-lite.test.tsx` and add both, matching the types the component declares. If the
|
|
627
|
+
fixture is repeated inline at each of lines 28, 35, 43, 50, 67, 73, 80 and 86, hoist it to one
|
|
628
|
+
`const baseProps` first and spread it — eight copies of one fixture is why this drifted.
|
|
629
|
+
|
|
630
|
+
- [ ] **Step 2: Fix the follower handler types**
|
|
631
|
+
|
|
632
|
+
Six `TS2322` at lines 216, 254, 273 and 299 are `Type 'number' is not assignable to type
|
|
633
|
+
'void | Promise<void>'` — a handler written as a concise arrow returning a number
|
|
634
|
+
(`() => someCounter++`). Wrap the body in braces so it returns void.
|
|
635
|
+
|
|
636
|
+
The four at lines 218, 256, 301 and 354 are `RecordingHandler` not assignable to
|
|
637
|
+
`FileDeliveryHandler`. Read both types before changing anything: if `RecordingHandler` is the
|
|
638
|
+
test's own recording double, give it the `FileDeliveryHandler` signature rather than casting it.
|
|
639
|
+
|
|
640
|
+
- [ ] **Step 3: Fix the wa-gateway-source mock**
|
|
641
|
+
|
|
642
|
+
Lines 53 and 54 cast `EnsureChannelSessionInput` to `Record<string, unknown>`, which the compiler
|
|
643
|
+
rejects as non-overlapping. Line 98 assigns a `Mock<(i: Record<string, unknown>) => Promise<void>>`
|
|
644
|
+
where an `EnsureTelegramSession…` signature is required. Type the mock with the real input type
|
|
645
|
+
instead of `Record<string, unknown>`, which removes all three.
|
|
646
|
+
|
|
647
|
+
- [ ] **Step 4: Fix the power-health runner fixture**
|
|
648
|
+
|
|
649
|
+
Line 118 adds a `status` key to an object literal typed
|
|
650
|
+
`{ runner: (c: string, a: string[]) => string | null }`. Read what the test intends: if `status` is
|
|
651
|
+
genuinely part of the fixture's contract, add it to the type; if it is a leftover, remove it.
|
|
652
|
+
|
|
653
|
+
- [ ] **Step 5: Run the gate**
|
|
654
|
+
|
|
655
|
+
Run: `npm run typecheck`
|
|
656
|
+
Expected: exit 0, `[check-types] ok errors=0 ignored=0 tsc-status=0`.
|
|
657
|
+
|
|
658
|
+
This is the first green run. If it is not zero, the remaining diagnostics are listed by the gate —
|
|
659
|
+
do not proceed to Task 7 until it is.
|
|
660
|
+
|
|
661
|
+
- [ ] **Step 6: Run every touched test file**
|
|
662
|
+
|
|
663
|
+
Run:
|
|
664
|
+
```bash
|
|
665
|
+
npx vitest run app/components/__tests__/session-list-lite.test.tsx \
|
|
666
|
+
app/lib/channel-pty-bridge/__tests__/follower.test.ts \
|
|
667
|
+
app/lib/whatsapp/gateway/__tests__/wa-gateway-source.test.ts app/lib/__tests__/power-health.test.ts
|
|
668
|
+
```
|
|
669
|
+
Expected: all pass.
|
|
670
|
+
|
|
671
|
+
- [ ] **Step 7: Commit**
|
|
672
|
+
|
|
673
|
+
```bash
|
|
674
|
+
git add maxy-code/platform/ui/app
|
|
675
|
+
git commit -m "test(1829): refresh stale fixtures and handler signatures"
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
### Task 7: Prove the gate catches a real error — the mutation check
|
|
681
|
+
|
|
682
|
+
A gate that has only ever been seen passing has not been shown to work. The load-bearing case is an
|
|
683
|
+
error in a file the narrow 1825 gate never covered.
|
|
684
|
+
|
|
685
|
+
- [ ] **Step 1: Introduce a deliberate error outside the old gate's six files**
|
|
686
|
+
|
|
687
|
+
`app/lib/file-index.ts` is not in `CONTRACT_FILES`. Add an implicit-`any` parameter to it — pick any
|
|
688
|
+
callback and strip its annotation, or append:
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
export function __gateProbe(rows) {
|
|
692
|
+
return rows.length
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
- [ ] **Step 2: Observe the gate fail on it**
|
|
697
|
+
|
|
698
|
+
Run: `npm run typecheck; echo "exit=$?"`
|
|
699
|
+
Expected: exit 1, `[check-types] FAIL errors=1 ignored=0`, and the listed diagnostic names
|
|
700
|
+
`app/lib/file-index.ts` with `TS7006`.
|
|
701
|
+
|
|
702
|
+
- [ ] **Step 3: Confirm the OLD gate would have missed it**
|
|
703
|
+
|
|
704
|
+
Run: `node scripts/check-loop-contract-types.mjs; echo "exit=$?"`
|
|
705
|
+
Expected: exit 0, `[loop-contract] ok … package-errors-ignored=1`. This is the whole reason the task
|
|
706
|
+
exists — record the output in the debrief.
|
|
707
|
+
|
|
708
|
+
- [ ] **Step 4: Remove the error and observe the gate pass**
|
|
709
|
+
|
|
710
|
+
Delete the probe, then run: `npm run typecheck; echo "exit=$?"`
|
|
711
|
+
Expected: exit 0, `[check-types] ok errors=0 ignored=0`.
|
|
712
|
+
|
|
713
|
+
- [ ] **Step 5: Confirm the gate does not pass blind**
|
|
714
|
+
|
|
715
|
+
Point it at a tree where tsc cannot run:
|
|
716
|
+
|
|
717
|
+
```bash
|
|
718
|
+
mv tsconfig.json tsconfig.json.bak && npm run typecheck; echo "exit=$?"
|
|
719
|
+
mv tsconfig.json.bak tsconfig.json
|
|
720
|
+
```
|
|
721
|
+
Expected: exit 1, and the message is `tsc-configuration-failed` or `tsc-produced-no-diagnostics` —
|
|
722
|
+
not `ok`. Record which branch fired.
|
|
723
|
+
|
|
724
|
+
- [ ] **Step 6: Commit nothing**
|
|
725
|
+
|
|
726
|
+
This task changes no tracked file. Confirm with `git status --porcelain` that the tree is clean
|
|
727
|
+
before moving on. If the probe or the tsconfig rename is still on disk, undo it now.
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
### Task 8: Retire the narrow gate and wire the wide one
|
|
732
|
+
|
|
733
|
+
**Files:**
|
|
734
|
+
- Delete: `platform/ui/scripts/check-loop-contract-types.mjs`
|
|
735
|
+
- Modify: `platform/ui/package.json` (`prebuild`)
|
|
736
|
+
|
|
737
|
+
- [ ] **Step 1: Swap the prebuild gate**
|
|
738
|
+
|
|
739
|
+
In `platform/ui/package.json`, in the `prebuild` chain, change the final entry from:
|
|
740
|
+
|
|
741
|
+
```
|
|
742
|
+
&& node scripts/check-loop-contract-types.mjs
|
|
743
|
+
```
|
|
744
|
+
to:
|
|
745
|
+
```
|
|
746
|
+
&& node scripts/check-types.mjs
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
- [ ] **Step 2: Delete the narrow gate**
|
|
750
|
+
|
|
751
|
+
```bash
|
|
752
|
+
git rm maxy-code/platform/ui/scripts/check-loop-contract-types.mjs
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
The loop-row contract is not lost. `check-types.mjs` compiles all six of its `CONTRACT_FILES` along
|
|
756
|
+
with the rest of the package, so every invariant 1825 asserted is still a build failure — now
|
|
757
|
+
without a second gate that could drift from the first.
|
|
758
|
+
|
|
759
|
+
- [ ] **Step 3: Verify no reference to the deleted gate survives**
|
|
760
|
+
|
|
761
|
+
Run: `/usr/bin/grep -rn "check-loop-contract-types" maxy-code/ --exclude-dir=node_modules`
|
|
762
|
+
Expected: hits only in `.tasks/` and `platform/docs/superpowers/` prose. Zero hits in
|
|
763
|
+
`package.json` or any script.
|
|
764
|
+
|
|
765
|
+
- [ ] **Step 4: Run the full build**
|
|
766
|
+
|
|
767
|
+
Run: `cd maxy-code/platform/ui && npm run build`
|
|
768
|
+
Expected: all nineteen prebuild gates pass, `[check-types] ok errors=0 ignored=0` among them, then
|
|
769
|
+
vite and tsup complete and `postbuild` passes.
|
|
770
|
+
|
|
771
|
+
- [ ] **Step 5: Commit**
|
|
772
|
+
|
|
773
|
+
```bash
|
|
774
|
+
git add maxy-code/platform/ui/package.json
|
|
775
|
+
git commit -m "feat(1829): wire the package-wide gate into prebuild, retire the narrow one"
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
---
|
|
779
|
+
|
|
780
|
+
### Task 9: Run the package's own test suite
|
|
781
|
+
|
|
782
|
+
The plan changed twenty test files and one dependency major version. The gate proves types; only the
|
|
783
|
+
suite proves behaviour.
|
|
784
|
+
|
|
785
|
+
- [ ] **Step 1: Run the full suite**
|
|
786
|
+
|
|
787
|
+
Run: `cd maxy-code/platform/ui && npx vitest run`
|
|
788
|
+
Expected: exit 0.
|
|
789
|
+
|
|
790
|
+
Do not dismiss a failure here as a worktree artefact. As of 2026-07 the worktree suite is
|
|
791
|
+
trustworthy — verify any failure against the parent checkout on `main` before calling it
|
|
792
|
+
environmental, and if it is real, fix it before landing.
|
|
793
|
+
|
|
794
|
+
- [ ] **Step 2: Record the count**
|
|
795
|
+
|
|
796
|
+
Note the file and test totals for the debrief.
|
|
797
|
+
|
|
798
|
+
---
|
|
799
|
+
|
|
800
|
+
### Task 10: File the follow-up for the rest of the platform
|
|
801
|
+
|
|
802
|
+
`platform/lib/*` and `platform/plugins/*` still typecheck nowhere. The task scopes them out, and a
|
|
803
|
+
prose deferral becomes a silent regression.
|
|
804
|
+
|
|
805
|
+
- [ ] **Step 1: Mint a task number**
|
|
806
|
+
|
|
807
|
+
Scan the worktrees, not just `main` — parallel sprints take numbers concurrently:
|
|
808
|
+
|
|
809
|
+
```bash
|
|
810
|
+
ls /Users/neo/getmaxy/maxy-code/.tasks/*/ /Users/neo/getmaxy/maxy-code/.claude/worktrees/*/maxy-code/.tasks/*/ 2>/dev/null \
|
|
811
|
+
| /usr/bin/grep -oE '^1[89][0-9]{2}' | sort -n | tail -3
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
- [ ] **Step 2: Write the task file**
|
|
815
|
+
|
|
816
|
+
Create `maxy-code/.tasks/backlog/<NNNN>-<slug>.md` describing: the other platform packages run no
|
|
817
|
+
typechecker; `platform/ui` now has `scripts/check-types.mjs` as the working shape to copy; each
|
|
818
|
+
package has its own error population that needs the same triage-then-gate treatment; and that the
|
|
819
|
+
`neo4j-driver` v5/v6 split is now uniform at v5 so a future v6 move is a single coordinated bump.
|
|
820
|
+
Task files nest to `##`, never `###`.
|
|
821
|
+
|
|
822
|
+
- [ ] **Step 3: Add a Ready row to LANES**
|
|
823
|
+
|
|
824
|
+
Edit `/Users/neo/getmaxy/maxy-code/.tasks/LANES.md` — use the absolute path, since a bare
|
|
825
|
+
`.tasks/LANES.md` from the worktree root resolves to the legacy parent tracker.
|
|
826
|
+
|
|
827
|
+
- [ ] **Step 4: Commit**
|
|
828
|
+
|
|
829
|
+
Fold this into the Task 1829 archive commit in the sprint's land phase rather than committing it
|
|
830
|
+
alone.
|