@runfusion/fusion 0.73.0-beta.3 → 0.73.0-beta.4
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/dist/bin.js +994 -292
- package/dist/child-process-worker.js +632 -153
- package/dist/client/.vite/manifest.json +256 -256
- package/dist/client/assets/{AgentDetailView-lJqxsPOR.js → AgentDetailView-BBOL6AgZ.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-De4wK_UT.js → AgentPermissionPolicyEditor-DV7OPUhR.js} +1 -1
- package/dist/client/assets/{AgentsView-CwizRdcA.js → AgentsView-B6xoAHyV.js} +3 -3
- package/dist/client/assets/{ChatView-BeQXaz7_.js → ChatView-DwVjnxM8.js} +1 -1
- package/dist/client/assets/{CommandCenter-BJZCaPLj.js → CommandCenter-DYWaoYFD.js} +1 -1
- package/dist/client/assets/{DevServerView-DQgwQXKx.js → DevServerView-BY5up-NA.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-B2UVwp6F.js → DirectoryPicker-fM8MJa2r.js} +1 -1
- package/dist/client/assets/{DocumentsView-DOeYrhvg.js → DocumentsView-D2KxsPG_.js} +1 -1
- package/dist/client/assets/{EvalsView-LwepJ9Ud.js → EvalsView-U8dOvTRM.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-DVNSzflw.js → ExperimentalAgentOnboardingModal-C27y8Y-1.js} +1 -1
- package/dist/client/assets/{GoalsView-__LpXw4S.js → GoalsView-D-2wmy-O.js} +1 -1
- package/dist/client/assets/{InsightsView-Dv388uaO.js → InsightsView-zLyuQL_l.js} +1 -1
- package/dist/client/assets/{MemoryView-ChCbEfZT.js → MemoryView-D-tSn48u.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-DehAjrqN.js → PiExtensionsManager-DvwmvGEY.js} +1 -1
- package/dist/client/assets/PluginManager-BACOwQAN.js +1 -0
- package/dist/client/assets/{PullRequestView-BvmajsBq.js → PullRequestView-DULyv21u.js} +1 -1
- package/dist/client/assets/{ReportModal-DM9B_h_w.js → ReportModal-CUlKMFWa.js} +1 -1
- package/dist/client/assets/{ResearchView-BzXSgUhp.js → ResearchView-DM_O3IFc.js} +1 -1
- package/dist/client/assets/{SecretsView-COBqEdJj.js → SecretsView-Bq3u_nAf.js} +1 -1
- package/dist/client/assets/{SessionTerminal-BUw_FTlh.js → SessionTerminal-D00ByR6U.js} +1 -1
- package/dist/client/assets/SettingsModal-Bb3pIxiX.js +21 -0
- package/dist/client/assets/SettingsModal-CMLHZBhX.css +1 -0
- package/dist/client/assets/{SettingsModal-CsLaIrqt.js → SettingsModal-QRaBE1ds.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-Bv3aZ9aU.js → SettingsTextareaRow-CHOJ-qHz.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-C-yMHTlW.js → SetupWizardModal-DriQyd81.js} +2 -2
- package/dist/client/assets/{SkillsView-kSHgkBar.js → SkillsView-BtDyujiZ.js} +1 -1
- package/dist/client/assets/{TodoView-DYoicJNY.js → TodoView-BNHUnz50.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-BtWrziOX.css → WorkflowNodeEditor-BNgkFJ_P.css} +1 -1
- package/dist/client/assets/WorkflowNodeEditor-BXikFpra.js +8 -0
- package/dist/client/assets/{agent-import-generation-D6P8OUuV.js → agent-import-generation-B2kYEm1O.js} +1 -1
- package/dist/client/assets/{app-DegRNirF.js → app-B_HrdDXZ.js} +1 -1
- package/dist/client/assets/{app-BsIXfnu-.js → app-C6yo-M_n.js} +1 -1
- package/dist/client/assets/{app-B-IdUeIu.js → app-CH8ZgPm4.js} +1 -1
- package/dist/client/assets/{app-D9ktpVhR.js → app-D4DpgDss.js} +1 -1
- package/dist/client/assets/{app-nBTNvNKK.js → app-Qv0blCyY.js} +1 -1
- package/dist/client/assets/{app-C8muVNUU.js → app-kFdtajPy.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DLqKCckA.js → architectureDiagram-3BPJPVTR-B-Efjj4Z.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DRz6F8wZ.js → blockDiagram-GPEHLZMM-CaOVxrlM.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CJ9glQAp.js → c4Diagram-AAUBKEIU-D8aYt5F1.js} +1 -1
- package/dist/client/assets/channel-5bPK6pTS.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CjIBb3ln.js → chunk-2J33WTMH-VSDT0J0r.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DrcoEr1E.js → chunk-4BX2VUAB-Chx1wQgD.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DU-WcuA9.js → chunk-55IACEB6-MlqjhIJg.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-C5Lklr3l.js → chunk-727SXJPM-BheQNUi8.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DlyTTghY.js → chunk-AQP2D5EJ-C5EoJhfJ.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-D3C65m5Y.js → chunk-FMBD7UC4-B8_8qP3j.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BZY-4WZF.js → chunk-ND2GUHAM-BuglCGRx.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-CKUtTYy5.js → chunk-QZHKN3VN-B7_06dxp.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Dv9RQDqG.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Dv9RQDqG.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DbpsF4N5.js → cose-bilkent-S5V4N54A-Cm-ZOycx.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BwIo4me1.js → dagre-BM42HDAG-Dj_Gwjpv.js} +1 -1
- package/dist/client/assets/{dashboard-view-C94UCci5.js → dashboard-view-B4CRL5Fy.js} +1 -1
- package/dist/client/assets/{dashboard-view-BvAsW6UZ.js → dashboard-view-noD9p0Zs.js} +1 -1
- package/dist/client/assets/{dashboard-view-BMQm7Lt_.js → dashboard-view-pXXSUxG9.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-C-d8XY1c.js → diagram-2AECGRRQ-C_9BfShy.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-ByRrlL9w.js → diagram-5GNKFQAL-Cmg2qpCj.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BK7jb_J-.js → diagram-KO2AKTUF-2FNo2HXb.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-u2o4bYk6.js → diagram-LMA3HP47-DgnVeCp-.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-Dakk1V3D.js → diagram-OG6HWLK6-iAIR50HH.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-Yp33v-Cf.js → erDiagram-TEJ5UH35-Da4I04eN.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-C4-dR2TA.js → flowDiagram-I6XJVG4X-Bv9r2T0m.js} +1 -1
- package/dist/client/assets/{folder-open-C9qq38qV.js → folder-open-CwWtrDh6.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-C0CTCkFN.js → ganttDiagram-6RSMTGT7-BMeO84U_.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DK0Dd5mm.js → gitGraphDiagram-PVQCEYII-CWDh_RIb.js} +1 -1
- package/dist/client/assets/index-CB3mYxAB.css +1 -0
- package/dist/client/assets/{index-BqLVwYoA.js → index-CE7C_XsS.js} +294 -294
- package/dist/client/assets/{infoDiagram-5YYISTIA-u5MwFb7j.js → infoDiagram-5YYISTIA-BAE4KtCL.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-C7R6TziI.js → ishikawaDiagram-YF4QCWOH-C_iXAuOy.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Dom8W5Ab.js → journeyDiagram-JHISSGLW-BnxSHwDo.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-_47C02t3.js → kanban-definition-UN3LZRKU-DYNRm3Nu.js} +1 -1
- package/dist/client/assets/{mermaid.core-Cd3LKosp.js → mermaid.core-B3hvDDep.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-D-qVOEin.js → mindmap-definition-RKZ34NQL-s7KBEuPD.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-B0TXvVbM.js → pieDiagram-4H26LBE5-Cy1_IPUD.js} +1 -1
- package/dist/client/assets/{puzzle-BBYTjDQK.js → puzzle-DWc6gFQ7.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-KcFvcZPm.js → quadrantDiagram-W4KKPZXB-DqgVGp41.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DEObokVc.js → requirementDiagram-4Y6WPE33-CA5-TDeF.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BGYnEp22.js → sankeyDiagram-5OEKKPKP-Cuvi3RgE.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BcYgyJRU.js → sequenceDiagram-3UESZ5HK-Da3GfmGP.js} +1 -1
- package/dist/client/assets/{shield-alert-CZg8yaFA.js → shield-alert-_iY63ED4.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-BsTtbEqp.js → standing-instructions-template-CCd2YY9c.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CfZQIqmX.js → stateDiagram-AJRCARHV-CZ_I9ENR.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-nBEPRSH7.js → stateDiagram-v2-BHNVJYJU-BomoRVhY.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DySyabS_.js → timeline-definition-PNZ67QCA-C3CYvIuR.js} +1 -1
- package/dist/client/assets/{upload-DMd3zMLx.js → upload-D0RrO65v.js} +1 -1
- package/dist/client/assets/{users-9Pyvnn8K.js → users-CGszBY2v.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DPomfxp_.js → vennDiagram-CIIHVFJN-By9fi8NW.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BPfzngS8.js → wardley-L42UT6IY-DErnXPkI.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Yp4nidAP.js → wardleyDiagram-YWT4CUSO-DFfXZVPk.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-REgng603.js → xychartDiagram-2RQKCTM6-9Y5oZ5mi.js} +1 -1
- package/dist/client/index.html +4 -2
- package/dist/client/version.json +1 -1
- package/dist/extension.js +752 -207
- package/dist/migrations/0000_initial.sql +2 -0
- package/dist/migrations/0033_fn-8505_wedge_notification.sql +5 -0
- package/dist/plugin-sdk/index.js +1 -0
- package/dist/plugins/.fusion-ce-agents/.fusion-ce-upstream-provenance.json +7 -0
- package/dist/plugins/.fusion-ce-agents/ce-adversarial-document-reviewer.md +115 -0
- package/dist/plugins/.fusion-ce-agents/ce-adversarial-reviewer.md +111 -0
- package/dist/plugins/.fusion-ce-agents/ce-agent-native-planning-strategist.md +71 -0
- package/dist/plugins/.fusion-ce-agents/ce-agent-native-reviewer.md +181 -0
- package/dist/plugins/.fusion-ce-agents/ce-ankane-readme-writer.md +50 -0
- package/dist/plugins/.fusion-ce-agents/ce-api-contract-reviewer.md +52 -0
- package/dist/plugins/.fusion-ce-agents/ce-architecture-strategist.md +53 -0
- package/dist/plugins/.fusion-ce-agents/ce-best-practices-researcher.md +122 -0
- package/dist/plugins/.fusion-ce-agents/ce-code-simplicity-reviewer.md +87 -0
- package/dist/plugins/.fusion-ce-agents/ce-coherence-reviewer.md +73 -0
- package/dist/plugins/.fusion-ce-agents/ce-correctness-reviewer.md +52 -0
- package/dist/plugins/.fusion-ce-agents/ce-data-integrity-guardian.md +75 -0
- package/dist/plugins/.fusion-ce-agents/ce-data-migration-reviewer.md +119 -0
- package/dist/plugins/.fusion-ce-agents/ce-deployment-verification-agent.md +164 -0
- package/dist/plugins/.fusion-ce-agents/ce-design-implementation-reviewer.md +94 -0
- package/dist/plugins/.fusion-ce-agents/ce-design-iterator.md +197 -0
- package/dist/plugins/.fusion-ce-agents/ce-design-lens-reviewer.md +56 -0
- package/dist/plugins/.fusion-ce-agents/ce-feasibility-reviewer.md +65 -0
- package/dist/plugins/.fusion-ce-agents/ce-figma-design-sync.md +172 -0
- package/dist/plugins/.fusion-ce-agents/ce-framework-docs-researcher.md +100 -0
- package/dist/plugins/.fusion-ce-agents/ce-git-history-analyzer.md +47 -0
- package/dist/plugins/.fusion-ce-agents/ce-issue-intelligence-analyst.md +207 -0
- package/dist/plugins/.fusion-ce-agents/ce-julik-frontend-races-reviewer.md +52 -0
- package/dist/plugins/.fusion-ce-agents/ce-learnings-researcher.md +254 -0
- package/dist/plugins/.fusion-ce-agents/ce-maintainability-reviewer.md +77 -0
- package/dist/plugins/.fusion-ce-agents/ce-pattern-recognition-specialist.md +62 -0
- package/dist/plugins/.fusion-ce-agents/ce-performance-oracle.md +115 -0
- package/dist/plugins/.fusion-ce-agents/ce-performance-reviewer.md +54 -0
- package/dist/plugins/.fusion-ce-agents/ce-pr-comment-resolver.md +63 -0
- package/dist/plugins/.fusion-ce-agents/ce-previous-comments-reviewer.md +68 -0
- package/dist/plugins/.fusion-ce-agents/ce-product-lens-reviewer.md +92 -0
- package/dist/plugins/.fusion-ce-agents/ce-project-standards-reviewer.md +84 -0
- package/dist/plugins/.fusion-ce-agents/ce-reliability-reviewer.md +52 -0
- package/dist/plugins/.fusion-ce-agents/ce-repo-research-analyst.md +263 -0
- package/dist/plugins/.fusion-ce-agents/ce-scope-guardian-reviewer.md +79 -0
- package/dist/plugins/.fusion-ce-agents/ce-security-lens-reviewer.md +48 -0
- package/dist/plugins/.fusion-ce-agents/ce-security-reviewer.md +54 -0
- package/dist/plugins/.fusion-ce-agents/ce-security-sentinel.md +98 -0
- package/dist/plugins/.fusion-ce-agents/ce-session-historian.md +89 -0
- package/dist/plugins/.fusion-ce-agents/ce-slack-researcher.md +133 -0
- package/dist/plugins/.fusion-ce-agents/ce-spec-flow-analyzer.md +87 -0
- package/dist/plugins/.fusion-ce-agents/ce-swift-ios-reviewer.md +107 -0
- package/dist/plugins/.fusion-ce-agents/ce-testing-reviewer.md +52 -0
- package/dist/plugins/.fusion-ce-agents/ce-web-researcher.md +127 -0
- package/dist/plugins/.fusion-ce-skills/.fusion-ce-upstream-provenance.json +7 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/SKILL.md +318 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/brainstorm-sections.md +354 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/handoff.md +172 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/html-rendering.md +662 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/markdown-rendering.md +236 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/synthesis-summary.md +271 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/universal-brainstorming.md +71 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/references/visual-probes.md +128 -0
- package/dist/plugins/.fusion-ce-skills/ce-brainstorm/scripts/visual-probe-server.js +419 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/SKILL.md +821 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/action-class-rubric.md +26 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/bulk-preview.md +112 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/cross-model-review.md +63 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/diff-scope.md +41 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/findings-schema.json +137 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/persona-catalog.md +63 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/adversarial-reviewer.md +102 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/agent-native-reviewer.md +173 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/api-contract-reviewer.md +43 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/correctness-reviewer.md +43 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/data-migration-reviewer.md +111 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/deployment-verification-agent.md +157 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/julik-frontend-races-reviewer.md +44 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/learnings-researcher.md +247 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/maintainability-reviewer.md +68 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/performance-reviewer.md +45 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/previous-comments-reviewer.md +59 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/project-standards-reviewer.md +75 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/reliability-reviewer.md +43 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/security-reviewer.md +45 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/swift-ios-reviewer.md +99 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/personas/testing-reviewer.md +43 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/review-output-template.md +170 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/subagent-template.md +199 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/tracker-defer.md +149 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/validator-template.md +89 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/references/walkthrough.md +249 -0
- package/dist/plugins/.fusion-ce-skills/ce-code-review/scripts/cross-model-adversarial-review.sh +218 -0
- package/dist/plugins/.fusion-ce-skills/ce-commit/SKILL.md +105 -0
- package/dist/plugins/.fusion-ce-skills/ce-commit-push-pr/SKILL.md +134 -0
- package/dist/plugins/.fusion-ce-skills/ce-commit-push-pr/references/branch-creation.md +55 -0
- package/dist/plugins/.fusion-ce-skills/ce-commit-push-pr/references/pr-description-writing.md +115 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/SKILL.md +712 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/assets/resolution-template.md +94 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/performance-oracle.md +108 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/security-sentinel.md +91 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/agents/session-historian.md +83 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/concepts-vocabulary.md +78 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/schema.yaml +231 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/references/yaml-schema.md +118 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/scripts/session-history/discover-sessions.sh +130 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/scripts/session-history/extract-errors.py +254 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/scripts/session-history/extract-metadata.py +456 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/scripts/session-history/extract-skeleton.py +570 -0
- package/dist/plugins/.fusion-ce-skills/ce-compound/scripts/validate-frontmatter.py +137 -0
- package/dist/plugins/.fusion-ce-skills/ce-debug/SKILL.md +257 -0
- package/dist/plugins/.fusion-ce-skills/ce-debug/references/anti-patterns.md +91 -0
- package/dist/plugins/.fusion-ce-skills/ce-debug/references/defense-in-depth.md +35 -0
- package/dist/plugins/.fusion-ce-skills/ce-debug/references/investigation-techniques.md +374 -0
- package/dist/plugins/.fusion-ce-skills/ce-doc-review/SKILL.md +70 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/SKILL.md +401 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/agents/issue-intelligence-analyst.md +200 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/agents/slack-researcher.md +127 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/agents/web-researcher.md +121 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/divergent-ideation.md +89 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/html-rendering.md +662 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/ideation-sections.md +191 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/markdown-rendering.md +236 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/post-ideation-workflow.md +166 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/universal-ideation.md +107 -0
- package/dist/plugins/.fusion-ce-skills/ce-ideate/references/web-research-cache.md +55 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/SKILL.md +858 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/agent-native-planning-strategist.md +62 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/architecture-strategist.md +46 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/best-practices-researcher.md +114 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/data-migration-reviewer.md +103 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/deployment-verification-agent.md +157 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/framework-docs-researcher.md +93 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/learnings-researcher.md +247 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/performance-oracle.md +108 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/repo-research-analyst.md +256 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/security-sentinel.md +91 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/slack-researcher.md +127 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/spec-flow-analyzer.md +80 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/agents/web-researcher.md +121 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/approach-altitude.md +55 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/deepening-workflow.md +259 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/html-rendering.md +668 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/markdown-rendering.md +236 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/plan-handoff.md +126 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/plan-sections.md +405 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/synthesis-summary.md +396 -0
- package/dist/plugins/.fusion-ce-skills/ce-plan/references/universal-planning.md +168 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/SKILL.md +53 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/references/agents/pr-comment-resolver.md +56 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/references/evaluation-rubric.md +106 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/references/full-mode.md +283 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/references/targeted-mode.md +45 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/scripts/get-pr-comments +159 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/scripts/get-thread-for-comment +76 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread +33 -0
- package/dist/plugins/.fusion-ce-skills/ce-resolve-pr-feedback/scripts/resolve-pr-thread +23 -0
- package/dist/plugins/.fusion-ce-skills/ce-strategy/SKILL.md +97 -0
- package/dist/plugins/.fusion-ce-skills/ce-strategy/references/interview.md +143 -0
- package/dist/plugins/.fusion-ce-skills/ce-strategy/references/strategy-template.md +89 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/SKILL.md +429 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/agents/figma-design-sync.md +165 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/execution-engines.md +85 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/non-code-execution.md +23 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/review-findings-followup.md +104 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/shipping-workflow.md +133 -0
- package/dist/plugins/.fusion-ce-skills/ce-work/references/tracker-defer.md +149 -0
- package/dist/plugins/fusion-plugin-compound-engineering/.bundled.reload-3.js +11266 -0
- package/dist/plugins/fusion-plugin-compound-engineering/.bundled.reload-4.js +11266 -0
- package/dist/plugins/fusion-plugin-dependency-graph/.bundled.reload-1.js +8206 -0
- package/dist/plugins/fusion-plugin-grok-runtime/.bundled.reload-2.js +26623 -0
- package/package.json +1 -1
- package/dist/client/assets/PluginManager-DBhJ1i27.js +0 -1
- package/dist/client/assets/SettingsModal-BDgH9XID.js +0 -21
- package/dist/client/assets/SettingsModal-BXDnzDkJ.css +0 -1
- package/dist/client/assets/WorkflowNodeEditor-DLno6bSJ.js +0 -8
- package/dist/client/assets/channel-Dj4nOgJO.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DnkFo5Qy.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DnkFo5Qy.js +0 -1
- package/dist/client/assets/index-6FBJPKkr.css +0 -1
|
@@ -983,6 +983,7 @@ var init_workflow_steps = __esm({
|
|
|
983
983
|
"in-review",
|
|
984
984
|
"merged",
|
|
985
985
|
"failed",
|
|
986
|
+
"task-wedged",
|
|
986
987
|
"awaiting-approval",
|
|
987
988
|
"awaiting-user-review",
|
|
988
989
|
"planning-awaiting-input",
|
|
@@ -1056,6 +1057,50 @@ var init_documents_artifacts = __esm({
|
|
|
1056
1057
|
}
|
|
1057
1058
|
});
|
|
1058
1059
|
|
|
1060
|
+
// ../core/src/types/task-core.ts
|
|
1061
|
+
function assertNotWorkspaceTaskMerge(task) {
|
|
1062
|
+
if (isWorkspaceTask(task)) {
|
|
1063
|
+
throw new WorkspaceTaskMergeError(
|
|
1064
|
+
`Workspace task ${task.id} cannot merge until per-repo merge support (master-plan U6) lands`
|
|
1065
|
+
);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
function isWorkspaceTask(task) {
|
|
1069
|
+
const worktrees = task.workspaceWorktrees;
|
|
1070
|
+
return !!worktrees && Object.keys(worktrees).length > 0;
|
|
1071
|
+
}
|
|
1072
|
+
var CheckoutConflictError, DUPLICATE_OF_METADATA_KEY, WorkspaceTaskMergeError;
|
|
1073
|
+
var init_task_core = __esm({
|
|
1074
|
+
"../core/src/types/task-core.ts"() {
|
|
1075
|
+
"use strict";
|
|
1076
|
+
CheckoutConflictError = class extends Error {
|
|
1077
|
+
constructor(taskId, currentHolderId, requestedById) {
|
|
1078
|
+
super(`Task ${taskId} is already checked out by agent ${currentHolderId}`);
|
|
1079
|
+
this.taskId = taskId;
|
|
1080
|
+
this.currentHolderId = currentHolderId;
|
|
1081
|
+
this.requestedById = requestedById;
|
|
1082
|
+
this.name = "CheckoutConflictError";
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
DUPLICATE_OF_METADATA_KEY = "duplicateOfTaskIds";
|
|
1086
|
+
WorkspaceTaskMergeError = class extends Error {
|
|
1087
|
+
constructor(message) {
|
|
1088
|
+
super(message);
|
|
1089
|
+
this.name = "WorkspaceTaskMergeError";
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
// ../core/src/types/todo-list.ts
|
|
1096
|
+
var SHARED_STATE_SNAPSHOT_VERSION;
|
|
1097
|
+
var init_todo_list = __esm({
|
|
1098
|
+
"../core/src/types/todo-list.ts"() {
|
|
1099
|
+
"use strict";
|
|
1100
|
+
SHARED_STATE_SNAPSHOT_VERSION = 1;
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1059
1104
|
// ../core/src/task-helpers.ts
|
|
1060
1105
|
function getPrimaryPrInfo(task) {
|
|
1061
1106
|
return task.prInfos?.[0] ?? task.prInfo;
|
|
@@ -1545,10 +1590,18 @@ var init_settings_schema = __esm({
|
|
|
1545
1590
|
"use strict";
|
|
1546
1591
|
init_in_review_stall();
|
|
1547
1592
|
DEFAULT_GLOBAL_SETTINGS = {
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1593
|
+
/*
|
|
1594
|
+
FNXC:PostgresEmbedded 2026-07-22-23:55:
|
|
1595
|
+
Embedded PostgreSQL is shared by all local Fusion projects and processes.
|
|
1596
|
+
Deliberately undefined (not 500): getSettings() merges these defaults, so a
|
|
1597
|
+
concrete value here would be indistinguishable from an operator choice and
|
|
1598
|
+
would mask the platform-aware server-side default in
|
|
1599
|
+
resolveEmbeddedMaxConnections (win32 150, else 500). Issue #2411: Windows
|
|
1600
|
+
backends are separate processes; a 500-connection cap exhausts the desktop
|
|
1601
|
+
heap under load and forked backends die with 0xC0000142, taking the embedded
|
|
1602
|
+
cluster and dashboard down.
|
|
1603
|
+
*/
|
|
1604
|
+
embeddedPostgresMaxConnections: void 0,
|
|
1552
1605
|
/*
|
|
1553
1606
|
FNXC:DashboardTheming 2026-07-03-00:00:
|
|
1554
1607
|
Fresh installs must follow the operating system theme until the user explicitly chooses Light, Dark, or System. Keep this global default aligned with dashboard and desktop pre-hydration fallbacks.
|
|
@@ -2311,6 +2364,53 @@ var init_settings_schema = __esm({
|
|
|
2311
2364
|
}
|
|
2312
2365
|
});
|
|
2313
2366
|
|
|
2367
|
+
// ../core/src/types/settings-scope.ts
|
|
2368
|
+
function isMcpSecretRef(value) {
|
|
2369
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
2370
|
+
const candidate = value;
|
|
2371
|
+
return typeof candidate.secretRef === "string" && candidate.secretRef.trim().length > 0 && (candidate.scope === "project" || candidate.scope === "global");
|
|
2372
|
+
}
|
|
2373
|
+
var init_settings_scope = __esm({
|
|
2374
|
+
"../core/src/types/settings-scope.ts"() {
|
|
2375
|
+
"use strict";
|
|
2376
|
+
init_settings_schema();
|
|
2377
|
+
}
|
|
2378
|
+
});
|
|
2379
|
+
|
|
2380
|
+
// ../core/src/types/board-config.ts
|
|
2381
|
+
var COLUMN_LABELS, COLUMN_DESCRIPTIONS, VALID_TRANSITIONS;
|
|
2382
|
+
var init_board_config = __esm({
|
|
2383
|
+
"../core/src/types/board-config.ts"() {
|
|
2384
|
+
"use strict";
|
|
2385
|
+
COLUMN_LABELS = {
|
|
2386
|
+
triage: "Planning",
|
|
2387
|
+
todo: "Todo",
|
|
2388
|
+
"in-progress": "In Progress",
|
|
2389
|
+
"in-review": "In Review",
|
|
2390
|
+
done: "Done",
|
|
2391
|
+
archived: "Archived"
|
|
2392
|
+
};
|
|
2393
|
+
COLUMN_DESCRIPTIONS = {
|
|
2394
|
+
triage: "Raw ideas \u2014 AI will plan these",
|
|
2395
|
+
"in-progress": "AI is working on this in a worktree",
|
|
2396
|
+
done: "Merged and closed",
|
|
2397
|
+
archived: "Completed and archived"
|
|
2398
|
+
};
|
|
2399
|
+
VALID_TRANSITIONS = {
|
|
2400
|
+
// FN-4892: intake-side heuristics may cold-archive tasks before execution starts.
|
|
2401
|
+
triage: ["todo", "archived"],
|
|
2402
|
+
// FN-4892: allow direct archival for newly specified intake tasks.
|
|
2403
|
+
todo: ["in-progress", "triage", "archived"],
|
|
2404
|
+
// NOTE: "in-progress" → "done" is enabled for mission validation tasks that complete directly.
|
|
2405
|
+
// Regular implementation tasks should move through "in-review" before "done".
|
|
2406
|
+
"in-progress": ["in-review", "todo", "triage", "done"],
|
|
2407
|
+
"in-review": ["done", "in-progress", "todo", "triage"],
|
|
2408
|
+
done: ["todo", "triage", "archived"],
|
|
2409
|
+
archived: ["done"]
|
|
2410
|
+
};
|
|
2411
|
+
}
|
|
2412
|
+
});
|
|
2413
|
+
|
|
2314
2414
|
// ../core/src/types/docker-nodes.ts
|
|
2315
2415
|
function validateDockerNodeConfig(config3) {
|
|
2316
2416
|
const errors = [];
|
|
@@ -2421,6 +2521,41 @@ var init_docker_nodes = __esm({
|
|
|
2421
2521
|
}
|
|
2422
2522
|
});
|
|
2423
2523
|
|
|
2524
|
+
// ../core/src/types/archive-planning.ts
|
|
2525
|
+
function formatPlanningPlanMd(summary) {
|
|
2526
|
+
const normalizeListItem = (item) => item.replace(/\s+/g, " ").trim();
|
|
2527
|
+
const list = (items) => items && items.length > 0 ? items.map((item) => `- ${normalizeListItem(item)}`).join("\n") : "_None_";
|
|
2528
|
+
const proposedChanges = list(summary.proposedChanges);
|
|
2529
|
+
const acceptanceCriteria = list(summary.acceptanceCriteria);
|
|
2530
|
+
const dependencies = list(summary.suggestedDependencies);
|
|
2531
|
+
const deliverables = list(summary.keyDeliverables);
|
|
2532
|
+
return `# ${summary.title}
|
|
2533
|
+
|
|
2534
|
+
${summary.description}
|
|
2535
|
+
|
|
2536
|
+
## What to change
|
|
2537
|
+
${proposedChanges}
|
|
2538
|
+
|
|
2539
|
+
## Acceptance criteria
|
|
2540
|
+
${acceptanceCriteria}
|
|
2541
|
+
|
|
2542
|
+
## Size
|
|
2543
|
+
${summary.suggestedSize}
|
|
2544
|
+
|
|
2545
|
+
## Suggested dependencies
|
|
2546
|
+
${dependencies}
|
|
2547
|
+
|
|
2548
|
+
## Key deliverables
|
|
2549
|
+
${deliverables}
|
|
2550
|
+
`;
|
|
2551
|
+
}
|
|
2552
|
+
var init_archive_planning = __esm({
|
|
2553
|
+
"../core/src/types/archive-planning.ts"() {
|
|
2554
|
+
"use strict";
|
|
2555
|
+
init_docker_nodes();
|
|
2556
|
+
}
|
|
2557
|
+
});
|
|
2558
|
+
|
|
2424
2559
|
// ../core/src/types/agent-state.ts
|
|
2425
2560
|
function isEphemeralAgent(agent) {
|
|
2426
2561
|
const metadata = agent.metadata ?? {};
|
|
@@ -4146,49 +4281,6 @@ var init_workflow_lifecycle_validation = __esm({
|
|
|
4146
4281
|
});
|
|
4147
4282
|
|
|
4148
4283
|
// ../core/src/types.ts
|
|
4149
|
-
function assertNotWorkspaceTaskMerge(task) {
|
|
4150
|
-
if (isWorkspaceTask(task)) {
|
|
4151
|
-
throw new WorkspaceTaskMergeError(
|
|
4152
|
-
`Workspace task ${task.id} cannot merge until per-repo merge support (master-plan U6) lands`
|
|
4153
|
-
);
|
|
4154
|
-
}
|
|
4155
|
-
}
|
|
4156
|
-
function isWorkspaceTask(task) {
|
|
4157
|
-
const worktrees = task.workspaceWorktrees;
|
|
4158
|
-
return !!worktrees && Object.keys(worktrees).length > 0;
|
|
4159
|
-
}
|
|
4160
|
-
function isMcpSecretRef(value) {
|
|
4161
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
4162
|
-
const candidate = value;
|
|
4163
|
-
return typeof candidate.secretRef === "string" && candidate.secretRef.trim().length > 0 && (candidate.scope === "project" || candidate.scope === "global");
|
|
4164
|
-
}
|
|
4165
|
-
function formatPlanningPlanMd(summary) {
|
|
4166
|
-
const normalizeListItem = (item) => item.replace(/\s+/g, " ").trim();
|
|
4167
|
-
const list = (items) => items && items.length > 0 ? items.map((item) => `- ${normalizeListItem(item)}`).join("\n") : "_None_";
|
|
4168
|
-
const proposedChanges = list(summary.proposedChanges);
|
|
4169
|
-
const acceptanceCriteria = list(summary.acceptanceCriteria);
|
|
4170
|
-
const dependencies = list(summary.suggestedDependencies);
|
|
4171
|
-
const deliverables = list(summary.keyDeliverables);
|
|
4172
|
-
return `# ${summary.title}
|
|
4173
|
-
|
|
4174
|
-
${summary.description}
|
|
4175
|
-
|
|
4176
|
-
## What to change
|
|
4177
|
-
${proposedChanges}
|
|
4178
|
-
|
|
4179
|
-
## Acceptance criteria
|
|
4180
|
-
${acceptanceCriteria}
|
|
4181
|
-
|
|
4182
|
-
## Size
|
|
4183
|
-
${summary.suggestedSize}
|
|
4184
|
-
|
|
4185
|
-
## Suggested dependencies
|
|
4186
|
-
${dependencies}
|
|
4187
|
-
|
|
4188
|
-
## Key deliverables
|
|
4189
|
-
${deliverables}
|
|
4190
|
-
`;
|
|
4191
|
-
}
|
|
4192
4284
|
function validateMessageMetadata(metadata) {
|
|
4193
4285
|
if (!metadata) {
|
|
4194
4286
|
return;
|
|
@@ -4240,7 +4332,7 @@ function validateMessageMetadata(metadata) {
|
|
|
4240
4332
|
if (metadata.proposalStatus === "pending" && (metadata.claimOwnerToken !== void 0 || metadata.claimStartedAt !== void 0)) throw new Error("pending proposal cannot have a creation lease");
|
|
4241
4333
|
}
|
|
4242
4334
|
}
|
|
4243
|
-
var DEPRECATED_BUILTIN_WORKFLOW_IDS
|
|
4335
|
+
var DEPRECATED_BUILTIN_WORKFLOW_IDS;
|
|
4244
4336
|
var init_types = __esm({
|
|
4245
4337
|
"../core/src/types.ts"() {
|
|
4246
4338
|
"use strict";
|
|
@@ -4254,8 +4346,11 @@ var init_types = __esm({
|
|
|
4254
4346
|
init_merge_policy();
|
|
4255
4347
|
init_workflow_steps();
|
|
4256
4348
|
init_documents_artifacts();
|
|
4257
|
-
|
|
4258
|
-
|
|
4349
|
+
init_task_core();
|
|
4350
|
+
init_todo_list();
|
|
4351
|
+
init_settings_scope();
|
|
4352
|
+
init_board_config();
|
|
4353
|
+
init_archive_planning();
|
|
4259
4354
|
init_agent_state();
|
|
4260
4355
|
init_planner_intervention();
|
|
4261
4356
|
init_agents();
|
|
@@ -4270,49 +4365,6 @@ var init_types = __esm({
|
|
|
4270
4365
|
DEPRECATED_BUILTIN_WORKFLOW_IDS = /* @__PURE__ */ new Set([
|
|
4271
4366
|
"builtin:brainstorming"
|
|
4272
4367
|
]);
|
|
4273
|
-
CheckoutConflictError = class extends Error {
|
|
4274
|
-
constructor(taskId, currentHolderId, requestedById) {
|
|
4275
|
-
super(`Task ${taskId} is already checked out by agent ${currentHolderId}`);
|
|
4276
|
-
this.taskId = taskId;
|
|
4277
|
-
this.currentHolderId = currentHolderId;
|
|
4278
|
-
this.requestedById = requestedById;
|
|
4279
|
-
this.name = "CheckoutConflictError";
|
|
4280
|
-
}
|
|
4281
|
-
};
|
|
4282
|
-
DUPLICATE_OF_METADATA_KEY = "duplicateOfTaskIds";
|
|
4283
|
-
WorkspaceTaskMergeError = class extends Error {
|
|
4284
|
-
constructor(message) {
|
|
4285
|
-
super(message);
|
|
4286
|
-
this.name = "WorkspaceTaskMergeError";
|
|
4287
|
-
}
|
|
4288
|
-
};
|
|
4289
|
-
SHARED_STATE_SNAPSHOT_VERSION = 1;
|
|
4290
|
-
COLUMN_LABELS = {
|
|
4291
|
-
triage: "Planning",
|
|
4292
|
-
todo: "Todo",
|
|
4293
|
-
"in-progress": "In Progress",
|
|
4294
|
-
"in-review": "In Review",
|
|
4295
|
-
done: "Done",
|
|
4296
|
-
archived: "Archived"
|
|
4297
|
-
};
|
|
4298
|
-
COLUMN_DESCRIPTIONS = {
|
|
4299
|
-
triage: "Raw ideas \u2014 AI will plan these",
|
|
4300
|
-
"in-progress": "AI is working on this in a worktree",
|
|
4301
|
-
done: "Merged and closed",
|
|
4302
|
-
archived: "Completed and archived"
|
|
4303
|
-
};
|
|
4304
|
-
VALID_TRANSITIONS = {
|
|
4305
|
-
// FN-4892: intake-side heuristics may cold-archive tasks before execution starts.
|
|
4306
|
-
triage: ["todo", "archived"],
|
|
4307
|
-
// FN-4892: allow direct archival for newly specified intake tasks.
|
|
4308
|
-
todo: ["in-progress", "triage", "archived"],
|
|
4309
|
-
// NOTE: "in-progress" → "done" is enabled for mission validation tasks that complete directly.
|
|
4310
|
-
// Regular implementation tasks should move through "in-review" before "done".
|
|
4311
|
-
"in-progress": ["in-review", "todo", "triage", "done"],
|
|
4312
|
-
"in-review": ["done", "in-progress", "todo", "triage"],
|
|
4313
|
-
done: ["todo", "triage", "archived"],
|
|
4314
|
-
archived: ["done"]
|
|
4315
|
-
};
|
|
4316
4368
|
}
|
|
4317
4369
|
});
|
|
4318
4370
|
|
|
@@ -12933,6 +12985,7 @@ var init_project = __esm({
|
|
|
12933
12985
|
paused: integer("paused").default(0),
|
|
12934
12986
|
userPaused: integer("user_paused").default(0),
|
|
12935
12987
|
pausedReason: text("paused_reason"),
|
|
12988
|
+
wedgeNotification: text("wedge_notification"),
|
|
12936
12989
|
baseBranch: text("base_branch"),
|
|
12937
12990
|
branch: text("branch"),
|
|
12938
12991
|
autoMerge: integer("auto_merge"),
|
|
@@ -21297,6 +21350,9 @@ function validateColumns(ir2) {
|
|
|
21297
21350
|
throw new WorkflowIrError(`Workflow IR has duplicate column id '${column.id}'`);
|
|
21298
21351
|
}
|
|
21299
21352
|
seen.add(column.id);
|
|
21353
|
+
if (column.description !== void 0 && typeof column.description !== "string") {
|
|
21354
|
+
throw new WorkflowIrError(`Workflow IR column '${column.id}' description must be a string`);
|
|
21355
|
+
}
|
|
21300
21356
|
if (!Array.isArray(column.traits)) {
|
|
21301
21357
|
throw new WorkflowIrError(`Workflow IR column '${column.id}' traits must be an array`);
|
|
21302
21358
|
}
|
|
@@ -36520,6 +36576,7 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
36520
36576
|
const legacyAdoptionDrainedMarkerRuntimeGrantsAlreadyApplied = applied.includes(
|
|
36521
36577
|
LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION
|
|
36522
36578
|
);
|
|
36579
|
+
const taskWedgeNotificationAlreadyApplied = applied.includes(TASK_WEDGE_NOTIFICATION_VERSION);
|
|
36523
36580
|
assertBinaryNotOlderThanDatabase(applied);
|
|
36524
36581
|
let schemaChanged = false;
|
|
36525
36582
|
if (!baselineAlreadyApplied) {
|
|
@@ -36843,17 +36900,25 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
36843
36900
|
);
|
|
36844
36901
|
schemaChanged = true;
|
|
36845
36902
|
}
|
|
36903
|
+
if (!taskWedgeNotificationAlreadyApplied) {
|
|
36904
|
+
const migrationSql = await readFile4(TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, "utf8");
|
|
36905
|
+
await tx.execute(sql.raw(migrationSql));
|
|
36906
|
+
await tx.execute(
|
|
36907
|
+
sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${TASK_WEDGE_NOTIFICATION_VERSION}) ON CONFLICT (version) DO NOTHING`
|
|
36908
|
+
);
|
|
36909
|
+
schemaChanged = true;
|
|
36910
|
+
}
|
|
36846
36911
|
return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
|
|
36847
36912
|
});
|
|
36848
36913
|
}
|
|
36849
|
-
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH;
|
|
36914
|
+
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH;
|
|
36850
36915
|
var init_schema_applier = __esm({
|
|
36851
36916
|
"../core/src/postgres/schema-applier.ts"() {
|
|
36852
36917
|
"use strict";
|
|
36853
36918
|
init_drizzle_orm();
|
|
36854
36919
|
init_plugin_schema_hook();
|
|
36855
36920
|
init_advisory_locks();
|
|
36856
|
-
SCHEMA_BASELINE_VERSION = "
|
|
36921
|
+
SCHEMA_BASELINE_VERSION = "0033";
|
|
36857
36922
|
TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
|
36858
36923
|
INITIAL_SCHEMA_VERSION = "0000";
|
|
36859
36924
|
AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
|
|
@@ -36886,6 +36951,7 @@ var init_schema_applier = __esm({
|
|
|
36886
36951
|
SQLITE_MIGRATION_RUNTIME_READ_VERSION = "0030";
|
|
36887
36952
|
WORKFLOW_TASK_CONTINUATIONS_VERSION = "0031";
|
|
36888
36953
|
LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION = "0032";
|
|
36954
|
+
TASK_WEDGE_NOTIFICATION_VERSION = "0033";
|
|
36889
36955
|
LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
|
|
36890
36956
|
StaleBinarySchemaError = class extends Error {
|
|
36891
36957
|
constructor(databaseVersion, binaryVersion) {
|
|
@@ -36992,6 +37058,10 @@ var init_schema_applier = __esm({
|
|
|
36992
37058
|
MIGRATIONS_DIR,
|
|
36993
37059
|
"0032_legacy_adoption_drained_marker_runtime_grants.sql"
|
|
36994
37060
|
);
|
|
37061
|
+
TASK_WEDGE_NOTIFICATION_MIGRATION_PATH = join8(
|
|
37062
|
+
MIGRATIONS_DIR,
|
|
37063
|
+
"0033_fn-8505_wedge_notification.sql"
|
|
37064
|
+
);
|
|
36995
37065
|
}
|
|
36996
37066
|
});
|
|
36997
37067
|
|
|
@@ -37382,6 +37452,7 @@ __export(sqlite_migrator_exports, {
|
|
|
37382
37452
|
isSqliteMigrationComplete: () => isSqliteMigrationComplete,
|
|
37383
37453
|
migrateLegacyProjectPluginRows: () => migrateLegacyProjectPluginRows,
|
|
37384
37454
|
migrateSqliteToPostgres: () => migrateSqliteToPostgres,
|
|
37455
|
+
projectPluginSqliteMigrationKey: () => projectPluginSqliteMigrationKey,
|
|
37385
37456
|
recordSqliteMigrationComplete: () => recordSqliteMigrationComplete,
|
|
37386
37457
|
toSnakeCase: () => toSnakeCase2
|
|
37387
37458
|
});
|
|
@@ -37924,7 +37995,12 @@ function normalizeLegacyJson(value, fallback) {
|
|
|
37924
37995
|
return fallback;
|
|
37925
37996
|
}
|
|
37926
37997
|
}
|
|
37998
|
+
function projectPluginSqliteMigrationKey(projectPath) {
|
|
37999
|
+
return `project-plugins:${resolve6(projectPath)}`;
|
|
38000
|
+
}
|
|
37927
38001
|
async function migrateLegacyProjectPluginRows(db, sqlitePath, projectPath) {
|
|
38002
|
+
const migrationKey = projectPluginSqliteMigrationKey(projectPath);
|
|
38003
|
+
if (await isSqliteMigrationComplete(db, migrationKey)) return;
|
|
37928
38004
|
await db.transaction(async (tx) => {
|
|
37929
38005
|
await migrateLegacyProjectPluginRowsOnSession(
|
|
37930
38006
|
tx,
|
|
@@ -37934,19 +38010,14 @@ async function migrateLegacyProjectPluginRows(db, sqlitePath, projectPath) {
|
|
|
37934
38010
|
});
|
|
37935
38011
|
}
|
|
37936
38012
|
async function migrateLegacyProjectPluginRowsOnSession(db, sqlitePath, projectPath) {
|
|
37937
|
-
if (!sqliteTableExists(sqlitePath, "plugins")) return;
|
|
37938
|
-
await acquireSqliteMigrationStateLock(db);
|
|
37939
38013
|
const canonicalProjectPath = resolve6(projectPath);
|
|
37940
|
-
const migrationKey =
|
|
38014
|
+
const migrationKey = projectPluginSqliteMigrationKey(projectPath);
|
|
38015
|
+
await acquireSqliteMigrationStateLock(db);
|
|
37941
38016
|
await ensureMigrationStateTable(db);
|
|
37942
38017
|
await db.execute(sql`SELECT pg_advisory_xact_lock(hashtextextended(${migrationKey}, 0))`);
|
|
37943
|
-
const completed = await db
|
|
37944
|
-
|
|
37945
|
-
|
|
37946
|
-
WHERE migration_key = ${migrationKey} AND status = 'complete'
|
|
37947
|
-
LIMIT 1
|
|
37948
|
-
`);
|
|
37949
|
-
if (completed.length > 0) return;
|
|
38018
|
+
const completed = await isSqliteMigrationComplete(db, migrationKey);
|
|
38019
|
+
if (completed) return;
|
|
38020
|
+
if (!sqliteTableExists(sqlitePath, "plugins")) return;
|
|
37950
38021
|
const sqlite = openSqlite(sqlitePath);
|
|
37951
38022
|
let rows;
|
|
37952
38023
|
try {
|
|
@@ -39032,6 +39103,17 @@ function buildPgCtlOptionsString(port, flags) {
|
|
|
39032
39103
|
function buildPgCtlStartArgs(dataDir, logFile, optionsString) {
|
|
39033
39104
|
return ["-D", dataDir, "-o", optionsString, "-l", logFile, "-W", "start"];
|
|
39034
39105
|
}
|
|
39106
|
+
function withWindowsNativeBinPath(environment, nativeRoot, platform3 = process.platform) {
|
|
39107
|
+
if (platform3 !== "win32") return environment;
|
|
39108
|
+
const pathKey = Object.keys(environment).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
39109
|
+
const bin = nativeRoot.replace(/[\\/]+$/, "") + "\\bin";
|
|
39110
|
+
const normalize8 = (value) => value.replace(/\//g, "\\").toLowerCase();
|
|
39111
|
+
const inherited = environment[pathKey] ?? "";
|
|
39112
|
+
const segments = inherited.split(";").filter(Boolean);
|
|
39113
|
+
const normalizedBin = normalize8(bin);
|
|
39114
|
+
const deduplicated = segments.filter((segment) => normalize8(segment) !== normalizedBin);
|
|
39115
|
+
return { ...environment, [pathKey]: [bin, ...deduplicated].join(";") };
|
|
39116
|
+
}
|
|
39035
39117
|
function readPostgresPid(dataDir) {
|
|
39036
39118
|
try {
|
|
39037
39119
|
const lines = readFileSync3(join9(dataDir, "postmaster.pid"), "utf-8").split("\n");
|
|
@@ -39086,7 +39168,13 @@ async function startServerElevatedRestricted(opts) {
|
|
|
39086
39168
|
`embedded postgres: elevated start via pg_ctl restricted token (no helper account); log ${logFile}`
|
|
39087
39169
|
);
|
|
39088
39170
|
let stopped = false;
|
|
39171
|
+
let logMonitor = null;
|
|
39172
|
+
const stopMonitoring = () => {
|
|
39173
|
+
if (logMonitor) clearInterval(logMonitor);
|
|
39174
|
+
logMonitor = null;
|
|
39175
|
+
};
|
|
39089
39176
|
const killAll = () => {
|
|
39177
|
+
stopMonitoring();
|
|
39090
39178
|
if (stopped) return;
|
|
39091
39179
|
stopped = true;
|
|
39092
39180
|
const r = spawnSync(pgCtl, ["-D", opts.dataDir, "-m", "fast", "-t", "30", "-w", "stop"], {
|
|
@@ -39120,14 +39208,21 @@ async function startServerElevatedRestricted(opts) {
|
|
|
39120
39208
|
killAll();
|
|
39121
39209
|
await waitForDown();
|
|
39122
39210
|
},
|
|
39211
|
+
stopMonitoring,
|
|
39123
39212
|
async stopWrapperOnly() {
|
|
39213
|
+
stopMonitoring();
|
|
39124
39214
|
stopped = true;
|
|
39125
39215
|
}
|
|
39126
39216
|
};
|
|
39127
39217
|
opts.onLaunched?.(handle);
|
|
39128
39218
|
const launch = await new Promise(
|
|
39129
39219
|
(resolve39, reject) => {
|
|
39130
|
-
const child = spawn(pgCtl, args, {
|
|
39220
|
+
const child = spawn(pgCtl, args, {
|
|
39221
|
+
windowsHide: true,
|
|
39222
|
+
// Do not mutate process.env: sibling dashboard/engine children must
|
|
39223
|
+
// retain their inherited environment unchanged.
|
|
39224
|
+
env: withWindowsNativeBinPath(process.env, opts.nativeRoot)
|
|
39225
|
+
});
|
|
39131
39226
|
let output = "";
|
|
39132
39227
|
child.stdout.on("data", (d) => output += d.toString());
|
|
39133
39228
|
child.stderr.on("data", (d) => output += d.toString());
|
|
@@ -39152,16 +39247,14 @@ ${readTail(logFile, 2e3)}`
|
|
|
39152
39247
|
killAll();
|
|
39153
39248
|
throw new Error("embedded postgres: elevated launch cancelled before ready.");
|
|
39154
39249
|
}
|
|
39250
|
+
if (await probeTcpPort(opts.port, 500)) {
|
|
39251
|
+
ready = true;
|
|
39252
|
+
break;
|
|
39253
|
+
}
|
|
39155
39254
|
const tail = readTail(logFile, 3e3);
|
|
39156
39255
|
if (tail !== lastSnapshot) {
|
|
39157
39256
|
lastSnapshot = tail;
|
|
39158
|
-
opts.onLog(`elevated
|
|
39159
|
-
}
|
|
39160
|
-
if (/database system is ready to accept connections/.test(tail)) {
|
|
39161
|
-
if (await probeTcpPort(opts.port, 500)) {
|
|
39162
|
-
ready = true;
|
|
39163
|
-
break;
|
|
39164
|
-
}
|
|
39257
|
+
opts.onLog(`elevated diagnostic pg={${tail.slice(-400)}}`);
|
|
39165
39258
|
}
|
|
39166
39259
|
if (/\bFATAL\b|\bPANIC\b|could not (bind|start|create|access|connect|load)|not permitted|Permission denied|is not the owner/i.test(tail)) {
|
|
39167
39260
|
killAll();
|
|
@@ -39193,6 +39286,18 @@ ${tail}`
|
|
|
39193
39286
|
opts.onLog(
|
|
39194
39287
|
`embedded postgres: elevated server ready on 127.0.0.1:${opts.port} (pid ${postgresPid ?? 0}, restricted token)`
|
|
39195
39288
|
);
|
|
39289
|
+
let lastLogSnapshot = "";
|
|
39290
|
+
const observePostReadyLog = () => {
|
|
39291
|
+
if (stopped) return;
|
|
39292
|
+
const snapshot = readTail(logFile, 16384);
|
|
39293
|
+
if (snapshot === "(no log file)" || snapshot === lastLogSnapshot) return;
|
|
39294
|
+
const next = snapshot.startsWith(lastLogSnapshot) ? snapshot.slice(lastLogSnapshot.length) : snapshot;
|
|
39295
|
+
lastLogSnapshot = snapshot;
|
|
39296
|
+
if (next) opts.onLog(next);
|
|
39297
|
+
};
|
|
39298
|
+
observePostReadyLog();
|
|
39299
|
+
logMonitor = setInterval(observePostReadyLog, 250);
|
|
39300
|
+
if (typeof logMonitor.unref === "function") logMonitor.unref();
|
|
39196
39301
|
return handle;
|
|
39197
39302
|
}
|
|
39198
39303
|
function probeTcpPort(port, timeoutMs) {
|
|
@@ -39212,10 +39317,26 @@ function probeTcpPort(port, timeoutMs) {
|
|
|
39212
39317
|
socket.once("error", () => finish(false));
|
|
39213
39318
|
});
|
|
39214
39319
|
}
|
|
39215
|
-
var elevatedCache;
|
|
39320
|
+
var WindowsPostgresFatalDetector, elevatedCache;
|
|
39216
39321
|
var init_embedded_windows_elevated = __esm({
|
|
39217
39322
|
"../core/src/postgres/embedded-windows-elevated.ts"() {
|
|
39218
39323
|
"use strict";
|
|
39324
|
+
WindowsPostgresFatalDetector = class {
|
|
39325
|
+
buffer = "";
|
|
39326
|
+
matched = false;
|
|
39327
|
+
push(chunk) {
|
|
39328
|
+
if (this.matched || !chunk) return false;
|
|
39329
|
+
this.buffer = (this.buffer + chunk).slice(-16384);
|
|
39330
|
+
const text2 = this.buffer.toLowerCase();
|
|
39331
|
+
if (/server process(?:\s+\(pid\s+\d+\))?\s+was terminated by exception\s+0xc0000142[\s\S]*?terminating any other active server processes[\s\S]*?shutting down due to startup process failure[\s\S]*?database system is shut down/.test(
|
|
39332
|
+
text2
|
|
39333
|
+
)) {
|
|
39334
|
+
this.matched = true;
|
|
39335
|
+
return true;
|
|
39336
|
+
}
|
|
39337
|
+
return false;
|
|
39338
|
+
}
|
|
39339
|
+
};
|
|
39219
39340
|
elevatedCache = null;
|
|
39220
39341
|
}
|
|
39221
39342
|
});
|
|
@@ -39225,10 +39346,14 @@ var embedded_lifecycle_exports = {};
|
|
|
39225
39346
|
__export(embedded_lifecycle_exports, {
|
|
39226
39347
|
DEFAULT_EMBEDDED_DATABASE: () => DEFAULT_EMBEDDED_DATABASE,
|
|
39227
39348
|
DEFAULT_EMBEDDED_INITDB_FLAGS: () => DEFAULT_EMBEDDED_INITDB_FLAGS,
|
|
39349
|
+
DEFAULT_EMBEDDED_MAX_CONNECTIONS: () => DEFAULT_EMBEDDED_MAX_CONNECTIONS,
|
|
39350
|
+
DEFAULT_EMBEDDED_MAX_CONNECTIONS_WIN32: () => DEFAULT_EMBEDDED_MAX_CONNECTIONS_WIN32,
|
|
39228
39351
|
DEFAULT_EMBEDDED_PASSWORD: () => DEFAULT_EMBEDDED_PASSWORD,
|
|
39229
39352
|
DEFAULT_EMBEDDED_POSTGRES_FLAGS: () => DEFAULT_EMBEDDED_POSTGRES_FLAGS,
|
|
39230
39353
|
DEFAULT_EMBEDDED_USER: () => DEFAULT_EMBEDDED_USER,
|
|
39231
39354
|
DEFAULT_START_TIMEOUT_MS: () => DEFAULT_START_TIMEOUT_MS,
|
|
39355
|
+
EMBEDDED_MAX_CONNECTIONS_MAX: () => EMBEDDED_MAX_CONNECTIONS_MAX,
|
|
39356
|
+
EMBEDDED_MAX_CONNECTIONS_MIN: () => EMBEDDED_MAX_CONNECTIONS_MIN,
|
|
39232
39357
|
EmbeddedPostgresLifecycle: () => EmbeddedPostgresLifecycle,
|
|
39233
39358
|
EmbeddedStartTimeoutError: () => EmbeddedStartTimeoutError,
|
|
39234
39359
|
__setEmbeddedPostgresCtorForTests: () => __setEmbeddedPostgresCtorForTests,
|
|
@@ -39247,6 +39372,7 @@ __export(embedded_lifecycle_exports, {
|
|
|
39247
39372
|
normalizeMacosEmbeddedPostgresDylibSymlinks: () => normalizeMacosEmbeddedPostgresDylibSymlinks,
|
|
39248
39373
|
readPortFromPostmasterPid: () => readPortFromPostmasterPid,
|
|
39249
39374
|
resolveElectronAsarUnpackedPath: () => resolveElectronAsarUnpackedPath,
|
|
39375
|
+
resolveEmbeddedMaxConnections: () => resolveEmbeddedMaxConnections,
|
|
39250
39376
|
uninstallElectronAsarNativePathPatchForTests: () => uninstallElectronAsarNativePathPatchForTests
|
|
39251
39377
|
});
|
|
39252
39378
|
import {
|
|
@@ -39456,6 +39582,23 @@ function materializeEmbeddedPostgresRuntimeBinaries(nativeRoot, options) {
|
|
|
39456
39582
|
writeFileSync2(marker, sourceMarker, "utf8");
|
|
39457
39583
|
return destRoot;
|
|
39458
39584
|
}
|
|
39585
|
+
function isWindowsEmbeddedPostgresBinary(command) {
|
|
39586
|
+
return process.platform === "win32" && typeof command === "string" && /[\\/]bin[\\/](?:postgres|initdb|pg_ctl)\.exe$/i.test(command);
|
|
39587
|
+
}
|
|
39588
|
+
function withWindowsPostgresSpawnEnvironment(command, rest) {
|
|
39589
|
+
if (!isWindowsEmbeddedPostgresBinary(command)) return rest;
|
|
39590
|
+
const args = [...rest];
|
|
39591
|
+
const optionIndex = args.length - 1;
|
|
39592
|
+
const existing = args[optionIndex];
|
|
39593
|
+
if (!existing || typeof existing !== "object" || Array.isArray(existing)) return args;
|
|
39594
|
+
const binDir = dirname6(command);
|
|
39595
|
+
const nativeRoot = dirname6(binDir);
|
|
39596
|
+
args[optionIndex] = {
|
|
39597
|
+
...existing,
|
|
39598
|
+
env: withWindowsNativeBinPath(existing.env ?? process.env, nativeRoot)
|
|
39599
|
+
};
|
|
39600
|
+
return args;
|
|
39601
|
+
}
|
|
39459
39602
|
function installElectronAsarNativePathPatch() {
|
|
39460
39603
|
if (electronAsarNativePathPatchInstalled) return;
|
|
39461
39604
|
electronAsarNativePathPatchInstalled = true;
|
|
@@ -39473,7 +39616,10 @@ function installElectronAsarNativePathPatch() {
|
|
|
39473
39616
|
const originalSpawn = childProcessMod.spawn.bind(childProcessMod);
|
|
39474
39617
|
childProcessMod.spawn = (command, ...rest) => {
|
|
39475
39618
|
const fixedCommand = typeof command === "string" ? resolveElectronAsarUnpackedPath(command) : command;
|
|
39476
|
-
return originalSpawn(
|
|
39619
|
+
return originalSpawn(
|
|
39620
|
+
fixedCommand,
|
|
39621
|
+
...withWindowsPostgresSpawnEnvironment(fixedCommand, rest)
|
|
39622
|
+
);
|
|
39477
39623
|
};
|
|
39478
39624
|
const fsPromisesMod = require2("fs/promises");
|
|
39479
39625
|
const originalStat = fsPromisesMod.stat.bind(fsPromisesMod);
|
|
@@ -39522,6 +39668,12 @@ function getEmbeddedPostgresCtor() {
|
|
|
39522
39668
|
function defaultEmbeddedPostgresFlagsFor(platform3) {
|
|
39523
39669
|
return platform3 === "win32" ? [] : ["-c", "shared_memory_type=mmap"];
|
|
39524
39670
|
}
|
|
39671
|
+
function resolveEmbeddedMaxConnections(configured, platform3 = process.platform) {
|
|
39672
|
+
if (typeof configured === "number" && Number.isInteger(configured)) {
|
|
39673
|
+
return Math.min(EMBEDDED_MAX_CONNECTIONS_MAX, Math.max(EMBEDDED_MAX_CONNECTIONS_MIN, configured));
|
|
39674
|
+
}
|
|
39675
|
+
return platform3 === "win32" ? DEFAULT_EMBEDDED_MAX_CONNECTIONS_WIN32 : DEFAULT_EMBEDDED_MAX_CONNECTIONS;
|
|
39676
|
+
}
|
|
39525
39677
|
function defaultEmbeddedDataDir() {
|
|
39526
39678
|
const home = process.env.HOME || process.env.USERPROFILE || process.cwd();
|
|
39527
39679
|
return join10(home, ".fusion", "embedded-postgres", "default");
|
|
@@ -39708,7 +39860,7 @@ function signalNumber(signal) {
|
|
|
39708
39860
|
return 0;
|
|
39709
39861
|
}
|
|
39710
39862
|
}
|
|
39711
|
-
var require2, stagedEmbeddedPgBundleCache, EMBEDDED_PG_BIN_NAMES, MATERIALIZATION_MARKER_VERSION, electronAsarNativePathPatchInstalled, electronAsarNativePathPatchRestore, embeddedPostgresCtorCache, embeddedPostgresCtorIsTestOverride, windowsElevatedAdminForTests, windowsNativeRootForTests, windowsLauncherForTests, log4, DEFAULT_EMBEDDED_USER, DEFAULT_EMBEDDED_PASSWORD, DEFAULT_EMBEDDED_DATABASE, DEFAULT_EMBEDDED_POSTGRES_FLAGS, DEFAULT_EMBEDDED_INITDB_FLAGS, DEFAULT_START_TIMEOUT_MS, PG_VERSION_FILENAME, MACOS_EMBEDDED_DYLIB_SYMLINKS, runningInstances, POSTMASTER_PID_READ_ATTEMPTS, POSTMASTER_PID_READ_RETRY_MS, EmbeddedPostgresLifecycle, EmbeddedStartCancelledError, EmbeddedStartTimeoutError;
|
|
39863
|
+
var require2, stagedEmbeddedPgBundleCache, EMBEDDED_PG_BIN_NAMES, MATERIALIZATION_MARKER_VERSION, electronAsarNativePathPatchInstalled, electronAsarNativePathPatchRestore, embeddedPostgresCtorCache, embeddedPostgresCtorIsTestOverride, windowsElevatedAdminForTests, windowsNativeRootForTests, windowsLauncherForTests, log4, DEFAULT_EMBEDDED_USER, DEFAULT_EMBEDDED_PASSWORD, DEFAULT_EMBEDDED_DATABASE, DEFAULT_EMBEDDED_POSTGRES_FLAGS, DEFAULT_EMBEDDED_MAX_CONNECTIONS, DEFAULT_EMBEDDED_MAX_CONNECTIONS_WIN32, EMBEDDED_MAX_CONNECTIONS_MIN, EMBEDDED_MAX_CONNECTIONS_MAX, DEFAULT_EMBEDDED_INITDB_FLAGS, DEFAULT_START_TIMEOUT_MS, PG_VERSION_FILENAME, MACOS_EMBEDDED_DYLIB_SYMLINKS, runningInstances, POSTMASTER_PID_READ_ATTEMPTS, POSTMASTER_PID_READ_RETRY_MS, EmbeddedPostgresLifecycle, EmbeddedStartCancelledError, EmbeddedStartTimeoutError;
|
|
39712
39864
|
var init_embedded_lifecycle = __esm({
|
|
39713
39865
|
"../core/src/postgres/embedded-lifecycle.ts"() {
|
|
39714
39866
|
"use strict";
|
|
@@ -39739,6 +39891,10 @@ var init_embedded_lifecycle = __esm({
|
|
|
39739
39891
|
DEFAULT_EMBEDDED_PASSWORD = "password";
|
|
39740
39892
|
DEFAULT_EMBEDDED_DATABASE = "fusion";
|
|
39741
39893
|
DEFAULT_EMBEDDED_POSTGRES_FLAGS = defaultEmbeddedPostgresFlagsFor(process.platform);
|
|
39894
|
+
DEFAULT_EMBEDDED_MAX_CONNECTIONS = 500;
|
|
39895
|
+
DEFAULT_EMBEDDED_MAX_CONNECTIONS_WIN32 = 150;
|
|
39896
|
+
EMBEDDED_MAX_CONNECTIONS_MIN = 32;
|
|
39897
|
+
EMBEDDED_MAX_CONNECTIONS_MAX = 2e3;
|
|
39742
39898
|
DEFAULT_EMBEDDED_INITDB_FLAGS = [
|
|
39743
39899
|
"--encoding=UTF8",
|
|
39744
39900
|
"--locale=C"
|
|
@@ -39781,6 +39937,10 @@ var init_embedded_lifecycle = __esm({
|
|
|
39781
39937
|
* on a failure that is handled before the timeout fires.
|
|
39782
39938
|
*/
|
|
39783
39939
|
startTimer = null;
|
|
39940
|
+
windowsFatalDetector = new WindowsPostgresFatalDetector();
|
|
39941
|
+
recoveryAttempts = 0;
|
|
39942
|
+
recoveryInFlight = null;
|
|
39943
|
+
stopRequested = false;
|
|
39784
39944
|
constructor(opts) {
|
|
39785
39945
|
this.options = {
|
|
39786
39946
|
dataDir: opts.dataDir,
|
|
@@ -39795,6 +39955,15 @@ var init_embedded_lifecycle = __esm({
|
|
|
39795
39955
|
onError: opts.onError ?? ((err) => log4.error(String(err)))
|
|
39796
39956
|
};
|
|
39797
39957
|
}
|
|
39958
|
+
/**
|
|
39959
|
+
* Forward native process output to the existing sink, then schedule recovery
|
|
39960
|
+
* only for a confirmed owned Windows fatal shutdown sequence.
|
|
39961
|
+
*/
|
|
39962
|
+
forwardPostgresLog = (message) => {
|
|
39963
|
+
this.options.onLog(message);
|
|
39964
|
+
if (process.platform !== "win32" || !this.running || !this.ownsProcess) return;
|
|
39965
|
+
if (this.windowsFatalDetector.push(message)) void this.recoverWindowsFatalOnce();
|
|
39966
|
+
};
|
|
39798
39967
|
/** The configured or discovered port. Undefined until assigned (explicit or discovered in `start()`). */
|
|
39799
39968
|
getPort() {
|
|
39800
39969
|
return this.options.port ?? this.resolvedPort;
|
|
@@ -39891,11 +40060,19 @@ var init_embedded_lifecycle = __esm({
|
|
|
39891
40060
|
migrationUrlOverridden: false
|
|
39892
40061
|
};
|
|
39893
40062
|
}
|
|
40063
|
+
return this.startBounded();
|
|
40064
|
+
}
|
|
40065
|
+
/**
|
|
40066
|
+
* Start an owned postmaster with the same cancellation and timeout contract
|
|
40067
|
+
* used by public startup. Recovery calls this directly because it must not
|
|
40068
|
+
* join a stale pid file or allocate a new endpoint between pool reconnects.
|
|
40069
|
+
*/
|
|
40070
|
+
async startBounded(preferredPort) {
|
|
39894
40071
|
if (this.options.startTimeoutMs <= 0) {
|
|
39895
|
-
return this.startInternal();
|
|
40072
|
+
return this.startInternal(void 0, preferredPort);
|
|
39896
40073
|
}
|
|
39897
40074
|
const controller = new AbortController();
|
|
39898
|
-
const startAttempt = this.startInternal(controller.signal);
|
|
40075
|
+
const startAttempt = this.startInternal(controller.signal, preferredPort);
|
|
39899
40076
|
let timer2;
|
|
39900
40077
|
const timeout = new Promise((_resolve, reject) => {
|
|
39901
40078
|
timer2 = setTimeout(() => {
|
|
@@ -39921,12 +40098,9 @@ var init_embedded_lifecycle = __esm({
|
|
|
39921
40098
|
this.startTimer = null;
|
|
39922
40099
|
}
|
|
39923
40100
|
}
|
|
39924
|
-
/**
|
|
39925
|
-
|
|
39926
|
-
|
|
39927
|
-
*/
|
|
39928
|
-
async startInternal(signal) {
|
|
39929
|
-
const port = this.options.port ?? await findFreePort();
|
|
40101
|
+
/** The actual start sequence, invoked only through {@link startBounded}. */
|
|
40102
|
+
async startInternal(signal, preferredPort) {
|
|
40103
|
+
const port = this.options.port ?? preferredPort ?? this.resolvedPort ?? await findFreePort();
|
|
39930
40104
|
if (signal?.aborted) throw new EmbeddedStartCancelledError(this.options.dataDir);
|
|
39931
40105
|
this.resolvedPort = port;
|
|
39932
40106
|
const alreadyInitialized = isDataDirInitialized(this.options.dataDir);
|
|
@@ -39940,7 +40114,7 @@ var init_embedded_lifecycle = __esm({
|
|
|
39940
40114
|
authMethod: "password",
|
|
39941
40115
|
initdbFlags: [...this.options.initdbFlags],
|
|
39942
40116
|
postgresFlags: [...this.options.postgresFlags],
|
|
39943
|
-
onLog: this.
|
|
40117
|
+
onLog: this.forwardPostgresLog,
|
|
39944
40118
|
onError: this.options.onError
|
|
39945
40119
|
});
|
|
39946
40120
|
this.pg = pg;
|
|
@@ -39972,7 +40146,7 @@ var init_embedded_lifecycle = __esm({
|
|
|
39972
40146
|
dataDir: this.options.dataDir,
|
|
39973
40147
|
port,
|
|
39974
40148
|
postgresFlags: this.options.postgresFlags,
|
|
39975
|
-
onLog: this.
|
|
40149
|
+
onLog: this.forwardPostgresLog,
|
|
39976
40150
|
onError: this.options.onError,
|
|
39977
40151
|
startTimeoutMs: this.options.startTimeoutMs,
|
|
39978
40152
|
signal,
|
|
@@ -40050,6 +40224,43 @@ var init_embedded_lifecycle = __esm({
|
|
|
40050
40224
|
migrationUrlOverridden: false
|
|
40051
40225
|
};
|
|
40052
40226
|
}
|
|
40227
|
+
/**
|
|
40228
|
+
* FNXC:PostgresEmbedded 2026-07-22-16:25:
|
|
40229
|
+
* A 0xC0000142 backend crash shuts down its whole PostgreSQL cluster. One
|
|
40230
|
+
* lifecycle-owned retry reuses the initialized directory and same resolved
|
|
40231
|
+
* port; joiners, stop/detach, and a second incident are deliberately inert.
|
|
40232
|
+
*/
|
|
40233
|
+
async recoverWindowsFatalOnce() {
|
|
40234
|
+
if (this.recoveryInFlight || this.recoveryAttempts >= 1 || this.stopRequested || !this.ownsProcess) return;
|
|
40235
|
+
this.recoveryAttempts += 1;
|
|
40236
|
+
this.recoveryInFlight = (async () => {
|
|
40237
|
+
this.options.onLog("embedded postgres: detected Windows DLL initialization shutdown; attempting one owned-cluster recovery");
|
|
40238
|
+
try {
|
|
40239
|
+
if (this.nonAdminHandle) await this.nonAdminHandle.stop();
|
|
40240
|
+
else await this.pg?.stop();
|
|
40241
|
+
this.pg = null;
|
|
40242
|
+
this.nonAdminHandle = null;
|
|
40243
|
+
this.running = false;
|
|
40244
|
+
runningInstances.delete(this.options.dataDir);
|
|
40245
|
+
if (this.stopRequested || !this.ownsProcess) return;
|
|
40246
|
+
const recoveryPort = this.resolvedPort;
|
|
40247
|
+
if (recoveryPort === void 0) {
|
|
40248
|
+
throw new Error("embedded postgres: recovery lost its resolved port");
|
|
40249
|
+
}
|
|
40250
|
+
await this.startBounded(recoveryPort);
|
|
40251
|
+
this.options.onLog("embedded postgres: Windows owned-cluster recovery completed; existing pools may reconnect");
|
|
40252
|
+
} catch (error2) {
|
|
40253
|
+
this.running = false;
|
|
40254
|
+
runningInstances.delete(this.options.dataDir);
|
|
40255
|
+
this.options.onError(
|
|
40256
|
+
`embedded postgres: Windows DLL initialization recovery failed after one retry; restart Fusion and inspect the System log. ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
40257
|
+
);
|
|
40258
|
+
} finally {
|
|
40259
|
+
this.recoveryInFlight = null;
|
|
40260
|
+
}
|
|
40261
|
+
})();
|
|
40262
|
+
await this.recoveryInFlight;
|
|
40263
|
+
}
|
|
40053
40264
|
async settleCancelledStart(pg) {
|
|
40054
40265
|
if (this.nonAdminHandle) {
|
|
40055
40266
|
try {
|
|
@@ -40196,6 +40407,7 @@ var init_embedded_lifecycle = __esm({
|
|
|
40196
40407
|
*/
|
|
40197
40408
|
detachWithoutStop() {
|
|
40198
40409
|
this.uninstallShutdownHook();
|
|
40410
|
+
this.nonAdminHandle?.stopMonitoring();
|
|
40199
40411
|
this.pg = null;
|
|
40200
40412
|
this.nonAdminHandle = null;
|
|
40201
40413
|
this.running = false;
|
|
@@ -40203,6 +40415,7 @@ var init_embedded_lifecycle = __esm({
|
|
|
40203
40415
|
runningInstances.delete(this.options.dataDir);
|
|
40204
40416
|
}
|
|
40205
40417
|
async stop() {
|
|
40418
|
+
this.stopRequested = true;
|
|
40206
40419
|
this.uninstallShutdownHook();
|
|
40207
40420
|
if (!this.ownsProcess) {
|
|
40208
40421
|
this.running = false;
|
|
@@ -52227,10 +52440,10 @@ async function bootSchemaBackendOnce(options, bypassProjectIsolation = false) {
|
|
|
52227
52440
|
let resolvedBackend = backend;
|
|
52228
52441
|
let embeddedDataDir = null;
|
|
52229
52442
|
if (backend.mode === "embedded") {
|
|
52230
|
-
const { EmbeddedPostgresLifecycle: EmbeddedPostgresLifecycle2, defaultEmbeddedDataDir: defaultEmbeddedDataDir2, DEFAULT_EMBEDDED_DATABASE: DEFAULT_EMBEDDED_DATABASE2 } = await Promise.resolve().then(() => (init_embedded_lifecycle(), embedded_lifecycle_exports));
|
|
52443
|
+
const { EmbeddedPostgresLifecycle: EmbeddedPostgresLifecycle2, defaultEmbeddedDataDir: defaultEmbeddedDataDir2, DEFAULT_EMBEDDED_DATABASE: DEFAULT_EMBEDDED_DATABASE2, resolveEmbeddedMaxConnections: resolveEmbeddedMaxConnections2 } = await Promise.resolve().then(() => (init_embedded_lifecycle(), embedded_lifecycle_exports));
|
|
52231
52444
|
const { GlobalSettingsStore: GlobalSettingsStore2 } = await Promise.resolve().then(() => (init_global_settings(), global_settings_exports));
|
|
52232
52445
|
const configuredMaxConnections = process.env.VITEST === "true" && !options.globalSettingsDir ? void 0 : (await new GlobalSettingsStore2(options.globalSettingsDir).getSettings()).embeddedPostgresMaxConnections;
|
|
52233
|
-
const maxConnections =
|
|
52446
|
+
const maxConnections = resolveEmbeddedMaxConnections2(configuredMaxConnections);
|
|
52234
52447
|
const dataDir = resolve8(options.embeddedDataDir ?? defaultEmbeddedDataDir2());
|
|
52235
52448
|
embeddedDataDir = dataDir;
|
|
52236
52449
|
log5.log(`startup-factory: starting embedded PostgreSQL (data dir ${dataDir})`);
|
|
@@ -52467,7 +52680,20 @@ async function createTaskStoreForBackend(options) {
|
|
|
52467
52680
|
try {
|
|
52468
52681
|
const fusionDir = join16(rootDir, ".fusion");
|
|
52469
52682
|
const legacySqlitePath = join16(fusionDir, "fusion.db");
|
|
52470
|
-
|
|
52683
|
+
const {
|
|
52684
|
+
migrateSqliteToPostgres: migrateSqliteToPostgres2,
|
|
52685
|
+
defaultMigrationSources: defaultMigrationSources2,
|
|
52686
|
+
formatMigrationProgress: formatMigrationProgress2,
|
|
52687
|
+
isSqliteMigrationComplete: isSqliteMigrationComplete2,
|
|
52688
|
+
completeSqliteMigration: completeSqliteMigration2,
|
|
52689
|
+
recordSqliteMigrationComplete: recordSqliteMigrationComplete2,
|
|
52690
|
+
CENTRAL_SQLITE_MIGRATION_KEY: CENTRAL_SQLITE_MIGRATION_KEY2
|
|
52691
|
+
} = await Promise.resolve().then(() => (init_sqlite_migrator(), sqlite_migrator_exports));
|
|
52692
|
+
const fallbackProjectId = fallbackProjectIdForRoot(rootDir);
|
|
52693
|
+
let migrationProjectId = options.projectId ?? await lookupRegisteredProjectIdByPath(connections.migration, rootDir) ?? fallbackProjectId;
|
|
52694
|
+
let migrationKey = `project:${migrationProjectId}`;
|
|
52695
|
+
let migrationComplete = await isSqliteMigrationComplete2(connections.migration, migrationKey);
|
|
52696
|
+
if (!migrationComplete && existsSync11(legacySqlitePath)) {
|
|
52471
52697
|
let globalDir = options.globalSettingsDir;
|
|
52472
52698
|
if (!globalDir) {
|
|
52473
52699
|
try {
|
|
@@ -52477,21 +52703,24 @@ async function createTaskStoreForBackend(options) {
|
|
|
52477
52703
|
globalDir = void 0;
|
|
52478
52704
|
}
|
|
52479
52705
|
}
|
|
52480
|
-
let
|
|
52706
|
+
let resolvedFromLegacyCentral = false;
|
|
52707
|
+
const centralMigrationComplete = await isSqliteMigrationComplete2(
|
|
52708
|
+
connections.migration,
|
|
52709
|
+
CENTRAL_SQLITE_MIGRATION_KEY2
|
|
52710
|
+
);
|
|
52481
52711
|
const legacyCentralPath = globalDir ? join16(globalDir, "fusion-central.db") : void 0;
|
|
52482
|
-
if (!migrationProjectId && legacyCentralPath && existsSync11(legacyCentralPath) && isValidSqliteDatabaseFile(legacyCentralPath)) {
|
|
52712
|
+
if (!centralMigrationComplete && migrationProjectId === fallbackProjectId && legacyCentralPath && existsSync11(legacyCentralPath) && isValidSqliteDatabaseFile(legacyCentralPath)) {
|
|
52483
52713
|
const { DatabaseSync: DatabaseSync2 } = await Promise.resolve().then(() => (init_sqlite_adapter(), sqlite_adapter_exports));
|
|
52484
52714
|
const legacyCentral = new DatabaseSync2(legacyCentralPath, { readOnly: true });
|
|
52485
52715
|
try {
|
|
52486
52716
|
const row = legacyCentral.prepare(`SELECT id FROM projects WHERE path = ? LIMIT 1`).get(rootDir);
|
|
52487
|
-
migrationProjectId = row?.id;
|
|
52717
|
+
migrationProjectId = row?.id ?? migrationProjectId;
|
|
52718
|
+
resolvedFromLegacyCentral = Boolean(row?.id);
|
|
52488
52719
|
} catch {
|
|
52489
52720
|
} finally {
|
|
52490
52721
|
legacyCentral.close();
|
|
52491
52722
|
}
|
|
52492
52723
|
}
|
|
52493
|
-
const fallbackProjectId = fallbackProjectIdForRoot(rootDir);
|
|
52494
|
-
migrationProjectId ??= fallbackProjectId;
|
|
52495
52724
|
if (migrationProjectId !== fallbackProjectId) {
|
|
52496
52725
|
try {
|
|
52497
52726
|
await rekeyFallbackProjectPartition(connections.migration, fallbackProjectId, migrationProjectId);
|
|
@@ -52507,14 +52736,9 @@ async function createTaskStoreForBackend(options) {
|
|
|
52507
52736
|
}
|
|
52508
52737
|
}
|
|
52509
52738
|
}
|
|
52510
|
-
|
|
52511
|
-
|
|
52512
|
-
const migrationComplete = await isSqliteMigrationComplete2(connections.migration, migrationKey);
|
|
52739
|
+
migrationKey = `project:${migrationProjectId}`;
|
|
52740
|
+
migrationComplete = await isSqliteMigrationComplete2(connections.migration, migrationKey);
|
|
52513
52741
|
if (!migrationComplete && isValidSqliteDatabaseFile(legacySqlitePath)) {
|
|
52514
|
-
const centralMigrationComplete = await isSqliteMigrationComplete2(
|
|
52515
|
-
connections.migration,
|
|
52516
|
-
CENTRAL_SQLITE_MIGRATION_KEY2
|
|
52517
|
-
);
|
|
52518
52742
|
const sources = defaultMigrationSources2(fusionDir, globalDir ?? join16(fusionDir, "__no-global-dir__")).filter((source) => !centralMigrationComplete || source.pgSchema !== "central").filter((source) => existsSync11(source.sqlitePath) && isValidSqliteDatabaseFile(source.sqlitePath));
|
|
52519
52743
|
if (sources.length > 0) {
|
|
52520
52744
|
log5.log(`startup-factory: empty PostgreSQL database with legacy SQLite data present \u2014 auto-migrating ${sources.length} source(s) (SQLite files are kept as backups)`);
|
|
@@ -52549,6 +52773,12 @@ async function createTaskStoreForBackend(options) {
|
|
|
52549
52773
|
rootDir
|
|
52550
52774
|
});
|
|
52551
52775
|
}
|
|
52776
|
+
if (resolvedFromLegacyCentral) {
|
|
52777
|
+
const registeredId = await lookupRegisteredProjectIdByPath(connections.migration, rootDir);
|
|
52778
|
+
if (registeredId !== migrationProjectId) {
|
|
52779
|
+
throw new Error(`legacy project identity ${migrationProjectId} was not materialized for ${rootDir} before migration completion`);
|
|
52780
|
+
}
|
|
52781
|
+
}
|
|
52552
52782
|
await completeSqliteMigration2(connections.migration, migrationKey);
|
|
52553
52783
|
if (sources.some((source) => source.pgSchema === "central")) {
|
|
52554
52784
|
await recordSqliteMigrationComplete2(
|
|
@@ -52566,14 +52796,9 @@ async function createTaskStoreForBackend(options) {
|
|
|
52566
52796
|
log5.log(`startup-factory: SQLite \u2192 PostgreSQL auto-migration complete (${migratedRows} row(s) across ${report.tables.length} table(s))`);
|
|
52567
52797
|
}
|
|
52568
52798
|
}
|
|
52569
|
-
if (isValidSqliteDatabaseFile(legacySqlitePath)) {
|
|
52570
|
-
await migrateLegacyProjectPluginRows2(
|
|
52571
|
-
connections.migration,
|
|
52572
|
-
legacySqlitePath,
|
|
52573
|
-
rootDir
|
|
52574
|
-
);
|
|
52575
|
-
}
|
|
52576
52799
|
}
|
|
52800
|
+
const { migrateLegacyProjectPluginRows: migrateLegacyProjectPluginRows2 } = await Promise.resolve().then(() => (init_sqlite_migrator(), sqlite_migrator_exports));
|
|
52801
|
+
await migrateLegacyProjectPluginRows2(connections.migration, legacySqlitePath, rootDir);
|
|
52577
52802
|
} catch (err) {
|
|
52578
52803
|
await connections.close().catch(() => void 0);
|
|
52579
52804
|
await stopEmbeddedRuntime(
|
|
@@ -62240,6 +62465,7 @@ var init_persistence = __esm({
|
|
|
62240
62465
|
defineTaskColumn("overlapBlockedBy", (task) => task.overlapBlockedBy ?? null),
|
|
62241
62466
|
defineTaskColumn("paused", (task) => task.paused ? 1 : 0),
|
|
62242
62467
|
defineTaskColumn("pausedReason", (task) => task.pausedReason ?? null),
|
|
62468
|
+
defineTaskColumn("wedgeNotification", (task) => toJsonNullable(task.wedgeNotification)),
|
|
62243
62469
|
defineTaskColumn("userPaused", (task) => task.userPaused ? 1 : 0),
|
|
62244
62470
|
defineTaskColumn("baseBranch", (task) => task.baseBranch ?? null),
|
|
62245
62471
|
defineTaskColumn("branch", (task) => task.branch ?? null),
|
|
@@ -62649,6 +62875,7 @@ function rowToTask(row) {
|
|
|
62649
62875
|
overlapBlockedBy: row.overlapBlockedBy || void 0,
|
|
62650
62876
|
paused: row.paused ? true : void 0,
|
|
62651
62877
|
pausedReason: row.pausedReason || void 0,
|
|
62878
|
+
wedgeNotification: fromJson(row.wedgeNotification) ?? void 0,
|
|
62652
62879
|
userPaused: row.userPaused ? true : void 0,
|
|
62653
62880
|
baseBranch: row.baseBranch || void 0,
|
|
62654
62881
|
executionStartBranch: row.executionStartBranch || void 0,
|
|
@@ -84904,6 +85131,7 @@ function getTaskSelectClauseImpl2(store, slim, tableAlias) {
|
|
|
84904
85131
|
"overlapBlockedBy",
|
|
84905
85132
|
"paused",
|
|
84906
85133
|
"pausedReason",
|
|
85134
|
+
"wedgeNotification",
|
|
84907
85135
|
"userPaused",
|
|
84908
85136
|
"baseBranch",
|
|
84909
85137
|
"branch",
|
|
@@ -91622,7 +91850,7 @@ var init_async_eval_store = __esm({
|
|
|
91622
91850
|
}
|
|
91623
91851
|
});
|
|
91624
91852
|
|
|
91625
|
-
// ../core/src/task-store/
|
|
91853
|
+
// ../core/src/task-store/project-store-ops.ts
|
|
91626
91854
|
import { randomUUID as randomUUID33 } from "node:crypto";
|
|
91627
91855
|
import { mkdir as mkdir13, writeFile as writeFile12 } from "node:fs/promises";
|
|
91628
91856
|
import { join as join33 } from "node:path";
|
|
@@ -92490,8 +92718,8 @@ function getEvalStoreImpl(store) {
|
|
|
92490
92718
|
return store.evalStore;
|
|
92491
92719
|
}
|
|
92492
92720
|
var workflowDefinitionBeforeInsertForTesting;
|
|
92493
|
-
var
|
|
92494
|
-
"../core/src/task-store/
|
|
92721
|
+
var init_project_store_ops = __esm({
|
|
92722
|
+
"../core/src/task-store/project-store-ops.ts"() {
|
|
92495
92723
|
"use strict";
|
|
92496
92724
|
init_store();
|
|
92497
92725
|
init_errors3();
|
|
@@ -99191,6 +99419,11 @@ async function updateTaskUnlockedImpl(store, id, updates, runContext) {
|
|
|
99191
99419
|
} else if (updates.pausedReason !== void 0) {
|
|
99192
99420
|
task.pausedReason = updates.pausedReason;
|
|
99193
99421
|
}
|
|
99422
|
+
if (updates.wedgeNotification === null) {
|
|
99423
|
+
task.wedgeNotification = void 0;
|
|
99424
|
+
} else if (updates.wedgeNotification !== void 0) {
|
|
99425
|
+
task.wedgeNotification = updates.wedgeNotification;
|
|
99426
|
+
}
|
|
99194
99427
|
if (updates.tokenBudgetSoftAlertedAt === null) {
|
|
99195
99428
|
task.tokenBudgetSoftAlertedAt = void 0;
|
|
99196
99429
|
} else if (updates.tokenBudgetSoftAlertedAt !== void 0) {
|
|
@@ -99853,7 +100086,7 @@ var init_store = __esm({
|
|
|
99853
100086
|
init_task_store_helpers();
|
|
99854
100087
|
init_task_row_mappers();
|
|
99855
100088
|
init_task_mutation_ops();
|
|
99856
|
-
|
|
100089
|
+
init_project_store_ops();
|
|
99857
100090
|
init_workflow_integrity();
|
|
99858
100091
|
init_branch_group_ops();
|
|
99859
100092
|
init_archive_lifecycle_2();
|
|
@@ -100717,6 +100950,26 @@ var init_store = __esm({
|
|
|
100717
100950
|
async updateTask(id, updates, runContext) {
|
|
100718
100951
|
return updateTaskImpl(this, id, updates, runContext);
|
|
100719
100952
|
}
|
|
100953
|
+
/**
|
|
100954
|
+
* Atomically opens or resolves the durable task-wedge episode. The task lock is
|
|
100955
|
+
* shared by SQLite and PostgreSQL persistence writes, so concurrent engine
|
|
100956
|
+
* observers cannot allocate two episodes for one active normalized reason.
|
|
100957
|
+
*/
|
|
100958
|
+
async claimTaskWedgeNotificationEpisode(taskId, reasonKey) {
|
|
100959
|
+
let result = { claimed: false };
|
|
100960
|
+
await this.updateTaskAtomic(taskId, (current) => {
|
|
100961
|
+
const prior = current.wedgeNotification;
|
|
100962
|
+
if (reasonKey === null) {
|
|
100963
|
+
if (!prior || prior.status === "resolved") return null;
|
|
100964
|
+
return { wedgeNotification: { ...prior, status: "resolved", transitionedAt: (/* @__PURE__ */ new Date()).toISOString() } };
|
|
100965
|
+
}
|
|
100966
|
+
if (prior?.status === "active" && prior.reasonKey === reasonKey) return null;
|
|
100967
|
+
const episodeId = randomUUID37();
|
|
100968
|
+
result = { episodeId, claimed: true };
|
|
100969
|
+
return { wedgeNotification: { reasonKey, episodeId, status: "active", transitionedAt: (/* @__PURE__ */ new Date()).toISOString() } };
|
|
100970
|
+
});
|
|
100971
|
+
return result;
|
|
100972
|
+
}
|
|
100720
100973
|
async claimNextToolFailureRetry(taskId, expectedCursor, maxRetries) {
|
|
100721
100974
|
return claimNextToolFailureRetryImpl(this, taskId, expectedCursor, maxRetries);
|
|
100722
100975
|
}
|
|
@@ -163344,6 +163597,7 @@ var init_ntfy_provider = __esm({
|
|
|
163344
163597
|
"in-review",
|
|
163345
163598
|
"merged",
|
|
163346
163599
|
"failed",
|
|
163600
|
+
"task-wedged",
|
|
163347
163601
|
"awaiting-approval",
|
|
163348
163602
|
"awaiting-user-review",
|
|
163349
163603
|
"planning-awaiting-input",
|
|
@@ -163447,6 +163701,15 @@ var init_ntfy_provider = __esm({
|
|
|
163447
163701
|
message: `Task "${identifier}" has failed and needs attention`,
|
|
163448
163702
|
priority: "high"
|
|
163449
163703
|
},
|
|
163704
|
+
"task-wedged": {
|
|
163705
|
+
title: `Task ${taskId} needs operator action`,
|
|
163706
|
+
message: [
|
|
163707
|
+
`Task "${identifier}" is wedged${typeof payload.metadata?.reason === "string" ? `: ${payload.metadata.reason}` : " and needs operator action"}`,
|
|
163708
|
+
typeof payload.metadata?.gate === "string" ? `Gate: ${payload.metadata.gate}` : null,
|
|
163709
|
+
typeof payload.metadata?.action === "string" ? `Recommended action: ${payload.metadata.action}` : null
|
|
163710
|
+
].filter((part) => part !== null).join("\n"),
|
|
163711
|
+
priority: "high"
|
|
163712
|
+
},
|
|
163450
163713
|
"awaiting-approval": {
|
|
163451
163714
|
title: payload.metadata?.awaitingApprovalReason === "plan-review-replan-cap" ? `Plan Review cap reached for ${taskId}` : `Plan needs approval for ${taskId}`,
|
|
163452
163715
|
/*
|
|
@@ -163801,6 +164064,132 @@ var init_transient_merge_error_classifier = __esm({
|
|
|
163801
164064
|
}
|
|
163802
164065
|
});
|
|
163803
164066
|
|
|
164067
|
+
// ../engine/src/notification/task-wedge-notification.ts
|
|
164068
|
+
function describeSelfHealingNoActionWedge(task, stage, metadata) {
|
|
164069
|
+
const description = SELF_HEALING_NO_ACTIONS[stage];
|
|
164070
|
+
if (!description || task.userPaused || task.paused || task.autoMerge === false) return null;
|
|
164071
|
+
const proof = metadata ?? {};
|
|
164072
|
+
if (proof.taskActive === true || proof.hasExecutingTaskLock === true || proof.mergePending === true) return null;
|
|
164073
|
+
if (Array.isArray(proof.livePaths) && proof.livePaths.length > 0) return null;
|
|
164074
|
+
return { reasonKey: `self-healing-no-action:${stage}`, ...description };
|
|
164075
|
+
}
|
|
164076
|
+
function describeTaskWedge(task) {
|
|
164077
|
+
const error2 = task.error ?? "";
|
|
164078
|
+
if (task.pausedReason === "completed-blocked") {
|
|
164079
|
+
return { reasonKey: "completion-blocked", reason: "Completed work is blocked from advancing to review.", action: "Clear the blocker or reset the task to todo." };
|
|
164080
|
+
}
|
|
164081
|
+
if (task.pausedReason === "error-retry-exhausted") {
|
|
164082
|
+
return { reasonKey: "heartbeat-retry-exhausted", reason: "The assigned agent exhausted its heartbeat recovery budget.", action: "Repair the agent configuration, then retry the task." };
|
|
164083
|
+
}
|
|
164084
|
+
if (task.pausedReason === "error-unrecoverable") {
|
|
164085
|
+
return { reasonKey: "heartbeat-error-unrecoverable", reason: "The assigned agent needs operator repair before it can resume.", action: "Repair credentials, access, or configuration, then retry the task." };
|
|
164086
|
+
}
|
|
164087
|
+
const pausedDescriptors = {
|
|
164088
|
+
"branch-cross-contamination": { reasonKey: "branch-cross-contamination", reason: "Branch contamination recovery requires operator intervention.", action: "Inspect the branch history, repair the contamination, then retry or reset to todo." },
|
|
164089
|
+
"branch-conflict-tripwire": { reasonKey: "branch-conflict-tripwire", reason: "A repeated branch conflict stopped automatic recovery.", action: "Resolve the branch conflict, then retry or reset to todo." },
|
|
164090
|
+
"branch-conflict-recovery-exhausted": { reasonKey: "branch-conflict-recovery-exhausted", reason: "Branch conflict recovery retries were exhausted.", action: "Resolve the conflict, then retry or reset to todo." },
|
|
164091
|
+
"branch-conflict-unrecoverable": { reasonKey: "branch-conflict-unrecoverable", reason: "An unrecoverable branch conflict needs operator intervention.", action: "Resolve the conflict or reset the task to todo and retry." },
|
|
164092
|
+
"stuck-loop-exhausted-manual-intervention-required": { reasonKey: "stuck-loop-exhausted", reason: "Self-healing exhausted its stalled-task recovery loop.", action: "Inspect the task state, then retry or reset to todo." },
|
|
164093
|
+
"non-retryable-provider-error": { reasonKey: "non-retryable-provider-error", reason: "A non-retryable provider error stopped the task.", action: "Repair provider access or configuration, then retry the task." },
|
|
164094
|
+
"in-review-stall-deadlock": { reasonKey: "in-review-stall-deadlock", reason: "Review stalled in a deadlock that needs operator intervention.", action: "Inspect review ownership and retry or reset to todo." }
|
|
164095
|
+
};
|
|
164096
|
+
if (task.pausedReason && pausedDescriptors[task.pausedReason]) return pausedDescriptors[task.pausedReason];
|
|
164097
|
+
if (task.status !== "failed") return null;
|
|
164098
|
+
if (error2.startsWith("EXECUTION_DISPATCH_LOOP_EXHAUSTED")) {
|
|
164099
|
+
return { reasonKey: "execution-dispatch-loop-exhausted", reason: "Execution re-queued without progress until its retry budget was exhausted.", action: "Retry, decompose, or rescope the task." };
|
|
164100
|
+
}
|
|
164101
|
+
if (error2.includes("tool failure") || error2.includes("Tool failure")) {
|
|
164102
|
+
return { reasonKey: "tool-failure-retry-exhausted", reason: "Execution tool-failure retries were exhausted.", action: "Inspect the failing tool and retry the task." };
|
|
164103
|
+
}
|
|
164104
|
+
if (/escalat(?:ion|ed).*exhaust|exhaust.*escalat/i.test(error2)) {
|
|
164105
|
+
return { reasonKey: "execution-escalation-exhausted", reason: "The alternate execution escalation was exhausted.", action: "Inspect the failure and retry or rescope the task." };
|
|
164106
|
+
}
|
|
164107
|
+
if (/review.*(?:retry|rework|revision).*(?:exhaust|limit)|(?:exhaust|limit).*review/i.test(error2)) {
|
|
164108
|
+
return { reasonKey: "review-retry-exhausted", reason: "The configured review recovery budget was exhausted.", action: "Review the feedback, fix the task, or use the approved review recovery action." };
|
|
164109
|
+
}
|
|
164110
|
+
const gate = error2.match(/check:([\w:-]+)/)?.[1];
|
|
164111
|
+
if (gate) {
|
|
164112
|
+
return {
|
|
164113
|
+
reasonKey: `merge-blocked:${gate}`,
|
|
164114
|
+
reason: `Merge is blocked by the check:${gate} verification gate.`,
|
|
164115
|
+
action: gate === "changeset-format" ? "Fix the changeset format, then retry the task." : "Fix the failing gate or reset the task to todo and retry.",
|
|
164116
|
+
gate: `check:${gate}`
|
|
164117
|
+
};
|
|
164118
|
+
}
|
|
164119
|
+
if (error2.startsWith("BLOCKED:")) {
|
|
164120
|
+
return { reasonKey: "execution-blocked", reason: "Execution was parked because an external blocker requires operator action.", action: "Resolve the dependency or blocker, then retry the task." };
|
|
164121
|
+
}
|
|
164122
|
+
if (/merge.*(?:blocked|verification|gate)|(?:verification|gate).*(?:failed|exhaust)/i.test(error2)) {
|
|
164123
|
+
return { reasonKey: "merge-blocked", reason: "Merge verification cannot progress without operator action.", action: "Fix the failing verification, then retry the task." };
|
|
164124
|
+
}
|
|
164125
|
+
if (!error2 && (task.mergeRetries ?? 0) < 3) return null;
|
|
164126
|
+
return {
|
|
164127
|
+
reasonKey: "terminal-failed",
|
|
164128
|
+
reason: "The task entered a terminal failed state and needs operator intervention.",
|
|
164129
|
+
action: "Inspect the task error, fix the underlying issue, then retry or reset to todo."
|
|
164130
|
+
};
|
|
164131
|
+
}
|
|
164132
|
+
var SELF_HEALING_NO_ACTIONS;
|
|
164133
|
+
var init_task_wedge_notification = __esm({
|
|
164134
|
+
"../engine/src/notification/task-wedge-notification.ts"() {
|
|
164135
|
+
"use strict";
|
|
164136
|
+
SELF_HEALING_NO_ACTIONS = {
|
|
164137
|
+
"reclaim-pr-conflict": {
|
|
164138
|
+
reason: "Self-healing could not reclaim a stalled pull-request conflict.",
|
|
164139
|
+
action: "Inspect the branch conflict and retry or reset the task to todo."
|
|
164140
|
+
},
|
|
164141
|
+
"reclaim-self-owned-branch-conflict": {
|
|
164142
|
+
reason: "Self-healing could not recover a stalled branch conflict.",
|
|
164143
|
+
action: "Inspect the branch conflict and retry or reset the task to todo."
|
|
164144
|
+
},
|
|
164145
|
+
"reconcile-in-review-unmet-dependencies": {
|
|
164146
|
+
reason: "Unmet dependencies are preventing review from progressing.",
|
|
164147
|
+
action: "Resolve the dependencies, then retry or reset the task to todo."
|
|
164148
|
+
},
|
|
164149
|
+
"reconcile-dependency-blocking-lease": {
|
|
164150
|
+
reason: "A dependency-blocking task lease could not be safely reclaimed.",
|
|
164151
|
+
action: "Inspect the task owner and lease, then retry or reset the task to todo."
|
|
164152
|
+
},
|
|
164153
|
+
"auto-rebound-paused-scope-decay": {
|
|
164154
|
+
reason: "A paused task with stale scope could not be safely resumed.",
|
|
164155
|
+
action: "Inspect the task scope and retry or reset the task to todo."
|
|
164156
|
+
},
|
|
164157
|
+
"stuck-merge-deadlock": {
|
|
164158
|
+
reason: "A merge deadlock needs operator intervention.",
|
|
164159
|
+
action: "Inspect merge ownership and retry or reset the task to todo."
|
|
164160
|
+
},
|
|
164161
|
+
"missing-worktree-merge-active": {
|
|
164162
|
+
reason: "An active merge has an unusable worktree and could not be recovered.",
|
|
164163
|
+
action: "Repair the worktree or reset the task to todo and retry."
|
|
164164
|
+
},
|
|
164165
|
+
"missing-worktree-review": {
|
|
164166
|
+
reason: "Review has an unusable worktree and could not be recovered.",
|
|
164167
|
+
action: "Repair the worktree or reset the task to todo and retry."
|
|
164168
|
+
},
|
|
164169
|
+
"finalize-no-op-review": {
|
|
164170
|
+
reason: "A no-op review task could not be safely finalized.",
|
|
164171
|
+
action: "Inspect merge state and retry or reset the task to todo."
|
|
164172
|
+
},
|
|
164173
|
+
"stale-incomplete-review": {
|
|
164174
|
+
reason: "Incomplete review work could not be safely resumed.",
|
|
164175
|
+
action: "Inspect incomplete steps and retry or reset the task to todo."
|
|
164176
|
+
},
|
|
164177
|
+
"ghost-review": {
|
|
164178
|
+
reason: "A review task has no recoverable workflow owner.",
|
|
164179
|
+
action: "Inspect workflow state and retry or reset the task to todo."
|
|
164180
|
+
},
|
|
164181
|
+
"no-progress-no-task-done": {
|
|
164182
|
+
reason: "Execution stopped without progress and could not be safely requeued.",
|
|
164183
|
+
action: "Inspect the task worktree and retry or reset the task to todo."
|
|
164184
|
+
},
|
|
164185
|
+
"partial-progress-no-task-done": {
|
|
164186
|
+
reason: "Partial execution progress could not be safely resumed.",
|
|
164187
|
+
action: "Inspect partial work and retry or reset the task to todo."
|
|
164188
|
+
}
|
|
164189
|
+
};
|
|
164190
|
+
}
|
|
164191
|
+
});
|
|
164192
|
+
|
|
163804
164193
|
// ../engine/src/notification/notification-service.ts
|
|
163805
164194
|
var NotificationService;
|
|
163806
164195
|
var init_notification_service = __esm({
|
|
@@ -163812,6 +164201,7 @@ var init_notification_service = __esm({
|
|
|
163812
164201
|
init_transient_merge_error_classifier();
|
|
163813
164202
|
init_ntfy_provider();
|
|
163814
164203
|
init_webhook_provider();
|
|
164204
|
+
init_task_wedge_notification();
|
|
163815
164205
|
NotificationService = class {
|
|
163816
164206
|
constructor(store, options = {}) {
|
|
163817
164207
|
this.store = store;
|
|
@@ -163842,6 +164232,8 @@ var init_notification_service = __esm({
|
|
|
163842
164232
|
failureNotificationSuppressedCount = 0;
|
|
163843
164233
|
failureNotificationDelayMs = 6e4;
|
|
163844
164234
|
failureNotificationMode = "sticky-only";
|
|
164235
|
+
/** Compatibility fallback for lightweight test stores without the durable TaskStore CAS. */
|
|
164236
|
+
activeWedgeReasons = /* @__PURE__ */ new Map();
|
|
163845
164237
|
attachChatStore(chatStore) {
|
|
163846
164238
|
if (this.chatStore && this.chatStore !== chatStore) {
|
|
163847
164239
|
this.detachChatStoreListener(this.chatStore);
|
|
@@ -163953,6 +164345,10 @@ var init_notification_service = __esm({
|
|
|
163953
164345
|
}
|
|
163954
164346
|
}
|
|
163955
164347
|
handleTaskUpdated = (task) => {
|
|
164348
|
+
const transientFailure = task.status === "failed" ? classifyTransientMergeError(task.error) : null;
|
|
164349
|
+
const wedge = transientFailure ? null : describeTaskWedge(task);
|
|
164350
|
+
if (wedge) this.cancelPendingFailureNotification(task.id, "classified-terminal-wedge");
|
|
164351
|
+
if (!transientFailure) void this.maybeNotifyTaskWedge(task, wedge);
|
|
163956
164352
|
void this.maybeSuppressTransientFailedNotification(task, `status=${task.status ?? "undefined"}`);
|
|
163957
164353
|
if (task.status === "awaiting-approval") {
|
|
163958
164354
|
void this.writeAwaitingApprovalMailboxMessage(task);
|
|
@@ -163963,7 +164359,7 @@ var init_notification_service = __esm({
|
|
|
163963
164359
|
if (!this.notificationsEnabled) {
|
|
163964
164360
|
return;
|
|
163965
164361
|
}
|
|
163966
|
-
if (task.status === "failed") {
|
|
164362
|
+
if (task.status === "failed" && !wedge) {
|
|
163967
164363
|
const transientClass = classifyTransientMergeError(task.error);
|
|
163968
164364
|
if (transientClass) {
|
|
163969
164365
|
this.failureNotificationSuppressedCount += 1;
|
|
@@ -164049,6 +164445,69 @@ var init_notification_service = __esm({
|
|
|
164049
164445
|
);
|
|
164050
164446
|
}
|
|
164051
164447
|
}
|
|
164448
|
+
/*
|
|
164449
|
+
FNXC:TaskWedgeNotifications 2026-07-22-12:00:
|
|
164450
|
+
Terminal task updates are the shared seam for merger, executor, heartbeat, and
|
|
164451
|
+
self-healing parks. Clear only on a non-wedge lifecycle update, allowing a
|
|
164452
|
+
resolved-then-reparked reason to begin a new actionable episode.
|
|
164453
|
+
*/
|
|
164454
|
+
/** Delivers a self-healing no-action escalation through the durable wedge episode seam. */
|
|
164455
|
+
async notifyTaskWedge(task, descriptor) {
|
|
164456
|
+
await this.maybeNotifyTaskWedge(task, descriptor);
|
|
164457
|
+
}
|
|
164458
|
+
async maybeNotifyTaskWedge(task, suppliedDescriptor) {
|
|
164459
|
+
const descriptor = suppliedDescriptor ?? describeTaskWedge(task);
|
|
164460
|
+
let episode;
|
|
164461
|
+
if (!descriptor) {
|
|
164462
|
+
const isActiveSelfHealingNoAction = task.wedgeNotification?.status === "active" && task.wedgeNotification.reasonKey.startsWith("self-healing-no-action:");
|
|
164463
|
+
const hasProgressed = task.column === "todo" || task.column === "in-progress" || task.column === "done" || task.column === "archived" || !isActiveSelfHealingNoAction && typeof task.status === "string" && task.status !== "failed" || isActiveSelfHealingNoAction && ["queued", "planning", "in-progress", "merging", "merging-pr", "merged", "done"].includes(task.status ?? "");
|
|
164464
|
+
if (hasProgressed) {
|
|
164465
|
+
this.activeWedgeReasons.delete(task.id);
|
|
164466
|
+
await this.store.claimTaskWedgeNotificationEpisode?.(task.id, null);
|
|
164467
|
+
}
|
|
164468
|
+
return;
|
|
164469
|
+
}
|
|
164470
|
+
if (this.store.claimTaskWedgeNotificationEpisode) {
|
|
164471
|
+
const claim = await this.store.claimTaskWedgeNotificationEpisode(task.id, descriptor.reasonKey);
|
|
164472
|
+
if (!claim.claimed || !claim.episodeId) return;
|
|
164473
|
+
episode = claim.episodeId;
|
|
164474
|
+
} else {
|
|
164475
|
+
if (this.activeWedgeReasons.get(task.id) === descriptor.reasonKey) return;
|
|
164476
|
+
this.activeWedgeReasons.set(task.id, descriptor.reasonKey);
|
|
164477
|
+
episode = `${task.id}:${descriptor.reasonKey}:${task.updatedAt}`;
|
|
164478
|
+
}
|
|
164479
|
+
const link = buildNtfyClickUrl({ dashboardHost: this.dashboardHost, projectId: this.options.projectId, taskId: task.id });
|
|
164480
|
+
const content = [
|
|
164481
|
+
`**${formatTaskIdentifier(task)} needs operator action**`,
|
|
164482
|
+
"",
|
|
164483
|
+
descriptor.reason,
|
|
164484
|
+
...descriptor.gate ? [`Gate: \`${descriptor.gate}\`.`] : [],
|
|
164485
|
+
`Recommended action: ${descriptor.action}`,
|
|
164486
|
+
...link ? ["", `[Open ${task.id}](${link})`] : []
|
|
164487
|
+
].join("\n");
|
|
164488
|
+
const payload = {
|
|
164489
|
+
taskId: task.id,
|
|
164490
|
+
taskTitle: task.title,
|
|
164491
|
+
taskDescription: task.description,
|
|
164492
|
+
event: "task-wedged",
|
|
164493
|
+
// Bounded descriptor text is operator-facing provider content, never audit metadata.
|
|
164494
|
+
metadata: { wedgeReason: descriptor.reasonKey, reason: descriptor.reason, action: descriptor.action, ...descriptor.gate ? { gate: descriptor.gate } : {}, notificationDedupeKey: `task-wedge:${episode}` }
|
|
164495
|
+
};
|
|
164496
|
+
void this.dispatch("task-wedged", payload);
|
|
164497
|
+
try {
|
|
164498
|
+
await this.options.messageStore?.sendMessageOnce?.({
|
|
164499
|
+
fromId: "system",
|
|
164500
|
+
fromType: "system",
|
|
164501
|
+
toId: DASHBOARD_USER_ID,
|
|
164502
|
+
toType: "user",
|
|
164503
|
+
type: "system",
|
|
164504
|
+
content,
|
|
164505
|
+
metadata: { taskId: task.id, kind: "task-wedge", wedgeReason: descriptor.reasonKey, ...descriptor.gate ? { gate: descriptor.gate } : {} }
|
|
164506
|
+
}, `task-wedge:${episode}`);
|
|
164507
|
+
} catch (error2) {
|
|
164508
|
+
schedulerLog.log(`[notify] ${task.id} wedge mailbox message failed: ${error2 instanceof Error ? error2.message : String(error2)}`);
|
|
164509
|
+
}
|
|
164510
|
+
}
|
|
164052
164511
|
isTriageDuplicateDecision(task) {
|
|
164053
164512
|
return task.paused === true && task.pausedReason === "duplicate-decision-required" && task.sourceMetadata?.duplicateSource === "triage-marker" && typeof task.sourceMetadata.nearDuplicateOf === "string";
|
|
164054
164513
|
}
|
|
@@ -164414,6 +164873,11 @@ var init_notification_service = __esm({
|
|
|
164414
164873
|
);
|
|
164415
164874
|
return;
|
|
164416
164875
|
}
|
|
164876
|
+
if (describeTaskWedge(task)) {
|
|
164877
|
+
this.failureNotificationSuppressedCount += 1;
|
|
164878
|
+
schedulerLog.log(`[notify] ${taskId} classified terminal wedge at dispatch time \u2014 suppressed generic failed notification`);
|
|
164879
|
+
return;
|
|
164880
|
+
}
|
|
164417
164881
|
const isTerminal2 = task.paused === true || task.column === "in-review";
|
|
164418
164882
|
if (this.failureNotificationMode === "terminal-only" && !isTerminal2) {
|
|
164419
164883
|
this.failureNotificationSuppressedCount += 1;
|
|
@@ -165242,7 +165706,10 @@ var init_notifier = __esm({
|
|
|
165242
165706
|
DEFAULT_NTFY_EVENTS = [
|
|
165243
165707
|
"in-review",
|
|
165244
165708
|
"merged",
|
|
165709
|
+
// FNXC:TaskWedgeNotifications 2026-07-22-19:00: Wedge episodes are operator
|
|
165710
|
+
// escalation events, so normal Ntfy defaults must not silently filter them.
|
|
165245
165711
|
"failed",
|
|
165712
|
+
"task-wedged",
|
|
165246
165713
|
"awaiting-approval",
|
|
165247
165714
|
"awaiting-user-review",
|
|
165248
165715
|
"planning-awaiting-input",
|
|
@@ -205139,6 +205606,9 @@ var DependencyBlockedTodoReporter = class {
|
|
|
205139
205606
|
}
|
|
205140
205607
|
};
|
|
205141
205608
|
|
|
205609
|
+
// ../engine/src/self-healing.ts
|
|
205610
|
+
init_task_wedge_notification();
|
|
205611
|
+
|
|
205142
205612
|
// ../engine/src/self-healing-constants.ts
|
|
205143
205613
|
var COMPLETED_BLOCKED_PAUSE_REASON = "completed-work-blocked";
|
|
205144
205614
|
var STALE_TEMP_MERGE_WORKTREE_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -205779,6 +206249,15 @@ var SelfHealingManager = class _SelfHealingManager {
|
|
|
205779
206249
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
205780
206250
|
log28.warn(`[${stage}] ${task.id}: no-action audit emission failed: ${message}`);
|
|
205781
206251
|
}
|
|
206252
|
+
const descriptor = describeSelfHealingNoActionWedge(task, stage, proof.metadata);
|
|
206253
|
+
if (descriptor) {
|
|
206254
|
+
try {
|
|
206255
|
+
await getActiveNotificationService()?.notifyTaskWedge(task, descriptor);
|
|
206256
|
+
} catch (error2) {
|
|
206257
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
206258
|
+
log28.warn(`[${stage}] ${task.id}: wedge notification failed: ${message}`);
|
|
206259
|
+
}
|
|
206260
|
+
}
|
|
205782
206261
|
log28.log(`[${stage}] ${task.id}: triple-proof not satisfied \u2014 no action (operator-decides)`);
|
|
205783
206262
|
}
|
|
205784
206263
|
/*
|