@runfusion/fusion 0.43.1 → 0.44.0

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.
Files changed (168) hide show
  1. package/dist/automation-store-EKXXEE2S.js +10 -0
  2. package/dist/automation-store-PLNG3X72.js +10 -0
  3. package/dist/automation-store-RDDYZFUJ.js +10 -0
  4. package/dist/bin.js +8097 -1796
  5. package/dist/chunk-2JI3F6MG.js +948 -0
  6. package/dist/chunk-4L6CLWJC.js +8345 -0
  7. package/dist/chunk-4VNS5WPM.js +42 -0
  8. package/dist/chunk-5RGECGQL.js +1139 -0
  9. package/dist/chunk-6JDLN7IL.js +409 -0
  10. package/dist/chunk-AICJATVW.js +948 -0
  11. package/dist/chunk-AWKNRUOR.js +1148 -0
  12. package/dist/chunk-BHM3UYWS.js +4651 -0
  13. package/dist/chunk-BMUXDSBF.js +4647 -0
  14. package/dist/chunk-GETECT6V.js +353 -0
  15. package/dist/chunk-GUV4QQT3.js +1143 -0
  16. package/dist/chunk-JKQO7YYZ.js +8369 -0
  17. package/dist/chunk-LYZVU6UV.js +409 -0
  18. package/dist/chunk-MAN4WYHO.js +353 -0
  19. package/dist/chunk-MCUG2Z7M.js +4651 -0
  20. package/dist/chunk-PSDYB45U.js +948 -0
  21. package/dist/chunk-RR2HM46R.js +8345 -0
  22. package/dist/chunk-RXMQ5OMY.js +9226 -0
  23. package/dist/chunk-S2EVJUY3.js +353 -0
  24. package/dist/chunk-UXR5XZFZ.js +409 -0
  25. package/dist/client/.vite/manifest.json +272 -261
  26. package/dist/client/assets/{AgentDetailView-BGN03dyz.css → AgentDetailView-CanIeYHg.css} +1 -1
  27. package/dist/client/assets/{AgentDetailView-DKMz3r04.js → AgentDetailView-DxV8pFHX.js} +3 -3
  28. package/dist/client/assets/{AgentPermissionPolicyEditor-BiY1a4KR.js → AgentPermissionPolicyEditor--YS4iMUY.js} +2 -2
  29. package/dist/client/assets/AgentsView-BVILQjdS.css +1 -0
  30. package/dist/client/assets/{AgentsView-Co-k4vjh.js → AgentsView-CTzbcvhK.js} +3 -3
  31. package/dist/client/assets/ChatView-COygcnyk.js +6 -0
  32. package/dist/client/assets/CommandCenter-CTaopaC0.css +1 -0
  33. package/dist/client/assets/CommandCenter-DoKX2HWm.js +56 -0
  34. package/dist/client/assets/DevServerView-Cyevyvqx.js +1 -0
  35. package/dist/client/assets/{DirectoryPicker-DTKtd8L2.css → DirectoryPicker-0rspvcMz.css} +1 -1
  36. package/dist/client/assets/{DirectoryPicker-CkcGjyv0.js → DirectoryPicker-DBdyXEhR.js} +1 -1
  37. package/dist/client/assets/DocumentsView-BzSMyrns.js +1 -0
  38. package/dist/client/assets/{EvalsView-CUfyj5GW.js → EvalsView-ikz00o9g.js} +1 -1
  39. package/dist/client/assets/ExperimentalAgentOnboardingModal-CZ_jbgep.css +1 -0
  40. package/dist/client/assets/{ExperimentalAgentOnboardingModal-Dau9RTU_.js → ExperimentalAgentOnboardingModal-D-rzCCET.js} +10 -10
  41. package/dist/client/assets/GoalsView-Bfu1Oy2-.js +2 -0
  42. package/dist/client/assets/GoalsView-rg9VSIza.css +1 -0
  43. package/dist/client/assets/{InsightsView-BQPxHxKI.js → InsightsView-Cgmf5nES.js} +1 -1
  44. package/dist/client/assets/InsightsView-LMv1M1dU.css +1 -0
  45. package/dist/client/assets/MemoryView-DkEuDKQs.js +2 -0
  46. package/dist/client/assets/{NodesView-CSMvGwDU.js → NodesView-B_KYfS4o.js} +3 -3
  47. package/dist/client/assets/{PiExtensionsManager-BtqXF3fl.js → PiExtensionsManager-Dz69kkKs.js} +2 -2
  48. package/dist/client/assets/PluginManager-DSiHizRD.css +1 -0
  49. package/dist/client/assets/{PluginManager-CSSDb3VO.js → PluginManager-LHCVcduP.js} +1 -1
  50. package/dist/client/assets/PullRequestView-3AdbS2a1.css +1 -0
  51. package/dist/client/assets/{PullRequestView-Bjyfffdu.js → PullRequestView-DBJutLLl.js} +2 -2
  52. package/dist/client/assets/{ResearchView-CRU_NPho.js → ResearchView-gpn1XcVy.js} +1 -1
  53. package/dist/client/assets/{SecretsView-Bs8ySyC5.js → SecretsView-B7YqIowt.js} +1 -1
  54. package/dist/client/assets/SessionTerminal-9l4bdKcn.js +2 -0
  55. package/dist/client/assets/SessionTerminal-BNgtmXb3.css +1 -0
  56. package/dist/client/assets/SettingsModal-BGEK9_9A.js +31 -0
  57. package/dist/client/assets/{SettingsModal-DpAxDq6M.css → SettingsModal-CKv0TJfM.css} +1 -1
  58. package/dist/client/assets/SettingsModal-CXogw-Er.css +1 -0
  59. package/dist/client/assets/{SettingsModal-Nw5cTKAK.js → SettingsModal-DIIoHGUH.js} +1 -1
  60. package/dist/client/assets/{SetupWizardModal-CE79myEy.js → SetupWizardModal-BcVeMxeX.js} +1 -1
  61. package/dist/client/assets/{SkillsView-Dc8YskAX.js → SkillsView-BxSJ4PHL.js} +1 -1
  62. package/dist/client/assets/{StashRecoveryView-CqKOFiXT.js → StashRecoveryView-BhFQ2FsP.js} +1 -1
  63. package/dist/client/assets/{TodoView-BqIRwcZw.js → TodoView-BZpewjy0.js} +2 -2
  64. package/dist/client/assets/WorkflowNodeEditor-Yn1FRF2v.css +1 -0
  65. package/dist/client/assets/WorkflowNodeEditor-tWsgCdVt.js +8 -0
  66. package/dist/client/assets/{addon-fit-B4jkcKk4.js → addon-fit-SnYDEvGm.js} +1 -1
  67. package/dist/client/assets/{addon-unicode11-Cdne2Sj4.js → addon-unicode11-s5GoZCpi.js} +1 -1
  68. package/dist/client/assets/{addon-web-links-CRNLzj7m.js → addon-web-links-jjt2f_oV.js} +1 -1
  69. package/dist/client/assets/{addon-webgl-CeCSULF1.js → addon-webgl-Icn-RnEx.js} +1 -1
  70. package/dist/client/assets/{app-sEkTyT-w.js → app-BmGA0Hiz.js} +3 -3
  71. package/dist/client/assets/{app-BffGU_HQ.js → app-CEVYlVuJ.js} +3 -3
  72. package/dist/client/assets/{app-C8AHhs5N.js → app-CbBFax2C.js} +3 -3
  73. package/dist/client/assets/{app-B2ZxMfJT.js → app-DORKrGAz.js} +3 -3
  74. package/dist/client/assets/{app-Ri9Te2Dv.js → app-DQibuQ9z.js} +3 -3
  75. package/dist/client/assets/app-k76GrQP0.js +13 -0
  76. package/dist/client/assets/{createLucideIcon-BYvOGRiO.js → createLucideIcon-DmVITl5d.js} +1 -1
  77. package/dist/client/assets/{dashboard-view-C3SsjXo1.js → dashboard-view-B4LXCv5H.js} +4 -4
  78. package/dist/client/assets/{dashboard-view-DlKsVySD.js → dashboard-view-BFoyhTYF.js} +1 -1
  79. package/dist/client/assets/{dashboard-view-BhbN8LPh.js → dashboard-view-Cxzm_eqc.js} +1 -1
  80. package/dist/client/assets/dashboard-view-_8yfNwju.css +1 -0
  81. package/dist/client/assets/{folder-open-Bw1mxVfa.js → folder-open-33WGVnbp.js} +1 -1
  82. package/dist/client/assets/index-Bglw05rM.js +791 -0
  83. package/dist/client/assets/index-FYgnflWD.css +1 -0
  84. package/dist/client/assets/shield-alert-CqeGWBUK.js +6 -0
  85. package/dist/client/assets/{upload-BCmd-1I0.js → upload-C11J2diI.js} +1 -1
  86. package/dist/client/assets/{users-DO_t3V1p.js → users-a-ELbyyZ.js} +1 -1
  87. package/dist/client/assets/{vendor-i18n-CV0mwX_-.js → vendor-i18n-DYlSUfot.js} +1 -1
  88. package/dist/client/assets/vendor-react-BTgM5bbZ.js +49 -0
  89. package/dist/client/assets/{vendor-reactflow-CRZcPCXF.js → vendor-reactflow-ZasuEfF9.js} +3 -3
  90. package/dist/client/assets/{vendor-xterm-tcedd2Jt.js → vendor-xterm-ea7-K05z.js} +1 -1
  91. package/dist/client/assets/{x-CqNX_9E2.js → x-PItWc-wQ.js} +1 -1
  92. package/dist/client/assets/{zoom-out-CSTHbJgD.js → zoom-out-CzlHv0Kj.js} +1 -1
  93. package/dist/client/icons/icon-192.png +0 -0
  94. package/dist/client/icons/icon-512.png +0 -0
  95. package/dist/client/index.html +6 -6
  96. package/dist/client/sw.js +1 -1
  97. package/dist/client/theme-data.css +288 -285
  98. package/dist/client/version.json +1 -1
  99. package/dist/droid-cli/package.json +1 -1
  100. package/dist/droid-cli/src/__tests__/execsync-guard.test.ts +17 -0
  101. package/dist/droid-cli/src/__tests__/process-manager.test.ts +1 -45
  102. package/dist/extension.js +4780 -793
  103. package/dist/extract-zip-WL55Z3AU.js +2497 -0
  104. package/dist/index.min-CHQ3ABYJ.js +2926 -0
  105. package/dist/memory-dreams-7USISKVE.js +32 -0
  106. package/dist/memory-dreams-PBPISUDD.js +32 -0
  107. package/dist/memory-dreams-XNO2B2QF.js +32 -0
  108. package/dist/migration-EH2YOCYQ.js +15 -0
  109. package/dist/migration-PLGTTKL5.js +15 -0
  110. package/dist/migration-WZEZK22R.js +15 -0
  111. package/dist/pi-claude-cli/index.ts +47 -8
  112. package/dist/pi-claude-cli/package.json +4 -1
  113. package/dist/pi-claude-cli/src/__tests__/acp-dispatch.test.ts +80 -0
  114. package/dist/pi-claude-cli/src/__tests__/acp-driver.test.ts +423 -0
  115. package/dist/pi-claude-cli/src/__tests__/execsync-guard.test.ts +14 -0
  116. package/dist/pi-claude-cli/src/__tests__/process-manager.test.ts +1 -45
  117. package/dist/pi-claude-cli/src/__tests__/provider.test.ts +0 -1
  118. package/dist/pi-claude-cli/src/acp-driver.ts +585 -0
  119. package/dist/pi-claude-cli/src/event-bridge.ts +7 -0
  120. package/dist/pi-claude-cli/src/mcp-config.ts +29 -0
  121. package/dist/pi-claude-cli/src/process-manager.ts +6 -38
  122. package/dist/plugin-sdk/index.d.ts +5179 -5144
  123. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +263 -19
  124. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  125. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  126. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +37 -7
  127. package/dist/plugins/fusion-plugin-compound-engineering/manifest.json +4 -4
  128. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  129. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  130. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  131. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +1 -1
  132. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  133. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  134. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  135. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  136. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  137. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  138. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  139. package/dist/plugins/fusion-plugin-whatsapp-chat/src/__tests__/index.test.ts +5 -1
  140. package/dist/routine-store-GIJ6MXWY.js +10 -0
  141. package/dist/routine-store-HTVC2PUQ.js +10 -0
  142. package/dist/routine-store-KGHZBPDF.js +10 -0
  143. package/package.json +1 -1
  144. package/skill/fusion/references/engine-tools.md +6 -4
  145. package/dist/client/assets/AgentsView-DfznJDek.css +0 -1
  146. package/dist/client/assets/ChatView-BkAG99bj.js +0 -6
  147. package/dist/client/assets/DevServerView-C6DC0URX.js +0 -1
  148. package/dist/client/assets/DocumentsView-OCK1Vsw_.js +0 -1
  149. package/dist/client/assets/ExperimentalAgentOnboardingModal-BNpveCEk.css +0 -1
  150. package/dist/client/assets/GoalsView-CNLTn0rX.js +0 -2
  151. package/dist/client/assets/GoalsView-DI66UsjT.css +0 -1
  152. package/dist/client/assets/InsightsView-C9-mqVvf.css +0 -1
  153. package/dist/client/assets/MemoryView-D3xQIFjj.js +0 -2
  154. package/dist/client/assets/PluginManager-UHVLvWWl.css +0 -1
  155. package/dist/client/assets/PullRequestView-WQIS0zUC.css +0 -1
  156. package/dist/client/assets/ReliabilityView-QKMUDebT.js +0 -1
  157. package/dist/client/assets/ReliabilityView-eoKBhBc4.css +0 -1
  158. package/dist/client/assets/SessionTerminal-BiigPP2l.css +0 -1
  159. package/dist/client/assets/SessionTerminal-Dk1NgmN2.js +0 -2
  160. package/dist/client/assets/SettingsModal-JCaNvdAb.js +0 -31
  161. package/dist/client/assets/SettingsModal-nF_GaeeK.css +0 -1
  162. package/dist/client/assets/WorkflowNodeEditor-2jDuk2FR.js +0 -8
  163. package/dist/client/assets/WorkflowNodeEditor-BokhW3de.css +0 -1
  164. package/dist/client/assets/app-CUu1sm3x.js +0 -13
  165. package/dist/client/assets/dashboard-view-Du53JbmQ.css +0 -1
  166. package/dist/client/assets/index-CpTBp1RG.js +0 -793
  167. package/dist/client/assets/index-DqhCiU35.css +0 -1
  168. package/dist/client/assets/vendor-react-D37HfzIf.js +0 -49
@@ -0,0 +1,1148 @@
1
+ // ../core/dist/settings-schema.js
2
+ var DEFAULT_GLOBAL_SETTINGS = {
3
+ themeMode: "dark",
4
+ colorTheme: "default",
5
+ dashboardFontScalePct: 100,
6
+ language: void 0,
7
+ defaultProvider: void 0,
8
+ defaultModelId: void 0,
9
+ testMode: void 0,
10
+ mergeRequestContractShadowEnabled: false,
11
+ fallbackProvider: void 0,
12
+ fallbackModelId: void 0,
13
+ defaultThinkingLevel: void 0,
14
+ ntfyEnabled: false,
15
+ ntfyTopic: void 0,
16
+ ntfyBaseUrl: void 0,
17
+ ntfyAccessToken: void 0,
18
+ ntfyEvents: [
19
+ "in-review",
20
+ "merged",
21
+ "failed",
22
+ "awaiting-approval",
23
+ "awaiting-user-review",
24
+ "planning-awaiting-input",
25
+ "message:agent-to-user",
26
+ "message:agent-to-agent",
27
+ "message:room",
28
+ "gridlock",
29
+ "board-stall-unrecovered",
30
+ "fallback-used",
31
+ "memory-dreams-processed",
32
+ "token-budget"
33
+ ],
34
+ ntfyDashboardHost: void 0,
35
+ taskTokenBudget: void 0,
36
+ failureNotificationDelayMs: 3e4,
37
+ failureNotificationMode: "sticky-only",
38
+ webhookEnabled: false,
39
+ webhookUrl: void 0,
40
+ webhookFormat: "generic",
41
+ webhookEvents: [],
42
+ notificationProviders: [],
43
+ customProviders: [],
44
+ defaultProjectId: void 0,
45
+ setupComplete: void 0,
46
+ cliOnboardingCompletedAt: void 0,
47
+ favoriteProviders: void 0,
48
+ favoriteModels: void 0,
49
+ openrouterModelSync: true,
50
+ openrouterAppAttribution: void 0,
51
+ openrouterModelFilters: void 0,
52
+ openrouterProviderPreferences: void 0,
53
+ opencodeGoModelSync: true,
54
+ updateCheckEnabled: true,
55
+ fnBinaryCheckEnabled: true,
56
+ updateCheckFrequency: "daily",
57
+ autoReloadOnVersionChange: true,
58
+ githubTrackingDefaultRepo: void 0,
59
+ modelOnboardingComplete: void 0,
60
+ useClaudeCli: void 0,
61
+ useDroidCli: void 0,
62
+ useLlamaCpp: void 0,
63
+ // Global baseline lanes for per-role model selection
64
+ executionGlobalProvider: void 0,
65
+ executionGlobalModelId: void 0,
66
+ planningGlobalProvider: void 0,
67
+ planningGlobalModelId: void 0,
68
+ validatorGlobalProvider: void 0,
69
+ validatorGlobalModelId: void 0,
70
+ titleSummarizerGlobalProvider: void 0,
71
+ titleSummarizerGlobalModelId: void 0,
72
+ // Daemon mode settings
73
+ daemonToken: void 0,
74
+ daemonPort: 4040,
75
+ daemonHost: "127.0.0.1",
76
+ // Node settings sync
77
+ settingsSyncEnabled: false,
78
+ settingsSyncAuth: false,
79
+ settingsSyncInterval: 9e5,
80
+ settingsSyncConflictResolution: "last-write-wins",
81
+ // Dashboard session state (persisted to global settings for PWA/offline restore)
82
+ dashboardCurrentNodeId: void 0,
83
+ dashboardCurrentProjectIdByNode: void 0,
84
+ // Dashboard TUI memory guard
85
+ vitestAutoKillEnabled: true,
86
+ vitestKillThresholdPct: 90,
87
+ // Agent log persistence controls
88
+ persistAgentToolOutput: true,
89
+ persistAgentThinkingLogPermanent: false,
90
+ persistAgentThinkingLogEphemeral: false,
91
+ persistAgentThinkingLog: false,
92
+ agentMemoryInclusionMode: "full",
93
+ secretsAccessPolicy: void 0,
94
+ secretsSyncPassphraseConfigured: false,
95
+ researchGlobalDefaults: {
96
+ searchProvider: void 0,
97
+ synthesisProvider: void 0,
98
+ synthesisModelId: void 0,
99
+ enabledSources: {
100
+ webSearch: true,
101
+ pageFetch: true,
102
+ github: false,
103
+ localDocs: true,
104
+ llmSynthesis: true
105
+ },
106
+ maxSourcesPerRun: 20,
107
+ defaultExportFormat: "markdown"
108
+ },
109
+ researchGlobalEnabled: true,
110
+ researchGlobalMaxConcurrentRuns: 3,
111
+ researchGlobalDefaultTimeout: 3e5,
112
+ researchGlobalMaxSourcesPerRun: 20,
113
+ researchGlobalMaxSynthesisRounds: 2,
114
+ researchGlobalWebSearchProvider: "builtin",
115
+ researchGlobalSearxngUrl: void 0,
116
+ researchGlobalBraveApiKey: void 0,
117
+ researchGlobalGoogleSearchApiKey: void 0,
118
+ researchGlobalGoogleSearchCx: void 0,
119
+ researchGlobalTavilyApiKey: void 0,
120
+ researchGlobalGitHubEnabled: false,
121
+ researchGlobalLocalDocsEnabled: true,
122
+ researchGlobalMaxSearchResults: 10,
123
+ researchGlobalFetchTimeoutMs: 3e4,
124
+ researchGlobalUserAgent: "FusionResearchBot/1.0",
125
+ remoteAccess: {
126
+ activeProvider: null,
127
+ providers: {
128
+ tailscale: {
129
+ enabled: false,
130
+ hostname: "",
131
+ targetPort: 0,
132
+ acceptRoutes: false
133
+ },
134
+ cloudflare: {
135
+ enabled: false,
136
+ quickTunnel: true,
137
+ tunnelName: "",
138
+ tunnelToken: null,
139
+ ingressUrl: ""
140
+ }
141
+ },
142
+ tokenStrategy: {
143
+ persistent: {
144
+ enabled: true,
145
+ token: null
146
+ },
147
+ shortLived: {
148
+ enabled: false,
149
+ ttlMs: 9e5,
150
+ maxTtlMs: 864e5
151
+ }
152
+ },
153
+ lifecycle: {
154
+ rememberLastRunning: false,
155
+ wasRunningOnShutdown: false,
156
+ lastRunningProvider: null
157
+ }
158
+ },
159
+ worktrunk: {
160
+ enabled: false,
161
+ binaryPath: void 0,
162
+ installedBinaryPath: void 0,
163
+ onFailure: "fail"
164
+ },
165
+ owningNodeHandoffPolicy: "reassign-to-local",
166
+ experimentalFeatures: {
167
+ workflowColumns: true,
168
+ workflowGraphExecutor: true,
169
+ workflowInterpreterDualObserve: true,
170
+ workflowInterpreterAuthoritative: true
171
+ },
172
+ cliAgents: {}
173
+ };
174
+ var DEFAULT_PROJECT_SETTINGS = {
175
+ globalPause: false,
176
+ globalPauseReason: void 0,
177
+ defaultWorkflowId: void 0,
178
+ enabledBuiltinWorkflowIds: void 0,
179
+ approvedWorkflowCliCommands: void 0,
180
+ approvedCliAutonomyAdapters: void 0,
181
+ enginePaused: false,
182
+ maxConcurrent: 2,
183
+ maxTriageConcurrent: 2,
184
+ globalMaxConcurrent: 4,
185
+ maxWorktrees: 4,
186
+ pollIntervalMs: 15e3,
187
+ heartbeatMultiplier: 1,
188
+ autoClaimCandidatesInPrompt: 5,
189
+ tombstoneStickyWindowDays: 7,
190
+ heartbeatScopeDiscipline: "strict",
191
+ heartbeatPromptTemplate: "default",
192
+ groupOverlappingFiles: true,
193
+ overlapIgnorePaths: [],
194
+ autoMerge: true,
195
+ testMode: void 0,
196
+ mergeRequestContractShadowEnabled: false,
197
+ mergeStrategy: "direct",
198
+ directMergeCommitStrategy: "always-squash",
199
+ mergeIntegrationWorktree: "reuse-task-worktree",
200
+ mergeAdvanceAutoSync: "stash-and-ff",
201
+ integrationBranch: void 0,
202
+ // `requirePrApproval` MOVED to workflow settings (U4) — see MOVED_SETTINGS_KEYS.
203
+ pushAfterMerge: false,
204
+ pushRemote: "origin",
205
+ unavailableNodePolicy: "block",
206
+ owningNodeHandoffPolicy: "reassign-to-local",
207
+ defaultNodeId: void 0,
208
+ secretsEnv: void 0,
209
+ worktreeInitCommand: void 0,
210
+ testCommand: void 0,
211
+ buildCommand: void 0,
212
+ recycleWorktrees: false,
213
+ executorAllowSiblingBranchRename: false,
214
+ worktreeNaming: "random",
215
+ worktrunk: {
216
+ enabled: false,
217
+ binaryPath: void 0,
218
+ installedBinaryPath: void 0,
219
+ onFailure: "fail"
220
+ },
221
+ worktreesDir: void 0,
222
+ taskPrefix: "FN",
223
+ taskAttributionTrailerNames: ["Fusion-Task-Id"],
224
+ commitMsgHookEnabled: true,
225
+ includeTaskIdInCommit: true,
226
+ commitAuthorEnabled: true,
227
+ commitAuthorName: "Fusion",
228
+ commitAuthorEmail: "noreply@runfusion.ai",
229
+ // Per-phase model lanes (planning/execution/validator) MOVED to workflow
230
+ // settings (U4) — see MOVED_SETTINGS_KEYS. The GLOBAL baseline lanes
231
+ // (executionGlobalProvider etc.) stay global; project default overrides stay.
232
+ // Project-level default override (NOT moved — stays project-scoped)
233
+ defaultProviderOverride: void 0,
234
+ defaultModelIdOverride: void 0,
235
+ modelPresets: [],
236
+ autoSelectModelPreset: false,
237
+ completionDocumentationMode: "off",
238
+ defaultPresetBySize: {},
239
+ autoResolveConflicts: true,
240
+ smartConflictResolution: true,
241
+ mergerAutostashMaxAgeHours: 24,
242
+ worktreeRebaseBeforeMerge: true,
243
+ worktreeRebaseRemote: "",
244
+ worktreeRebaseLocalBase: true,
245
+ prerebaseAutoEnabled: true,
246
+ prerebaseHotFiles: [
247
+ "AGENTS.md",
248
+ "packages/core/src/store.ts",
249
+ "packages/core/src/db.ts",
250
+ "packages/engine/src/executor.ts",
251
+ "packages/engine/src/scheduler.ts",
252
+ "packages/engine/src/merger.ts",
253
+ "packages/dashboard/app/styles.css"
254
+ ],
255
+ prerebaseDivergenceThreshold: 50,
256
+ mergeConflictStrategy: "smart-prefer-main",
257
+ merger: { mode: "ai", maxReviewPasses: 3, allowDirtyLocalCheckoutSync: false },
258
+ mergeDiffVolumeMinLines: void 0,
259
+ mergeDiffVolumeThreshold: void 0,
260
+ mergeDiffVolumeAllowlist: void 0,
261
+ mergeStrategyOverlapBehavior: "flip-to-prefer-branch",
262
+ postMergeAuditMode: "warn",
263
+ mergeAuditAutoRecovery: "ai-assisted",
264
+ autoRecovery: {
265
+ mode: "deterministic-only",
266
+ maxRetries: 3
267
+ },
268
+ reliabilityStatsResetAt: void 0,
269
+ // Step-execution knobs (workflowStepTimeoutMs, workflowStepScopeEnforcement,
270
+ // planOnlyScopeLeakEnforcement, workflowRevisionForkOnScopeMismatch,
271
+ // strictScopeEnforcement, buildRetryCount, verificationFixRetries,
272
+ // requirePlanApproval) MOVED to workflow settings (U4) — see
273
+ // MOVED_SETTINGS_KEYS. `buildTimeoutMs` is NOT moved (no engine reader) and
274
+ // stays a plain project setting:
275
+ buildTimeoutMs: 3e5,
276
+ ephemeralAgentsEnabled: true,
277
+ agentProvisioning: {},
278
+ sandboxProvisioning: {},
279
+ defaultAgentPermissionPolicy: void 0,
280
+ specStalenessEnabled: false,
281
+ specStalenessMaxAgeMs: 6 * 60 * 60 * 1e3,
282
+ taskStuckTimeoutMs: 6e5,
283
+ /** Number of rapid todo↔in-progress cycles allowed before auto-pausing the task. */
284
+ dispatchOscillationThreshold: 5,
285
+ /** Sliding time window used to count rapid todo↔in-progress cycles. */
286
+ dispatchOscillationWindowMs: 6e4,
287
+ /** Delay before scheduler may re-dispatch an engine-requeued todo task. */
288
+ dispatchOscillationSettleMs: 5e3,
289
+ runtimeStopDrainMs: 2e3,
290
+ engineActiveSinceMs: void 0,
291
+ engineActivationGraceMs: 5 * 6e4,
292
+ inReviewStallDeadlockThreshold: 3,
293
+ stalePausedReviewThresholdMs: 24 * 60 * 6e4,
294
+ inReviewStalledThresholdMs: 24 * 60 * 6e4,
295
+ stalePausedTodoThresholdMs: 24 * 60 * 6e4,
296
+ pausedScopeDecayMs: 30 * 6e4,
297
+ metaTaskStallAutoCloseMs: 2 * 60 * 6e4,
298
+ metaTaskActiveExecutionGraceMs: 30 * 6e4,
299
+ boardStallSweepWindowMs: 2 * 60 * 6e4,
300
+ boardStallBlockedGrowthThreshold: 3,
301
+ // Capacity risk warning default: only warn once todo is meaningfully backlogged.
302
+ capacityRiskBannerEnabled: false,
303
+ capacityRiskTodoThreshold: 20,
304
+ backlogPressureAlertEnabled: true,
305
+ backlogPressureRatioThreshold: 10,
306
+ backlogPressureMinTodoCount: 5,
307
+ backlogPressureAlertCooldownMs: 24 * 60 * 6e4,
308
+ dependencyBlockedTodoReportEnabled: true,
309
+ dependencyBlockedTodoFreshAgeMs: 30 * 6e4,
310
+ dependencyBlockedTodoStaleAgeMs: 4 * 60 * 6e4,
311
+ dependencyBlockedTodoMinCount: 1,
312
+ dependencyBlockedTodoReportCooldownMs: 6 * 60 * 6e4,
313
+ staleHighFanoutBlockerAgeThresholdMs: 2 * 60 * 60 * 1e3,
314
+ staleInProgressWarningMs: 4 * 60 * 6e4,
315
+ staleInProgressCriticalMs: 24 * 60 * 6e4,
316
+ staleInReviewWarningMs: 24 * 60 * 6e4,
317
+ staleInReviewCriticalMs: 3 * 24 * 60 * 6e4,
318
+ aiSessionTtlMs: 7 * 24 * 60 * 60 * 1e3,
319
+ aiSessionCleanupIntervalMs: 60 * 60 * 1e3,
320
+ autoUnpauseEnabled: true,
321
+ autoUnpauseBaseDelayMs: 3e5,
322
+ autoUnpauseMaxDelayMs: 36e5,
323
+ maxStuckKills: 6,
324
+ maxBranchConflictRecoveries: 5,
325
+ // maxReviewerContextRetries / maxReviewerFallbackRetries MOVED to workflow
326
+ // settings (U4) — see MOVED_SETTINGS_KEYS.
327
+ maxTotalRetriesBeforeFail: 25,
328
+ preserveProgressOnStuckRequeue: true,
329
+ // maxPostReviewFixes MOVED to workflow settings (U4).
330
+ maxSpawnedAgentsPerParent: 5,
331
+ maxSpawnedAgentsGlobal: 20,
332
+ // Run maintenance (including WAL checkpointing) every 5 minutes by default.
333
+ maintenanceIntervalMs: 3e5,
334
+ autoArchiveDoneTasksEnabled: true,
335
+ autoArchiveDoneAfterMs: 48 * 60 * 60 * 1e3,
336
+ doneAutoArchiveDays: 0,
337
+ archiveAgentLogMode: "compact",
338
+ autoUpdatePrStatus: false,
339
+ githubCommentOnDone: false,
340
+ githubCommentTemplate: void 0,
341
+ githubCloseSourceIssueOnDone: false,
342
+ githubTrackingEnabledByDefault: false,
343
+ githubTrackingDefaultRepo: void 0,
344
+ githubTrackingDedupEnabled: true,
345
+ githubAuthMode: "gh-cli",
346
+ githubAuthToken: void 0,
347
+ autoBackupEnabled: false,
348
+ autoBackupSchedule: "0 2 * * *",
349
+ autoBackupRetention: 7,
350
+ autoBackupDir: ".fusion/backups",
351
+ memoryBackupEnabled: false,
352
+ memoryBackupSchedule: "0 3 * * *",
353
+ memoryBackupRetention: 14,
354
+ memoryBackupDir: ".fusion/backups/memory",
355
+ memoryBackupScope: "all",
356
+ autoSummarizeTitles: false,
357
+ useAiMergeCommitSummary: true,
358
+ // Title-summarizer model lanes stay project-scoped (not moved in U4).
359
+ titleSummarizerProvider: void 0,
360
+ titleSummarizerModelId: void 0,
361
+ titleSummarizerFallbackProvider: void 0,
362
+ titleSummarizerFallbackModelId: void 0,
363
+ scripts: void 0,
364
+ setupScript: void 0,
365
+ insightExtractionEnabled: false,
366
+ insightExtractionSchedule: "0 2 * * *",
367
+ insightExtractionMinIntervalMs: 864e5,
368
+ taskEvaluationEnabled: false,
369
+ taskEvaluationSchedule: "0 5 * * *",
370
+ taskEvaluationProvider: void 0,
371
+ taskEvaluationModelId: void 0,
372
+ taskEvaluationFollowUpPolicy: "off",
373
+ taskEvaluationRetention: void 0,
374
+ memoryEnabled: true,
375
+ memoryBackendType: "qmd",
376
+ memoryAutoSummarizeEnabled: false,
377
+ memoryAutoSummarizeThresholdChars: 5e4,
378
+ memoryAutoSummarizeSchedule: "0 3 * * *",
379
+ memoryDreamsEnabled: false,
380
+ memoryDreamsSchedule: "0 4 * * *",
381
+ tokenCap: void 0,
382
+ taskTokenBudget: void 0,
383
+ // runStepsInNewSessions / maxParallelSteps MOVED to workflow settings (U4) —
384
+ // see MOVED_SETTINGS_KEYS.
385
+ missionStaleThresholdMs: 6e5,
386
+ missionMaxTaskRetries: 3,
387
+ missionHealthCheckIntervalMs: 3e5,
388
+ agentPrompts: void 0,
389
+ promptOverrides: void 0,
390
+ // reflectionEnabled MOVED to workflow settings (U4). reflectionIntervalMs /
391
+ // reflectionAfterTask have no engine reader, so they STAY plain project
392
+ // settings (catalog-shrink rule) and are NOT in MOVED_SETTINGS_KEYS.
393
+ reflectionIntervalMs: 36e5,
394
+ reflectionAfterTask: true,
395
+ // reviewHandoffPolicy MOVED to workflow settings (U4) — see MOVED_SETTINGS_KEYS.
396
+ showQuickChatFAB: false,
397
+ chatAutoCleanupDays: 0,
398
+ mailAutoCleanupDays: 0,
399
+ operationalLogRetentionDays: 30,
400
+ agentLogFileRetentionDays: 0,
401
+ chatRoomRecentVerbatimMessages: 25,
402
+ chatRoomCompactionFetchLimit: 200,
403
+ chatRoomSummaryMaxChars: 3e3,
404
+ researchSettings: {
405
+ enabled: true,
406
+ searchProvider: void 0,
407
+ synthesisProvider: void 0,
408
+ synthesisModelId: void 0,
409
+ enabledSources: {
410
+ webSearch: true,
411
+ pageFetch: true,
412
+ github: false,
413
+ localDocs: true,
414
+ llmSynthesis: true
415
+ },
416
+ limits: {
417
+ maxConcurrentRuns: 3,
418
+ maxSourcesPerRun: 20,
419
+ maxDurationMs: 3e5,
420
+ requestTimeoutMs: 3e4
421
+ }
422
+ },
423
+ sandbox: {
424
+ backend: "native",
425
+ policy: {
426
+ allowNetwork: true,
427
+ allowedPaths: []
428
+ },
429
+ failureMode: "fail-hard"
430
+ },
431
+ evalSettings: {
432
+ enabled: false,
433
+ intervalMs: 864e5,
434
+ evaluatorProvider: void 0,
435
+ evaluatorModelId: void 0,
436
+ followUpPolicy: "suggest-only",
437
+ retentionDays: 30
438
+ },
439
+ researchEnabled: true,
440
+ researchMaxConcurrentRuns: 3,
441
+ researchDefaultTimeout: 3e5,
442
+ researchMaxSourcesPerRun: 20,
443
+ researchMaxSynthesisRounds: 2
444
+ };
445
+ var DEFAULT_SETTINGS = {
446
+ ...DEFAULT_GLOBAL_SETTINGS,
447
+ ...DEFAULT_PROJECT_SETTINGS
448
+ };
449
+ var GLOBAL_SETTINGS_KEYS = Object.freeze(Object.keys(DEFAULT_GLOBAL_SETTINGS));
450
+ var PROJECT_SETTINGS_KEYS = Object.freeze(Object.keys(DEFAULT_PROJECT_SETTINGS));
451
+ function isGlobalSettingsKey(key) {
452
+ return GLOBAL_SETTINGS_KEYS.includes(key);
453
+ }
454
+ function isProjectSettingsKey(key) {
455
+ return PROJECT_SETTINGS_KEYS.includes(key);
456
+ }
457
+ function isGlobalOnlySettingsKey(key) {
458
+ return isGlobalSettingsKey(key) && !isProjectSettingsKey(key);
459
+ }
460
+ var CLI_AGENT_ADAPTER_IDS = Object.freeze([
461
+ "claude-code",
462
+ "codex",
463
+ "droid",
464
+ "pi",
465
+ "generic"
466
+ ]);
467
+ var CLI_AGENT_AUTONOMY_MODES = Object.freeze(["default", "elevated"]);
468
+ function sanitizeStringArray(value) {
469
+ if (!Array.isArray(value))
470
+ return void 0;
471
+ const cleaned = value.filter((v) => typeof v === "string").map((v) => v.trim()).filter((v) => v.length > 0);
472
+ return cleaned.length > 0 ? cleaned : void 0;
473
+ }
474
+ function sanitizeCliAgentSettings(value) {
475
+ if (!value || typeof value !== "object" || Array.isArray(value))
476
+ return void 0;
477
+ const input = value;
478
+ const out = {};
479
+ if (typeof input.commandOverride === "string") {
480
+ const trimmed = input.commandOverride.trim();
481
+ if (trimmed.length > 0)
482
+ out.commandOverride = trimmed;
483
+ }
484
+ const extraArgs = sanitizeStringArray(input.extraArgs);
485
+ if (extraArgs)
486
+ out.extraArgs = extraArgs;
487
+ const envAdditions = sanitizeStringArray(input.envAdditions);
488
+ if (envAdditions)
489
+ out.envAdditions = envAdditions;
490
+ if (typeof input.autonomyMode === "string" && CLI_AGENT_AUTONOMY_MODES.includes(input.autonomyMode)) {
491
+ out.autonomyMode = input.autonomyMode;
492
+ }
493
+ return Object.keys(out).length > 0 ? out : void 0;
494
+ }
495
+ function sanitizeCliAgentsSettings(value) {
496
+ if (!value || typeof value !== "object" || Array.isArray(value))
497
+ return {};
498
+ const input = value;
499
+ const out = {};
500
+ for (const adapterId of CLI_AGENT_ADAPTER_IDS) {
501
+ if (!(adapterId in input))
502
+ continue;
503
+ const entry = sanitizeCliAgentSettings(input[adapterId]);
504
+ if (entry)
505
+ out[adapterId] = entry;
506
+ }
507
+ return out;
508
+ }
509
+
510
+ // ../core/dist/error-message.js
511
+ function getErrorMessage(err) {
512
+ if (err instanceof Error)
513
+ return err.message;
514
+ if (typeof err === "string")
515
+ return err;
516
+ try {
517
+ return JSON.stringify(err);
518
+ } catch {
519
+ return String(err);
520
+ }
521
+ }
522
+
523
+ // ../core/dist/model-resolution.js
524
+ var TEST_MODE_RESOLVED = { provider: "mock", modelId: "scripted" };
525
+ function isTestModeActive(settings) {
526
+ return settings?.testMode === true || settings?.defaultProvider?.trim().toLowerCase() === "mock";
527
+ }
528
+ function applyTestModeOverrides(resolved, settings) {
529
+ return isTestModeActive(settings) ? TEST_MODE_RESOLVED : resolved;
530
+ }
531
+ function hasCompleteModelPair(pair) {
532
+ return Boolean(pair?.provider && pair?.modelId);
533
+ }
534
+ function pickFirstModelPair(...pairs) {
535
+ for (const pair of pairs) {
536
+ if (hasCompleteModelPair(pair)) {
537
+ return { provider: pair.provider, modelId: pair.modelId };
538
+ }
539
+ }
540
+ return {};
541
+ }
542
+ function resolveProjectDefaultModel(settings) {
543
+ return applyTestModeOverrides(pickFirstModelPair({
544
+ provider: settings?.defaultProviderOverride,
545
+ modelId: settings?.defaultModelIdOverride
546
+ }, {
547
+ provider: settings?.defaultProvider,
548
+ modelId: settings?.defaultModelId
549
+ }), settings);
550
+ }
551
+ function resolveTitleSummarizerSettingsModel(settings) {
552
+ return applyTestModeOverrides(pickFirstModelPair({
553
+ provider: settings?.titleSummarizerProvider,
554
+ modelId: settings?.titleSummarizerModelId
555
+ }, {
556
+ provider: settings?.titleSummarizerGlobalProvider,
557
+ modelId: settings?.titleSummarizerGlobalModelId
558
+ }, {
559
+ provider: settings?.planningProvider,
560
+ modelId: settings?.planningModelId
561
+ }, resolveProjectDefaultModel(settings)), settings);
562
+ }
563
+
564
+ // ../core/dist/experimental-features.js
565
+ var LEGACY_EXPERIMENTAL_FEATURE_ALIASES = {
566
+ devServer: "devServerView"
567
+ };
568
+ function isExperimentalFeatureEnabled(settings, key) {
569
+ const features = settings?.experimentalFeatures;
570
+ if (!features)
571
+ return false;
572
+ const canonicalKey = LEGACY_EXPERIMENTAL_FEATURE_ALIASES[key] ?? key;
573
+ if (features[canonicalKey] === true)
574
+ return true;
575
+ for (const [legacyKey, aliasCanonical] of Object.entries(LEGACY_EXPERIMENTAL_FEATURE_ALIASES)) {
576
+ if (aliasCanonical === canonicalKey && features[legacyKey] === true) {
577
+ return true;
578
+ }
579
+ }
580
+ return false;
581
+ }
582
+
583
+ // ../core/dist/types.js
584
+ var COLUMNS = ["triage", "todo", "in-progress", "in-review", "done", "archived"];
585
+ var TASK_PRIORITIES = ["low", "normal", "high", "urgent"];
586
+ var DEFAULT_TASK_PRIORITY = "normal";
587
+ var STALE_HIGH_FANOUT_BLOCKER_AGE_THRESHOLD_MS = 2 * 60 * 60 * 1e3;
588
+ var SUPPORTED_LOCALES = ["en", "zh-CN", "zh-TW", "fr", "es", "ko"];
589
+ function isLocale(value) {
590
+ return typeof value === "string" && SUPPORTED_LOCALES.includes(value);
591
+ }
592
+ var WORKFLOW_STEP_TEMPLATES = [
593
+ {
594
+ id: "documentation-review",
595
+ name: "Documentation Review",
596
+ description: "Verify all public APIs, functions, and complex logic have appropriate documentation",
597
+ category: "Quality",
598
+ icon: "file-text",
599
+ toolMode: "readonly",
600
+ prompt: `You are a documentation reviewer. Review the completed task and verify documentation quality.
601
+
602
+ Review Criteria:
603
+ 1. All new public functions, classes, and modules have JSDoc comments or equivalent documentation
604
+ 2. Complex logic has inline comments explaining the "why" not just the "what"
605
+ 3. README files are updated if the task changes user-facing behavior
606
+ 4. CHANGELOG or release notes are considered for significant changes
607
+ 5. Type definitions are documented for public APIs
608
+
609
+ Files to Review:
610
+ - Review all files modified in the task worktree
611
+ - Focus on public API surface area
612
+ - Check test files for test documentation
613
+
614
+ Output Requirements:
615
+ - Fast-bail: if Diff Scope contains no documentation-relevant files, output {"verdict":"APPROVE","notes":"out of scope: documentation"} immediately.
616
+ - APPROVE: documentation is adequate; use empty or brief notes.
617
+ - APPROVE_WITH_NOTES: documentation is adequate with advisory improvements; include concise suggestions in notes.
618
+ - REVISE: documentation is missing or incorrect; include actionable file paths/functions in notes.
619
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
620
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`
621
+ },
622
+ {
623
+ id: "qa-check",
624
+ name: "QA Check",
625
+ description: "Run lint, tests, and typecheck; verify they pass and check for obvious bugs",
626
+ category: "Quality",
627
+ icon: "check-circle",
628
+ toolMode: "coding",
629
+ prompt: `You are a QA tester. Verify the task implementation by running lint, tests, and typecheck, and checking for bugs.
630
+
631
+ Quality Gate Execution (all three must pass):
632
+ 1. Run the project's lint command (e.g. \`pnpm lint\`, \`npm run lint\`)
633
+ 2. Run the project's test suite (e.g. \`pnpm test\`, \`npm test\`, or the configured test command)
634
+ 3. Run the project's typecheck command if one exists (e.g. \`pnpm typecheck\`, \`tsc --noEmit\`)
635
+ 4. Verify lint, tests, and typecheck all pass
636
+ 5. If any gate fails, analyze whether failures are related to the task changes
637
+
638
+ Code Review:
639
+ 1. Review the changes for obvious bugs or edge cases
640
+ 2. Check error handling is appropriate
641
+ 3. Verify input validation is present where needed
642
+ 4. Look for common issues: null pointer risks, off-by-one errors, race conditions
643
+
644
+ Output Requirements:
645
+ - Fast-bail: if Diff Scope contains no QA-relevant files, output {"verdict":"APPROVE","notes":"out of scope: QA"} immediately.
646
+ - APPROVE: lint/tests/typecheck pass and no actionable bugs.
647
+ - APPROVE_WITH_NOTES: quality gates pass but include non-blocking advisories in notes.
648
+ - REVISE: any gate fails or actionable bugs are found; include failing commands and affected file paths in notes.
649
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
650
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`
651
+ },
652
+ {
653
+ id: "security-audit",
654
+ name: "Security Audit",
655
+ description: "Check for common security vulnerabilities and anti-patterns",
656
+ category: "Security",
657
+ icon: "shield",
658
+ toolMode: "readonly",
659
+ prompt: `You are a security auditor. Review the task changes for common security vulnerabilities.
660
+
661
+ Security Checklist:
662
+ 1. **Injection vulnerabilities** \u2014 Check for SQL injection, command injection, XSS via unsanitized user input
663
+ 2. **Secrets and credentials** \u2014 Ensure no hardcoded passwords, API keys, tokens, or private keys
664
+ 3. **Unsafe eval** \u2014 Check for eval(), new Function(), or similar dangerous patterns
665
+ 4. **Path traversal** \u2014 Verify file path handling prevents directory traversal attacks
666
+ 5. **Insecure deserialization** \u2014 Check for unsafe parsing of untrusted data
667
+ 6. **Authentication/Authorization** \u2014 Verify access controls are properly implemented
668
+ 7. **Dependency risks** \u2014 Note any new dependencies that might have known vulnerabilities
669
+
670
+ Files to Review:
671
+ - All modified files in the task
672
+ - Configuration files that might contain secrets
673
+ - Areas handling user input or external data
674
+
675
+ Output Requirements:
676
+ - Fast-bail: if Diff Scope contains no security-relevant files, output {"verdict":"APPROVE","notes":"out of scope: security"} immediately.
677
+ - APPROVE: no security issues found.
678
+ - APPROVE_WITH_NOTES: no blocking issues, but include advisory hardening opportunities in notes.
679
+ - REVISE: vulnerabilities require changes; include file paths, severity, and remediation guidance in notes.
680
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
681
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`
682
+ },
683
+ {
684
+ id: "performance-review",
685
+ name: "Performance Review",
686
+ description: "Check for performance anti-patterns and optimization opportunities",
687
+ category: "Quality",
688
+ icon: "zap",
689
+ toolMode: "readonly",
690
+ prompt: `You are a performance reviewer. Analyze the task changes for performance implications.
691
+
692
+ Performance Checklist:
693
+ 1. **Algorithmic complexity** \u2014 Check for O(n\xB2) or worse patterns that could bottleneck
694
+ 2. **N+1 queries** \u2014 Look for database queries in loops
695
+ 3. **Memory leaks** \u2014 Check for unclosed resources, event listeners, or accumulating caches
696
+ 4. **Unnecessary re-renders** \u2014 For UI code, check for inefficient React/Angular/Vue patterns
697
+ 5. **Bundle size** \u2014 Note if large dependencies are added unnecessarily
698
+ 6. **Async patterns** \u2014 Verify proper use of async/await, Promise.all for parallel work
699
+ 7. **Caching opportunities** \u2014 Identify where caching could improve performance
700
+
701
+ Files to Review:
702
+ - All modified files, focusing on hot paths and frequently executed code
703
+ - Database query files
704
+ - API endpoints and route handlers
705
+
706
+ Output Requirements:
707
+ - Fast-bail: if Diff Scope contains no performance-relevant files, output {"verdict":"APPROVE","notes":"out of scope: performance"} immediately.
708
+ - APPROVE: performance impact is acceptable.
709
+ - APPROVE_WITH_NOTES: acceptable overall, but include optimization advisories in notes.
710
+ - REVISE: performance risks require changes; include actionable file paths and optimization guidance in notes.
711
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
712
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`
713
+ },
714
+ {
715
+ id: "accessibility-check",
716
+ name: "Accessibility Check",
717
+ description: "Verify UI changes meet accessibility standards (WCAG 2.1)",
718
+ category: "Quality",
719
+ icon: "eye",
720
+ toolMode: "readonly",
721
+ prompt: `You are an accessibility reviewer. Check UI changes for WCAG 2.1 compliance.
722
+
723
+ Accessibility Checklist:
724
+ 1. **Keyboard navigation** \u2014 Ensure all interactive elements are keyboard accessible
725
+ 2. **ARIA labels** \u2014 Check that screen reader announcements are appropriate
726
+ 3. **Color contrast** \u2014 Verify text meets minimum contrast ratios (4.5:1 for normal text)
727
+ 4. **Focus indicators** \u2014 Ensure visible focus states for keyboard navigation
728
+ 5. **Alt text** \u2014 Check that images have meaningful alternative text
729
+ 6. **Form labels** \u2014 Verify all inputs have associated labels
730
+ 7. **Semantic HTML** \u2014 Check that proper HTML elements are used (buttons not divs)
731
+
732
+ Files to Review:
733
+ - Modified UI components
734
+ - CSS/styling changes
735
+ - New HTML templates or JSX
736
+
737
+ Output Requirements:
738
+ - Fast-bail: if Diff Scope contains no accessibility-relevant UI files, output {"verdict":"APPROVE","notes":"out of scope: accessibility"} immediately.
739
+ - APPROVE: accessibility requirements are met.
740
+ - APPROVE_WITH_NOTES: compliant overall, with advisory improvements in notes.
741
+ - REVISE: accessibility issues require changes; include file paths, WCAG references, and remediation steps in notes.
742
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
743
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}`
744
+ },
745
+ {
746
+ id: "browser-verification",
747
+ name: "Browser Verification",
748
+ description: "Verify web application functionality using browser automation",
749
+ category: "Quality",
750
+ icon: "globe",
751
+ toolMode: "coding",
752
+ prompt: `You are a browser verification specialist. Verify web application functionality after task implementation using the agent-browser CLI tool.
753
+
754
+ ## Prerequisites
755
+ First, determine the URL to verify. Check the task PROMPT.md for any URLs mentioned, or look at the code changes to identify the local development server URL (typically http://localhost:3000, http://localhost:5173, http://localhost:8080, etc.).
756
+
757
+ ## Verification Commands
758
+ Use these agent-browser commands for verification:
759
+ - \`agent-browser open <url>\` \u2014 Navigate to the page
760
+ - \`agent-browser snapshot -i\` \u2014 Get interactive elements with refs (@e1, @e2, etc.)
761
+ - \`agent-browser click @e1\` \u2014 Click an element
762
+ - \`agent-browser fill @e1 "text"\` \u2014 Fill an input field
763
+ - \`agent-browser get text @e1\` \u2014 Get element text content
764
+ - \`agent-browser screenshot\` \u2014 Capture screenshot to file
765
+ - \`agent-browser wait --load networkidle\` \u2014 Wait for page to fully load
766
+
767
+ ## Verification Checklist
768
+ 1. Page loads without JavaScript errors or blank screens
769
+ 2. Navigation between pages/sections works
770
+ 3. Forms accept input and submit correctly
771
+ 4. Interactive elements (buttons, links) respond to clicks
772
+ 5. Error states are handled gracefully
773
+ 6. Screenshots capture expected content
774
+
775
+ ## Output Requirements
776
+ - Fast-bail: if Diff Scope contains no browser-verification-relevant UI files, output {"verdict":"APPROVE","notes":"out of scope: browser verification"} immediately.
777
+ - APPROVE: verification succeeds.
778
+ - APPROVE_WITH_NOTES: verification succeeds with non-blocking advisory findings; include evidence references in notes.
779
+ - REVISE: verification failures or regressions require changes; include failing behavior and actionable file paths in notes.
780
+ - Screenshots/artifacts referenced in notes are evidence only; verdict must be conveyed by the final JSON line.
781
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
782
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}
783
+
784
+ Note: Refs (@e1, @e2) are invalidated after page navigation. Re-snapshot after clicking links or form submissions.`
785
+ },
786
+ {
787
+ id: "frontend-ux-design",
788
+ name: "Frontend UX Design",
789
+ description: "Verify visual polish and consistency with existing UI patterns and design tokens",
790
+ category: "Quality",
791
+ icon: "layout-grid",
792
+ toolMode: "readonly",
793
+ prompt: `You are a UX design reviewer. Verify frontend changes maintain visual polish and consistency with existing UI patterns and design tokens.
794
+
795
+ ## Step 1: Scope Check (MANDATORY FIRST)
796
+
797
+ The task harness provides a "Diff Scope" listing files this task actually changed.
798
+
799
+ If the Diff Scope contains ZERO frontend/UI files (no .tsx/.jsx/.ts/.js component files, no .css/.scss/.sass/.styl, no .html/.vue/.svelte/.astro, no design-token/theme files), output ONLY:
800
+ {"verdict":"APPROVE","notes":"out of scope: frontend UX design"}
801
+ Then STOP. Do not browse the worktree. Do not read any files.
802
+
803
+ If there ARE frontend/UI files in scope, proceed to Step 2.
804
+
805
+ ## Step 2: Design Review
806
+
807
+ Restrict your review to ONLY the UI files in the diff scope.
808
+
809
+ Check:
810
+ 1. **Visual Hierarchy** \u2014 heading levels, content flow, information architecture
811
+ 2. **Spacing and Typography** \u2014 consistent margins, padding, gaps, type scale
812
+ 3. **Color and Token Consistency** \u2014 CSS custom properties and design tokens used; no hardcoded colors
813
+ 4. **Component Reuse** \u2014 existing components reused; no one-off styling or duplication
814
+ 5. **Responsive Behavior** \u2014 layouts adapt across viewports
815
+ 6. **Fit with Design Language** \u2014 border radius, shadows, transitions, icon style match patterns
816
+
817
+ ## Output Format
818
+
819
+ - APPROVE: visual quality is acceptable; use empty or brief notes.
820
+ - APPROVE_WITH_NOTES: acceptable with non-blocking polish advisories; include specific notes.
821
+ - REVISE: issues require code changes; include specific files and required changes in notes.
822
+ - Final output: output exactly one trailing JSON object on the final line (no markdown fences, no surrounding prose):
823
+ {"verdict":"APPROVE|APPROVE_WITH_NOTES|REVISE","notes":"..."}
824
+
825
+ Prioritize: layout breaks > visual inconsistency > style preferences.
826
+ Do NOT spend time on nits when no real issues exist.`
827
+ }
828
+ ];
829
+ var DOCUMENT_KEY_RE = /^[a-zA-Z0-9_-]{1,64}$/;
830
+ function validateDocumentKey(key) {
831
+ if (!DOCUMENT_KEY_RE.test(key)) {
832
+ throw new Error(`Invalid document key: "${key}". Must be 1-64 characters: letters, digits, hyphens, or underscores.`);
833
+ }
834
+ }
835
+ var CheckoutConflictError = class extends Error {
836
+ taskId;
837
+ currentHolderId;
838
+ requestedById;
839
+ constructor(taskId, currentHolderId, requestedById) {
840
+ super(`Task ${taskId} is already checked out by agent ${currentHolderId}`);
841
+ this.taskId = taskId;
842
+ this.currentHolderId = currentHolderId;
843
+ this.requestedById = requestedById;
844
+ this.name = "CheckoutConflictError";
845
+ }
846
+ };
847
+ var SHARED_STATE_SNAPSHOT_VERSION = 1;
848
+ var VALID_TRANSITIONS = {
849
+ // FN-4892: intake-side heuristics may cold-archive tasks before execution starts.
850
+ triage: ["todo", "archived"],
851
+ // FN-4892: allow direct archival for newly specified intake tasks.
852
+ todo: ["in-progress", "triage", "archived"],
853
+ // NOTE: "in-progress" → "done" is enabled for mission validation tasks that complete directly.
854
+ // Regular implementation tasks should move through "in-review" before "done".
855
+ "in-progress": ["in-review", "todo", "triage", "done"],
856
+ "in-review": ["done", "in-progress", "todo", "triage"],
857
+ done: ["todo", "triage", "archived"],
858
+ archived: ["done"]
859
+ };
860
+ function validateDockerNodeConfig(config) {
861
+ const errors = [];
862
+ if (!config || typeof config !== "object" || Array.isArray(config)) {
863
+ return { valid: false, errors: ["config must be an object"] };
864
+ }
865
+ const candidate = config;
866
+ if (typeof candidate.image !== "string" || !candidate.image.trim()) {
867
+ errors.push("image must be a non-empty string");
868
+ }
869
+ if (!Array.isArray(candidate.volumeMounts)) {
870
+ errors.push("volumeMounts must be an array");
871
+ } else {
872
+ candidate.volumeMounts.forEach((mount, index) => {
873
+ if (!mount || typeof mount !== "object" || Array.isArray(mount)) {
874
+ errors.push(`volumeMounts[${index}] must be an object`);
875
+ return;
876
+ }
877
+ const mountCandidate = mount;
878
+ if (typeof mountCandidate.hostPath !== "string") {
879
+ errors.push(`volumeMounts[${index}].hostPath must be a string`);
880
+ }
881
+ if (typeof mountCandidate.containerPath !== "string") {
882
+ errors.push(`volumeMounts[${index}].containerPath must be a string`);
883
+ }
884
+ if (mountCandidate.mode !== void 0 && mountCandidate.mode !== "rw" && mountCandidate.mode !== "ro") {
885
+ errors.push(`volumeMounts[${index}].mode must be "rw" or "ro"`);
886
+ }
887
+ if (mountCandidate.type !== void 0 && mountCandidate.type !== "volume" && mountCandidate.type !== "bind") {
888
+ errors.push(`volumeMounts[${index}].type must be "volume" or "bind"`);
889
+ }
890
+ });
891
+ }
892
+ if (!candidate.environment || typeof candidate.environment !== "object" || Array.isArray(candidate.environment)) {
893
+ errors.push("environment must be an object");
894
+ } else {
895
+ for (const [key, value] of Object.entries(candidate.environment)) {
896
+ if (typeof key !== "string" || typeof value !== "string") {
897
+ errors.push(`environment.${key} must be a string value`);
898
+ }
899
+ }
900
+ }
901
+ if (typeof candidate.configVersion !== "number" || !Number.isFinite(candidate.configVersion) || candidate.configVersion < 1) {
902
+ errors.push("configVersion must be a number >= 1");
903
+ }
904
+ const validateOptionalObject = (fieldName, value, validators) => {
905
+ if (value === void 0)
906
+ return;
907
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
908
+ errors.push(`${fieldName} must be an object`);
909
+ return;
910
+ }
911
+ const typed = value;
912
+ for (const [prop, test, message] of validators) {
913
+ if (typed[prop] !== void 0 && !test(typed[prop])) {
914
+ errors.push(`${fieldName}.${prop} ${message}`);
915
+ }
916
+ }
917
+ };
918
+ validateOptionalObject("resources", candidate.resources, [
919
+ ["memoryBytes", (value) => typeof value === "number" && Number.isFinite(value), "must be a number"],
920
+ ["cpuCount", (value) => typeof value === "number" && Number.isFinite(value), "must be a number"],
921
+ ["pidsLimit", (value) => typeof value === "number" && Number.isFinite(value), "must be a number"]
922
+ ]);
923
+ validateOptionalObject("host", candidate.host, [
924
+ ["contextName", (value) => typeof value === "string", "must be a string"],
925
+ ["dockerHost", (value) => typeof value === "string", "must be a string"],
926
+ ["tlsCaCert", (value) => typeof value === "string", "must be a string"],
927
+ ["tlsCert", (value) => typeof value === "string", "must be a string"],
928
+ ["tlsKey", (value) => typeof value === "string", "must be a string"],
929
+ ["tlsVerify", (value) => typeof value === "boolean", "must be a boolean"]
930
+ ]);
931
+ validateOptionalObject("persistence", candidate.persistence, [
932
+ ["volumeName", (value) => typeof value === "string", "must be a string"],
933
+ ["retainOnDelete", (value) => typeof value === "boolean", "must be a boolean"]
934
+ ]);
935
+ if (candidate.extraClis !== void 0) {
936
+ if (!Array.isArray(candidate.extraClis) || candidate.extraClis.some((item) => typeof item !== "string")) {
937
+ errors.push("extraClis must be an array of strings");
938
+ }
939
+ }
940
+ if (candidate.containerName !== void 0 && typeof candidate.containerName !== "string") {
941
+ errors.push("containerName must be a string");
942
+ }
943
+ if (candidate.lastUpdated !== void 0 && typeof candidate.lastUpdated !== "string") {
944
+ errors.push("lastUpdated must be a string");
945
+ }
946
+ if (errors.length > 0) {
947
+ return { valid: false, errors };
948
+ }
949
+ return { valid: true, config: candidate };
950
+ }
951
+ var AGENT_VALID_TRANSITIONS = {
952
+ idle: ["active"],
953
+ active: ["idle", "running", "paused", "error"],
954
+ running: ["idle", "active", "paused", "error"],
955
+ paused: ["idle", "active"],
956
+ error: ["idle", "active", "paused"]
957
+ };
958
+ function isEphemeralAgent(agent) {
959
+ const metadata = agent.metadata ?? {};
960
+ if (metadata.agentKind === "task-worker")
961
+ return true;
962
+ if (metadata.taskWorker === true)
963
+ return true;
964
+ if (metadata.managedBy === "task-executor")
965
+ return true;
966
+ if (metadata.type === "spawned")
967
+ return true;
968
+ if (metadata.internal === true)
969
+ return true;
970
+ if (agent.role === "executor" && typeof agent.name === "string" && agent.name.startsWith("executor-") && agent.reportsTo == null) {
971
+ return true;
972
+ }
973
+ if (agent.role === "executor" && agent.name === "verification-agent" && agent.reportsTo == null) {
974
+ return true;
975
+ }
976
+ return false;
977
+ }
978
+ var AGENT_PERMISSIONS = [
979
+ "tasks:assign",
980
+ // Assign tasks to agents
981
+ "tasks:create",
982
+ // Create new tasks
983
+ "tasks:execute",
984
+ // Execute/run tasks
985
+ "tasks:review",
986
+ // Review task output (code, specs)
987
+ "tasks:merge",
988
+ // Merge completed task branches
989
+ "tasks:delete",
990
+ // Delete tasks
991
+ "tasks:archive",
992
+ // Archive/unarchive tasks
993
+ "agents:create",
994
+ // Create new agents
995
+ "agents:update",
996
+ // Update agent configuration
997
+ "agents:delete",
998
+ // Delete agents
999
+ "agents:view",
1000
+ // View agent details and logs
1001
+ "settings:read",
1002
+ // Read project settings
1003
+ "settings:update",
1004
+ // Modify project settings
1005
+ "workflows:manage",
1006
+ // Create/edit/delete workflow steps
1007
+ "missions:manage",
1008
+ // Create/edit/delete missions and slices
1009
+ "automations:manage",
1010
+ // Create/edit/delete scheduled automations
1011
+ "messages:send",
1012
+ // Send messages to agents/users
1013
+ "messages:read"
1014
+ // Read mailbox messages
1015
+ ];
1016
+ var AGENT_PERMISSION_POLICY_ACTION_CATEGORIES = [
1017
+ "git_write",
1018
+ "file_write_delete",
1019
+ "command_execution",
1020
+ "network_api",
1021
+ "task_agent_mutation"
1022
+ ];
1023
+ var AGENT_PERMISSION_POLICY_PRESET_IDS = ["unrestricted", "approval-required", "locked-down", "custom"];
1024
+ var DEFAULT_HEARTBEAT_PROCEDURE_PATH = ".fusion/HEARTBEAT.md";
1025
+ function slugifyAgentAssetSegment(value) {
1026
+ return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1027
+ }
1028
+ function getSafeAgentAssetIdSegment(agentId) {
1029
+ const slug = slugifyAgentAssetSegment(agentId);
1030
+ return slug || "agent";
1031
+ }
1032
+ function getCanonicalAgentAssetDirectoryName(agentName, agentId) {
1033
+ if (!agentId || typeof agentId !== "string") {
1034
+ throw new Error("getCanonicalAgentAssetDirectoryName requires a non-empty agentId");
1035
+ }
1036
+ const safeId = getSafeAgentAssetIdSegment(agentId);
1037
+ const nameSlug = slugifyAgentAssetSegment(agentName ?? "");
1038
+ const prefix = nameSlug || safeId;
1039
+ return `${prefix}-${safeId}`;
1040
+ }
1041
+ function getLegacyAgentAssetDirectoryName(agentId) {
1042
+ if (!agentId || typeof agentId !== "string") {
1043
+ throw new Error("getLegacyAgentAssetDirectoryName requires a non-empty agentId");
1044
+ }
1045
+ return agentId;
1046
+ }
1047
+ function getCanonicalAgentInstructionsBundleDirName(agentName, agentId) {
1048
+ return `${getCanonicalAgentAssetDirectoryName(agentName, agentId)}-instructions`;
1049
+ }
1050
+ function getLegacyAgentInstructionsBundleDirName(agentId) {
1051
+ return `${getLegacyAgentAssetDirectoryName(agentId)}-instructions`;
1052
+ }
1053
+ function getDefaultHeartbeatProcedurePath(agentId, agentName) {
1054
+ if (!agentId || typeof agentId !== "string") {
1055
+ throw new Error("getDefaultHeartbeatProcedurePath requires a non-empty agentId");
1056
+ }
1057
+ const directory = agentName ? getCanonicalAgentAssetDirectoryName(agentName, agentId) : getLegacyAgentAssetDirectoryName(agentId);
1058
+ return `.fusion/agents/${directory}/HEARTBEAT.md`;
1059
+ }
1060
+ function agentToConfigSnapshot(agent) {
1061
+ return {
1062
+ name: agent.name,
1063
+ role: agent.role,
1064
+ title: agent.title,
1065
+ icon: agent.icon,
1066
+ imageUrl: agent.imageUrl,
1067
+ reportsTo: agent.reportsTo,
1068
+ runtimeConfig: agent.runtimeConfig ? { ...agent.runtimeConfig } : void 0,
1069
+ permissions: agent.permissions ? { ...agent.permissions } : void 0,
1070
+ permissionPolicy: agent.permissionPolicy ? {
1071
+ presetId: agent.permissionPolicy.presetId,
1072
+ rules: { ...agent.permissionPolicy.rules }
1073
+ } : void 0,
1074
+ instructionsPath: agent.instructionsPath,
1075
+ instructionsText: agent.instructionsText,
1076
+ soul: agent.soul,
1077
+ memory: agent.memory,
1078
+ bundleConfig: agent.bundleConfig ? {
1079
+ ...agent.bundleConfig,
1080
+ files: [...agent.bundleConfig.files]
1081
+ } : void 0,
1082
+ heartbeatProcedurePath: agent.heartbeatProcedurePath,
1083
+ metadata: { ...agent.metadata }
1084
+ };
1085
+ }
1086
+ function diffConfigSnapshots(before, after) {
1087
+ const trackedFields = [
1088
+ "name",
1089
+ "role",
1090
+ "title",
1091
+ "icon",
1092
+ "imageUrl",
1093
+ "reportsTo",
1094
+ "runtimeConfig",
1095
+ "permissions",
1096
+ "permissionPolicy",
1097
+ "instructionsPath",
1098
+ "instructionsText",
1099
+ "soul",
1100
+ "memory",
1101
+ "bundleConfig",
1102
+ "heartbeatProcedurePath",
1103
+ "metadata"
1104
+ ];
1105
+ const diffs = [];
1106
+ for (const field of trackedFields) {
1107
+ const oldVal = before[field];
1108
+ const newVal = after[field];
1109
+ if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
1110
+ diffs.push({ field, oldValue: oldVal, newValue: newVal });
1111
+ }
1112
+ }
1113
+ return diffs;
1114
+ }
1115
+
1116
+ export {
1117
+ DEFAULT_GLOBAL_SETTINGS,
1118
+ DEFAULT_PROJECT_SETTINGS,
1119
+ DEFAULT_SETTINGS,
1120
+ isGlobalOnlySettingsKey,
1121
+ sanitizeCliAgentsSettings,
1122
+ getErrorMessage,
1123
+ resolveTitleSummarizerSettingsModel,
1124
+ isExperimentalFeatureEnabled,
1125
+ COLUMNS,
1126
+ TASK_PRIORITIES,
1127
+ DEFAULT_TASK_PRIORITY,
1128
+ isLocale,
1129
+ WORKFLOW_STEP_TEMPLATES,
1130
+ validateDocumentKey,
1131
+ CheckoutConflictError,
1132
+ SHARED_STATE_SNAPSHOT_VERSION,
1133
+ VALID_TRANSITIONS,
1134
+ validateDockerNodeConfig,
1135
+ AGENT_VALID_TRANSITIONS,
1136
+ isEphemeralAgent,
1137
+ AGENT_PERMISSIONS,
1138
+ AGENT_PERMISSION_POLICY_ACTION_CATEGORIES,
1139
+ AGENT_PERMISSION_POLICY_PRESET_IDS,
1140
+ DEFAULT_HEARTBEAT_PROCEDURE_PATH,
1141
+ getSafeAgentAssetIdSegment,
1142
+ getLegacyAgentAssetDirectoryName,
1143
+ getCanonicalAgentInstructionsBundleDirName,
1144
+ getLegacyAgentInstructionsBundleDirName,
1145
+ getDefaultHeartbeatProcedurePath,
1146
+ agentToConfigSnapshot,
1147
+ diffConfigSnapshots
1148
+ };