@runfusion/fusion 0.77.0-beta.6 → 0.77.0-beta.8

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 (170) hide show
  1. package/dist/bin.js +42896 -39460
  2. package/dist/child-process-worker.js +7535 -4556
  3. package/dist/client/.vite/manifest.json +267 -330
  4. package/dist/client/assets/{AgentDetailView-oyY72uSo.js → AgentDetailView-DsMRc-aH.js} +4 -4
  5. package/dist/client/assets/{AgentPermissionPolicyEditor-C3Qo9p1M.js → AgentPermissionPolicyEditor-BXJ52YpO.js} +2 -2
  6. package/dist/client/assets/{AgentsView-M2MhTIGW.js → AgentsView-DO-25nlB.js} +4 -4
  7. package/dist/client/assets/{CommandCenter-CpcAt6jt.js → CommandCenter-BMXMg_I2.js} +18 -18
  8. package/dist/client/assets/DevServerView-DAeL5TYz.js +1 -0
  9. package/dist/client/assets/DirectoryPicker-Cw-XRjAa.js +1 -0
  10. package/dist/client/assets/DocumentsView-CusClN9u.js +1 -0
  11. package/dist/client/assets/EvalsView-gNdeUDww.js +1 -0
  12. package/dist/client/assets/ExperimentalAgentOnboardingModal-Bmzbqzhs.js +1 -0
  13. package/dist/client/assets/{GoalsView-DPj59B3l.js → GoalsView-J8JMsoLn.js} +1 -1
  14. package/dist/client/assets/{InsightsView-QLJNkKJp.js → InsightsView-BVbv56K0.js} +3 -3
  15. package/dist/client/assets/{MemoryView-CDCS-1ig.js → MemoryView-DNvJFoDu.js} +1 -1
  16. package/dist/client/assets/{PiExtensionsManager-DktXXrmF.js → PiExtensionsManager-BPMexS34.js} +2 -2
  17. package/dist/client/assets/PluginManager-DGEv-ptu.js +1 -0
  18. package/dist/client/assets/{PullRequestView-CkObT6e3.js → PullRequestView-CF7fx-Uo.js} +2 -2
  19. package/dist/client/assets/ReportModal-B8S5BFgn.js +21 -0
  20. package/dist/client/assets/ReportModal-Dx3f2aj7.css +1 -0
  21. package/dist/client/assets/{ResearchView-CryFrV8l.js → ResearchView-CBeXsevy.js} +1 -1
  22. package/dist/client/assets/{SecretsView-9YcNW_fo.js → SecretsView-Dmi9wZkv.js} +1 -1
  23. package/dist/client/assets/SettingsModal-D2kXP7Um.js +21 -0
  24. package/dist/client/assets/{SettingsModal-llkoaJev.js → SettingsModal-DSW3xnGk.js} +1 -1
  25. package/dist/client/assets/{SettingsTextareaRow-B_Legu-A.js → SettingsTextareaRow-CLab4Vcd.js} +1 -1
  26. package/dist/client/assets/SetupWizardModal-Ct6juX9x.js +2 -0
  27. package/dist/client/assets/{SkillsView-CSeauwIw.js → SkillsView-Dn0bwT6i.js} +1 -1
  28. package/dist/client/assets/WorkflowNodeEditor-cvReMlG-.js +8 -0
  29. package/dist/client/assets/{agent-import-generation-CttglSmZ.js → agent-import-generation-C8_ewVzC.js} +1 -1
  30. package/dist/client/assets/{agentsOrgChartLayout-f-9mwRbD.js → agentsOrgChartLayout-p1i6XROQ.js} +1 -1
  31. package/dist/client/assets/{app-C_PTWuI1.js → app-BOvA34XN.js} +3 -3
  32. package/dist/client/assets/{app-BBSLJDbV.js → app-Bic4iWXQ.js} +3 -3
  33. package/dist/client/assets/{app-Bvr57EZQ.js → app-BlbH7Tir.js} +2 -2
  34. package/dist/client/assets/{app-DwvelD-n.js → app-C6TctczU.js} +3 -3
  35. package/dist/client/assets/{app-DRW5hIgr.js → app-D3qZmEIu.js} +3 -3
  36. package/dist/client/assets/{app-BKwOvuxE.js → app-DLnMkUt5.js} +2 -2
  37. package/dist/client/assets/{app-DKx18PHE.js → app-mNy0DeDM.js} +3 -3
  38. package/dist/client/assets/{architectureDiagram-3BPJPVTR-DA_Hm_di.js → architectureDiagram-3BPJPVTR-CzCk1QdH.js} +1 -1
  39. package/dist/client/assets/{blockDiagram-GPEHLZMM-JF7K8CcV.js → blockDiagram-GPEHLZMM-74Rj-5ov.js} +1 -1
  40. package/dist/client/assets/{c4Diagram-AAUBKEIU-DN-wklCP.js → c4Diagram-AAUBKEIU-B570qYH-.js} +1 -1
  41. package/dist/client/assets/channel-DWAK5y-J.js +1 -0
  42. package/dist/client/assets/{chunk-2J33WTMH-ChtjU8Cu.js → chunk-2J33WTMH-DejJkxt6.js} +1 -1
  43. package/dist/client/assets/{chunk-4BX2VUAB-dJL0n3nn.js → chunk-4BX2VUAB-DlgxkBuE.js} +1 -1
  44. package/dist/client/assets/{chunk-55IACEB6-Bfg-QB9A.js → chunk-55IACEB6-XCfE8PwC.js} +1 -1
  45. package/dist/client/assets/{chunk-727SXJPM-BHPPwYUS.js → chunk-727SXJPM-D-nDw0Bi.js} +1 -1
  46. package/dist/client/assets/{chunk-AQP2D5EJ-DIIpPUQN.js → chunk-AQP2D5EJ-C4KySao0.js} +1 -1
  47. package/dist/client/assets/{chunk-FMBD7UC4-D230R32b.js → chunk-FMBD7UC4-CXKdLygA.js} +1 -1
  48. package/dist/client/assets/{chunk-ND2GUHAM-0Lhp5CRv.js → chunk-ND2GUHAM-bNYWWGVJ.js} +1 -1
  49. package/dist/client/assets/{chunk-QZHKN3VN-BxbHBfKJ.js → chunk-QZHKN3VN-cfBQJ-MX.js} +1 -1
  50. package/dist/client/assets/classDiagram-4FO5ZUOK-WTkXRkfm.js +1 -0
  51. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-WTkXRkfm.js +1 -0
  52. package/dist/client/assets/{common-13IRj_PO.js → common-BsNuuNOe.js} +1 -1
  53. package/dist/client/assets/{common-BBynATth.js → common-CASsTuSW.js} +1 -1
  54. package/dist/client/assets/{common-BG-vw0tL.js → common-CfyFt5OG.js} +1 -1
  55. package/dist/client/assets/{common-DSo46rnH.js → common-DS98trLj.js} +1 -1
  56. package/dist/client/assets/common-DeoHWJCq.js +1 -0
  57. package/dist/client/assets/common-PpMdoH5r.js +1 -0
  58. package/dist/client/assets/{common-vpHuuvkd.js → common-cN--mrmm.js} +1 -1
  59. package/dist/client/assets/{cose-bilkent-S5V4N54A-3vEwhfYz.js → cose-bilkent-S5V4N54A-CiZrg3mQ.js} +1 -1
  60. package/dist/client/assets/{dagre-BM42HDAG-Br44UsdY.js → dagre-BM42HDAG-Bckph2U4.js} +1 -1
  61. package/dist/client/assets/{dashboard-view-_EglxMDl.js → dashboard-view-CN_fkDM1.js} +1 -1
  62. package/dist/client/assets/{dashboard-view-BldxxYfz.js → dashboard-view-CVYHQZwx.js} +1 -1
  63. package/dist/client/assets/dashboard-view-DDRKwfFs.js +1 -0
  64. package/dist/client/assets/{dashboard-view-CcPcELPx.js → dashboard-view-IuPjDVGa.js} +2 -2
  65. package/dist/client/assets/{diagram-2AECGRRQ-CLNxbHUP.js → diagram-2AECGRRQ-Bnaurex7.js} +1 -1
  66. package/dist/client/assets/{diagram-5GNKFQAL-D3cNAeQH.js → diagram-5GNKFQAL-BKz1omVN.js} +1 -1
  67. package/dist/client/assets/{diagram-KO2AKTUF-DkX7h6to.js → diagram-KO2AKTUF-C51lEZwo.js} +1 -1
  68. package/dist/client/assets/{diagram-LMA3HP47-6iQIiYUr.js → diagram-LMA3HP47-BYm5gql7.js} +1 -1
  69. package/dist/client/assets/{diagram-OG6HWLK6-Caje3229.js → diagram-OG6HWLK6-B9CFA4ha.js} +1 -1
  70. package/dist/client/assets/{erDiagram-TEJ5UH35-BkU-1HB1.js → erDiagram-TEJ5UH35-BLyCSssl.js} +1 -1
  71. package/dist/client/assets/{flowDiagram-I6XJVG4X-BRx3V6RE.js → flowDiagram-I6XJVG4X-yDVmpkro.js} +1 -1
  72. package/dist/client/assets/{folder-open-BaSOBfk2.js → folder-open-Cf2NA9nV.js} +1 -1
  73. package/dist/client/assets/{ganttDiagram-6RSMTGT7-D9f1kH3t.js → ganttDiagram-6RSMTGT7-mC9YPFcx.js} +1 -1
  74. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CQwmZcRd.js → gitGraphDiagram-PVQCEYII-DS0bEccv.js} +1 -1
  75. package/dist/client/assets/index-BjM7LxzY.js +2805 -0
  76. package/dist/client/assets/index-DcKIzuMk.css +1 -0
  77. package/dist/client/assets/{infoDiagram-5YYISTIA-DYWBkGjG.js → infoDiagram-5YYISTIA-CuuNZITP.js} +1 -1
  78. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-Df0Nzvh4.js → ishikawaDiagram-YF4QCWOH-MBSaC94m.js} +1 -1
  79. package/dist/client/assets/{journeyDiagram-JHISSGLW-bSvrZSyZ.js → journeyDiagram-JHISSGLW-DkaAow9E.js} +1 -1
  80. package/dist/client/assets/{kanban-definition-UN3LZRKU-yHJ101M8.js → kanban-definition-UN3LZRKU-DSf5OLtq.js} +1 -1
  81. package/dist/client/assets/{mermaid.core-Bc_0VLJw.js → mermaid.core-HmTn21MF.js} +4 -4
  82. package/dist/client/assets/{mindmap-definition-RKZ34NQL-DWRnMguM.js → mindmap-definition-RKZ34NQL-sv0Dl8aI.js} +1 -1
  83. package/dist/client/assets/{pieDiagram-4H26LBE5-Ds-DEOqr.js → pieDiagram-4H26LBE5-BDK2IQNq.js} +1 -1
  84. package/dist/client/assets/{puzzle-CdYF81IT.js → puzzle-D00mP67o.js} +1 -1
  85. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Bz-j2fkf.js → quadrantDiagram-W4KKPZXB-CiWAhwf1.js} +1 -1
  86. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BaQ_PaZ-.js → requirementDiagram-4Y6WPE33-DwC99D35.js} +1 -1
  87. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-pUCz8V4-.js → sankeyDiagram-5OEKKPKP-CQn8z721.js} +1 -1
  88. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CFwUMspe.js → sequenceDiagram-3UESZ5HK-B0CT8-vw.js} +1 -1
  89. package/dist/client/assets/{standing-instructions-template-Crocrob7.js → standing-instructions-template-BIBO_Prr.js} +2 -2
  90. package/dist/client/assets/{stateDiagram-AJRCARHV-CHZwo-vd.js → stateDiagram-AJRCARHV-BYAB_dFF.js} +1 -1
  91. package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-BTvKaIZR.js → stateDiagram-v2-BHNVJYJU-Cd19uJBk.js} +1 -1
  92. package/dist/client/assets/{timeline-definition-PNZ67QCA-Cn3XIoz2.js → timeline-definition-PNZ67QCA-DQLh8XkY.js} +1 -1
  93. package/dist/client/assets/{upload--GqImz6h.js → upload-D4pkNOz2.js} +1 -1
  94. package/dist/client/assets/{users-B0h1q4x6.js → users-COgviS_S.js} +1 -1
  95. package/dist/client/assets/{vennDiagram-CIIHVFJN-CS0FNVU_.js → vennDiagram-CIIHVFJN-BmwG1Wud.js} +1 -1
  96. package/dist/client/assets/{wardley-L42UT6IY-DdYkfF5d.js → wardley-L42UT6IY-BiO7jkmj.js} +1 -1
  97. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-B_rFmPCh.js → wardleyDiagram-YWT4CUSO-Dq0IPg5H.js} +1 -1
  98. package/dist/client/assets/{xychartDiagram-2RQKCTM6-CCoaCgmc.js → xychartDiagram-2RQKCTM6-BlMOlSBc.js} +1 -1
  99. package/dist/client/index.html +13 -6
  100. package/dist/client/theme-data.css +85 -0
  101. package/dist/client/version.json +1 -1
  102. package/dist/droid-cli/package.json +1 -1
  103. package/dist/extension.js +42201 -38907
  104. package/dist/migrations/0065_fn_149_review_convergence_stage.sql +3 -0
  105. package/dist/pi-claude-cli/package.json +1 -1
  106. package/dist/plugin-sdk/index.d.ts +62 -11
  107. package/dist/plugin-sdk/index.js +140 -46
  108. package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +195 -49
  109. package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
  110. package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +140 -46
  111. package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
  112. package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +140 -46
  113. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  114. package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +140 -46
  115. package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
  116. package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +140 -46
  117. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  118. package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +140 -46
  119. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  120. package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +140 -46
  121. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  122. package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +140 -46
  123. package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
  124. package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +140 -46
  125. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  126. package/dist/plugins/fusion-plugin-linear-import/bundled.js +140 -46
  127. package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
  128. package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +140 -46
  129. package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
  130. package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +140 -46
  131. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  132. package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +140 -46
  133. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  134. package/dist/plugins/fusion-plugin-quality/bundled.js +140 -46
  135. package/dist/plugins/fusion-plugin-quality/package.json +1 -1
  136. package/dist/plugins/fusion-plugin-reports/bundled.js +140 -46
  137. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  138. package/dist/plugins/fusion-plugin-roadmap/bundled.js +140 -46
  139. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  140. package/dist/plugins/fusion-plugin-todos/bundled.js +140 -46
  141. package/dist/plugins/fusion-plugin-todos/package.json +1 -1
  142. package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +140 -46
  143. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  144. package/package.json +1 -1
  145. package/skill/fusion/references/engine-tools.md +5 -5
  146. package/dist/client/assets/ChatView-DS4XiCm_.css +0 -1
  147. package/dist/client/assets/ChatView-zKrUSqiQ.js +0 -13
  148. package/dist/client/assets/DevServerView-CjTneoG7.js +0 -1
  149. package/dist/client/assets/DirectoryPicker-BY6V5HLV.js +0 -1
  150. package/dist/client/assets/DocumentsView-RDK56-qg.js +0 -1
  151. package/dist/client/assets/EvalsView-DKK4ceUW.js +0 -1
  152. package/dist/client/assets/ExperimentalAgentOnboardingModal-DiBPZVwC.js +0 -1
  153. package/dist/client/assets/PluginManager-CQ3iEFMq.js +0 -1
  154. package/dist/client/assets/ReportModal-B5LTdDgi.js +0 -21
  155. package/dist/client/assets/ReportModal-lzN_xrnM.css +0 -1
  156. package/dist/client/assets/SessionTerminal-2ZSXmOkG.css +0 -1
  157. package/dist/client/assets/SessionTerminal-BWsA9puD.js +0 -2
  158. package/dist/client/assets/SettingsModal-CL6aiXiI.js +0 -21
  159. package/dist/client/assets/SetupWizardModal-DLA4UAGp.js +0 -2
  160. package/dist/client/assets/WorkflowNodeEditor-CGgMiiWy.js +0 -8
  161. package/dist/client/assets/channel-CwFfFSI9.js +0 -1
  162. package/dist/client/assets/classDiagram-4FO5ZUOK-C8dZsxxX.js +0 -1
  163. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C8dZsxxX.js +0 -1
  164. package/dist/client/assets/common-DbOCE-0i.js +0 -1
  165. package/dist/client/assets/common-DnXF4Jmj.js +0 -1
  166. package/dist/client/assets/dashboard-view-B0OM3KYC.js +0 -1
  167. package/dist/client/assets/index-B8PcG8AJ.js +0 -2774
  168. package/dist/client/assets/index-Dki2LBAp.css +0 -1
  169. package/dist/client/assets/shield-alert-4qeU3_Rm.js +0 -6
  170. package/dist/client/assets/useDiscoveredSkillsCache-BEHgTFai.js +0 -1
@@ -0,0 +1,3 @@
1
+ -- FN-149 durable bounded review-convergence state.
2
+ ALTER TABLE project.tasks ADD COLUMN IF NOT EXISTS review_convergence_stage integer DEFAULT 0;
3
+ ALTER TABLE project.tasks ADD COLUMN IF NOT EXISTS review_convergence_escalation_count integer DEFAULT 0;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion/pi-claude-cli",
3
- "version": "0.77.0-beta.6",
3
+ "version": "0.77.0-beta.8",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "main": "index.ts",
@@ -233,7 +233,7 @@ type WorkflowStepMode = "prompt" | "script";
233
233
  type WorkflowStepToolMode = "readonly" | "coding";
234
234
  type WorkflowStepGateMode = "gate" | "advisory";
235
235
  type WorkflowReviewFindingSeverity = "low" | "medium" | "high" | "critical";
236
- type WorkflowReviewFindingResolution = "open" | "resolved-in-review" | "superseded";
236
+ type WorkflowReviewFindingResolution = "open" | "resolved-in-review" | "superseded" | "dispute-upheld";
237
237
  interface WorkflowReviewFinding {
238
238
  id: string;
239
239
  title: string;
@@ -242,6 +242,10 @@ interface WorkflowReviewFinding {
242
242
  line?: number;
243
243
  severity?: WorkflowReviewFindingSeverity;
244
244
  resolution?: WorkflowReviewFindingResolution;
245
+ disputeRationale?: string;
246
+ disputedAt?: string;
247
+ disputeRebuttedAt?: string;
248
+ rebutsDisputedFindingId?: string;
245
249
  }
246
250
  interface WorkflowRepositoryReviewOutcome {
247
251
  repository: string;
@@ -327,6 +331,14 @@ interface WorkflowStepResult {
327
331
  findings?: WorkflowReviewFinding[];
328
332
  repositoryReviewOutcomes?: WorkflowRepositoryReviewOutcome[];
329
333
  repositoryScopeRevision?: number;
334
+ remediationArchivedAt?: string;
335
+ remediationArchivedFromStatus?: WorkflowStepResult["status"];
336
+ reviewInputFingerprint?: string;
337
+ arbitrationDecision?: "UPHOLD_REVIEW" | "UPHOLD_IMPLEMENTER" | "SPLIT";
338
+ arbitrationBindingFindingCount?: number;
339
+ arbitratedAttemptAt?: string;
340
+ arbitratedAt?: string;
341
+ arbitrationNotes?: string;
330
342
  supersededFindingSourceWorkflowStepId?: string;
331
343
  supersededFindingIds?: string[];
332
344
  verdict?: "APPROVE" | "APPROVE_WITH_NOTES" | "REVISE" | "CLOSE_NO_OP";
@@ -338,7 +350,7 @@ interface WorkflowStepResult {
338
350
  bypassedBy?: string;
339
351
  bypassedAt?: string;
340
352
  bypassReason?: string;
341
- bypassedFromStatus?: WorkflowStepResult["status"];
353
+ bypassedFromStatus?: WorkflowStepResult["status"] | "absent";
342
354
  bypassedFromVerdict?: WorkflowStepResult["verdict"];
343
355
  supersededAt?: string;
344
356
  supersededReason?: "dependency-change";
@@ -610,6 +622,8 @@ interface TaskRow {
610
622
  branchConflictRecoveryCount: number | null;
611
623
  reviewerContextRetryCount: number | null;
612
624
  reviewerFallbackRetryCount: number | null;
625
+ reviewConvergenceStage: number | null;
626
+ reviewConvergenceEscalationCount: number | null;
613
627
  nextRecoveryAt: string | null;
614
628
  error: string | null;
615
629
  summary: string | null;
@@ -1188,7 +1202,7 @@ interface CustomFieldRejection {
1188
1202
  detail: string;
1189
1203
  }
1190
1204
 
1191
- type WorkflowLifecycleWarningCode = "missing-completion-summary" | "missing-merge-region" | "unsafe-terminal-before-merge" | "optional-group-after-execution" | "review-gate-without-failure-route";
1205
+ type WorkflowLifecycleWarningCode = "missing-completion-summary" | "missing-merge-region" | "unsafe-terminal-before-merge" | "optional-group-after-execution" | "review-gate-without-failure-route" | "write-capable-node-after-code-review";
1192
1206
  interface WorkflowLifecycleWarning {
1193
1207
  code: WorkflowLifecycleWarningCode;
1194
1208
  nodeId?: string;
@@ -5593,6 +5607,8 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5593
5607
  branchConflictRecoveryCount?: number | null;
5594
5608
  reviewerContextRetryCount?: number | null;
5595
5609
  reviewerFallbackRetryCount?: number | null;
5610
+ reviewConvergenceStage?: number | null;
5611
+ reviewConvergenceEscalationCount?: number | null;
5596
5612
  nextRecoveryAt?: string | null;
5597
5613
  enabledWorkflowSteps?: string[];
5598
5614
  noCommitsExpected?: boolean | null;
@@ -5698,9 +5714,10 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5698
5714
  dismissAiMergeReviewFinding(taskId: string, findingId: string, reason: string, actor?: string): Promise<Task>;
5699
5715
  linkTaskRecommendation(id: string, recommendationId: string, createdTaskId: string, completeColumns?: ReadonlySet<string>): Promise<Task>;
5700
5716
  normalizeWorkspaceTaskWorktreeMetadata(id: string): Promise<Task>;
5701
- mergeWorkspaceWorktreeEntry(id: string, repoRelPath: string, patch: Partial<WorkspaceWorktreeEntry>, options?: {
5717
+ mergeWorkspaceWorktreeEntry(id: string, repoRelPath: string, patch: Partial<WorkspaceWorktreeEntry> | ((current: Task) => Promise<Partial<WorkspaceWorktreeEntry>>), options?: {
5702
5718
  requireExistingEntry?: boolean;
5703
5719
  clearSingularWorktree?: boolean;
5720
+ validateBeforePersist?: (current: Task) => Promise<void>;
5704
5721
  }): Promise<Task>;
5705
5722
  updateTaskRepositoryScope(id: string, repositoryScope: TaskRepositoryScope | undefined): Promise<Task>;
5706
5723
  mutateTaskRepositoryScope(id: string, mutation: TaskRepositoryScopeMutation): Promise<Task>;
@@ -5758,6 +5775,12 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5758
5775
  checkAndRecordUnplannedExecutionBlock(id: string, episode: string): Promise<boolean>;
5759
5776
  transitionQueuedEpisode(id: string, transition: QueuedEpisodeTransition): Promise<QueuedEpisodeTransitionResult>;
5760
5777
  logEntry(id: string, action: string, outcome?: string, runContext?: RunMutationContext): Promise<Task>;
5778
+ logEntryOnce(id: string, input: {
5779
+ action: string;
5780
+ outcome?: string;
5781
+ dedupeKey: string;
5782
+ windowMs: number;
5783
+ }): Promise<boolean>;
5761
5784
  getMutationsForRun(runId: string): Promise<TaskLogEntry[]>;
5762
5785
  rowToMergeQueueEntry(row: MergeQueueRow): MergeQueueEntry;
5763
5786
  normalizeMergeRequestState(value: string): MergeRequestState;
@@ -5792,6 +5815,7 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5792
5815
  }): Promise<MergeRequestRecord>;
5793
5816
  getMergeRequestRecord(taskId: string): MergeRequestRecord | null;
5794
5817
  getMergeRequestRecordAsync(taskId: string): Promise<MergeRequestRecord | null>;
5818
+ getMergeRequestRecordsAsync(taskIds: readonly string[]): Promise<Map<string, MergeRequestRecord>>;
5795
5819
  projectMergeRequestToWorkflowWorkItem(taskId: string, opts?: MergeRequestWorkflowProjectionOptions): Promise<WorkflowWorkItem | null>;
5796
5820
  createCompletionHandoffWorkflowWork(task: Pick<Task, "id" | "autoMerge" | "priority">, opts?: {
5797
5821
  runId?: string;
@@ -5804,6 +5828,13 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5804
5828
  replaceActiveTaskWorkflowContinuation(input: WorkflowWorkItemUpsertInput & {
5805
5829
  kind: "task";
5806
5830
  }): Promise<WorkflowWorkItem>;
5831
+ seedWorkspaceCodeReviewContinuationIfIdle(input: WorkflowWorkItemUpsertInput & {
5832
+ kind: "task";
5833
+ }): Promise<{
5834
+ seeded: boolean;
5835
+ reason?: "active-continuation";
5836
+ workItemId?: string;
5837
+ }>;
5807
5838
  seedStrandedPlanReviewContinuation(input: WorkflowWorkItemUpsertInput & {
5808
5839
  kind: "task";
5809
5840
  }, options?: {
@@ -5819,6 +5850,9 @@ declare class TaskStore extends EventEmitter<TaskStoreEvents> {
5819
5850
  listWorkflowWorkItemsForTask(taskId: string, opts?: {
5820
5851
  kinds?: WorkflowWorkItemKind[];
5821
5852
  }): Promise<WorkflowWorkItem[]>;
5853
+ listWorkflowWorkItemsForTasks(taskIds: readonly string[], opts?: {
5854
+ kinds?: WorkflowWorkItemKind[];
5855
+ }): Promise<Map<string, WorkflowWorkItem[]>>;
5822
5856
  listWorkflowWorkItemsForTaskSync(taskId: string, opts?: {
5823
5857
  kinds?: WorkflowWorkItemKind[];
5824
5858
  }): WorkflowWorkItem[];
@@ -6803,7 +6837,7 @@ declare const ANTHROPIC_AUTH_PREFERENCES: readonly ["api-key", "subscription"];
6803
6837
  type AnthropicAuthPreference = (typeof ANTHROPIC_AUTH_PREFERENCES)[number];
6804
6838
  declare const THEME_MODES: readonly ["dark", "light", "system"];
6805
6839
  type ThemeMode = (typeof THEME_MODES)[number];
6806
- declare const COLOR_THEMES: readonly ["default", "ocean", "forest", "sunset", "zen", "berry", "high-contrast", "industrial", "monochrome", "slate", "ash", "air", "graphite", "silver", "solarized", "factory", "factory-mono", "ayu", "one-dark", "nord", "dracula", "gruvbox", "tokyo-night", "catppuccin-mocha", "github-dark", "everforest", "rose-pine", "kanagawa", "night-owl", "palenight", "monokai-pro", "slime", "brutalist", "neon-city", "parchment", "medieval", "terminal", "glass", "glass-silver", "horizon", "vitesse", "outrun", "snazzy", "porple", "espresso", "mars", "poimandres", "ember", "rust", "copper", "foundry", "carbon", "sandstone", "lagoon", "frost", "lavender", "neon-bloom", "sepia", "cobalt", "clay", "moss", "aurora", "calm", "dawn", "sage", "midnight", "velvet", "factory-dark", "factory-light", "shadcn", "shadcn-ember", "shadcn-custom", "shadcn-blue", "shadcn-green", "shadcn-red", "shadcn-purple", "shadcn-pink", "shadcn-orange", "shadcn-yellow", "shadcn-mono", "shadcn-mono-red", "shadcn-mono-blue", "shadcn-mono-green", "shadcn-mono-purple", "shadcn-mono-pink", "shadcn-mono-orange", "shadcn-mono-yellow", "shadcn-black", "shadcn-gray", "shadcn-gray-blue"];
6840
+ declare const COLOR_THEMES: readonly ["default", "ocean", "forest", "sunset", "zen", "berry", "high-contrast", "industrial", "monochrome", "slate", "ash", "air", "graphite", "silver", "solarized", "factory", "factory-mono", "ayu", "one-dark", "nord", "dracula", "gruvbox", "tokyo-night", "catppuccin-mocha", "github-dark", "everforest", "rose-pine", "kanagawa", "night-owl", "palenight", "monokai-pro", "slime", "brutalist", "neon-city", "parchment", "medieval", "terminal", "glass", "glass-silver", "horizon", "vitesse", "outrun", "snazzy", "porple", "espresso", "mars", "poimandres", "ember", "rust", "copper", "foundry", "carbon", "sandstone", "lagoon", "frost", "lavender", "neon-bloom", "sepia", "cobalt", "clay", "moss", "aurora", "calm", "dawn", "sage", "midnight", "velvet", "iceberg", "factory-dark", "factory-light", "shadcn", "shadcn-ember", "shadcn-custom", "shadcn-blue", "shadcn-green", "shadcn-red", "shadcn-purple", "shadcn-pink", "shadcn-orange", "shadcn-yellow", "shadcn-mono", "shadcn-mono-red", "shadcn-mono-blue", "shadcn-mono-green", "shadcn-mono-purple", "shadcn-mono-pink", "shadcn-mono-orange", "shadcn-mono-yellow", "shadcn-black", "shadcn-gray", "shadcn-gray-blue"];
6807
6841
  type ColorTheme = (typeof COLOR_THEMES)[number];
6808
6842
  declare const SUPPORTED_LOCALES: readonly ["en", "zh-CN", "zh-TW", "fr", "es", "ko", "pt-BR"];
6809
6843
  type Locale = (typeof SUPPORTED_LOCALES)[number];
@@ -6943,6 +6977,7 @@ interface TaskLogEntry {
6943
6977
  timestamp: string;
6944
6978
  action: string;
6945
6979
  outcome?: string;
6980
+ dedupeKey?: string;
6946
6981
  runContext?: RunMutationContext;
6947
6982
  }
6948
6983
  type WorkflowTransitionNotificationKind = "manual-merge-hold" | "recovery-requeue";
@@ -7008,7 +7043,7 @@ type TaskReviewVerdict = "APPROVE" | "APPROVE_WITH_NOTES" | "REVISE" | "RETHINK"
7008
7043
  type TaskReviewerType = "plan" | "code";
7009
7044
  type TaskReviewItemStatus = "queued" | "in-progress" | "addressed" | "failed";
7010
7045
  type TaskReviewFindingSeverity = "low" | "medium" | "high" | "critical";
7011
- type TaskReviewFindingResolution = "open" | "resolved-in-review" | "superseded";
7046
+ type TaskReviewFindingResolution = "open" | "resolved-in-review" | "superseded" | "dispute-upheld";
7012
7047
  interface LegacyTaskReviewItem {
7013
7048
  id: string;
7014
7049
  source: TaskReviewSource;
@@ -7620,6 +7655,16 @@ interface TaskRepositoryScope {
7620
7655
  refusalReason?: string;
7621
7656
  }>;
7622
7657
  }
7658
+ interface WorkspaceLandFailure {
7659
+ category: "environment" | "review" | "content-conflict" | "internal-technical";
7660
+ message: string;
7661
+ at: string;
7662
+ branch?: string;
7663
+ repository?: string;
7664
+ resource?: string;
7665
+ action?: string;
7666
+ technicalDetail?: string;
7667
+ }
7623
7668
  interface WorkspaceWorktreeEntry {
7624
7669
  worktreePath: string;
7625
7670
  branch: string;
@@ -7628,11 +7673,7 @@ interface WorkspaceWorktreeEntry {
7628
7673
  baseCommitSha?: string;
7629
7674
  landedSha?: string;
7630
7675
  revertBoundarySha?: string;
7631
- landFailure?: {
7632
- message: string;
7633
- at: string;
7634
- branch?: string;
7635
- };
7676
+ landFailure?: WorkspaceLandFailure;
7636
7677
  }
7637
7678
  type AiMergeFindingDisposition = "pending" | "corrected" | "absent-from-squash" | "still-present" | "dismissed";
7638
7679
  interface AiMergeReviewFinding {
@@ -7654,6 +7695,7 @@ interface AiMergeReviewReconciliation {
7654
7695
  findings: AiMergeReviewFinding[];
7655
7696
  consecutiveCleanApprovals: number;
7656
7697
  correctivePasses: number;
7698
+ invalidAcknowledgementCandidateSha?: string;
7657
7699
  terminal?: boolean;
7658
7700
  }
7659
7701
  interface Task {
@@ -7781,6 +7823,8 @@ interface Task {
7781
7823
  branchConflictRecoveryCount?: number;
7782
7824
  reviewerContextRetryCount?: number;
7783
7825
  reviewerFallbackRetryCount?: number;
7826
+ reviewConvergenceStage?: number;
7827
+ reviewConvergenceEscalationCount?: number;
7784
7828
  retrySummary?: RetrySummary;
7785
7829
  nextRecoveryAt?: string;
7786
7830
  awaitingApprovalReason?: "release-authorization" | "plan-review-replan-cap" | "merge-blocked-by-policy" | "code-review-non-convergence";
@@ -8176,6 +8220,7 @@ interface GlobalSettings {
8176
8220
  openrouterModelFilters?: OpenRouterModelFilters;
8177
8221
  openrouterProviderPreferences?: OpenRouterProviderPreferences;
8178
8222
  opencodeGoModelSync?: boolean;
8223
+ orcarouterModelSync?: boolean;
8179
8224
  updateCheckEnabled?: boolean;
8180
8225
  fnBinaryCheckEnabled?: boolean;
8181
8226
  githubTrackingDefaultRepo?: string;
@@ -8357,6 +8402,12 @@ interface ProjectSettings {
8357
8402
  executorEscalationProvider?: string;
8358
8403
  executorEscalationModelId?: string;
8359
8404
  executorEscalationNodeId?: string;
8405
+ reviewConvergenceEscalationEnabled?: boolean;
8406
+ reviewConvergenceEscalationProvider?: string;
8407
+ reviewConvergenceEscalationModelId?: string;
8408
+ reviewArbitrationEnabled?: boolean;
8409
+ reviewArbitrationProvider?: string;
8410
+ reviewArbitrationModelId?: string;
8360
8411
  maxConcurrentVerifications?: number;
8361
8412
  maxWorktrees: number;
8362
8413
  worktreeLimitEnabled?: boolean;
@@ -5879,6 +5879,8 @@ var tasks = projectSchema.table("tasks", {
5879
5879
  branchConflictRecoveryCount: integer("branch_conflict_recovery_count").default(0),
5880
5880
  reviewerContextRetryCount: integer("reviewer_context_retry_count").default(0),
5881
5881
  reviewerFallbackRetryCount: integer("reviewer_fallback_retry_count").default(0),
5882
+ reviewConvergenceStage: integer("review_convergence_stage").default(0),
5883
+ reviewConvergenceEscalationCount: integer("review_convergence_escalation_count").default(0),
5882
5884
  nextRecoveryAt: text("next_recovery_at"),
5883
5885
  error: text("error"),
5884
5886
  summary: text("summary"),
@@ -8199,7 +8201,16 @@ var projectTableNames = [
8199
8201
  "chat_rooms",
8200
8202
  "chat_room_members",
8201
8203
  "chat_room_messages",
8202
- "chat_token_usage"
8204
+ "chat_token_usage",
8205
+ /*
8206
+ FNXC:WorkspaceCoordination 2026-08-23-20:05:
8207
+ FN-9059 (migration 0060) added these two tables to the schema without registering them here, so
8208
+ every registry consumer under-counted them: the PostgreSQL test harness never TRUNCATEd them
8209
+ between tests (a held `repo:<repo>` lease leaked from one case into the next and made the next
8210
+ land report the previous test's successor as the busy holder), and health compaction skipped them.
8211
+ */
8212
+ "workspace_coordination_leases",
8213
+ "workspace_land_intents"
8203
8214
  ];
8204
8215
 
8205
8216
  // ../core/src/postgres/schema/central.ts
@@ -8976,6 +8987,7 @@ var DEFAULT_GLOBAL_SETTINGS = {
8976
8987
  openrouterAppAttribution: void 0,
8977
8988
  openrouterModelFilters: void 0,
8978
8989
  openrouterProviderPreferences: void 0,
8990
+ orcarouterModelSync: true,
8979
8991
  opencodeGoModelSync: true,
8980
8992
  updateCheckEnabled: true,
8981
8993
  fnBinaryCheckEnabled: true,
@@ -9391,6 +9403,16 @@ var DEFAULT_PROJECT_SETTINGS = {
9391
9403
  executorEscalationProvider: void 0,
9392
9404
  executorEscalationModelId: void 0,
9393
9405
  executorEscalationNodeId: void 0,
9406
+ /*
9407
+ FNXC:ReviewConvergence 2026-08-23-21:05:
9408
+ FN-149's six review-convergence/arbitration keys are declared in BUILTIN_WORKFLOW_SETTINGS, which
9409
+ the U4 hard-move made the SINGLE source of truth for a moved key's default. Re-declaring them here
9410
+ put them back in the legacy object the hard-move emptied, so an undeclared key on a custom workflow
9411
+ could resolve to this literal instead of the declaration default — the exact drift
9412
+ `workflow-settings-fallback-alignment` guards. The declaration defaults are identical (both
9413
+ `*Enabled` default true, the provider/model lanes carry no default), and the reader uses
9414
+ `!== false`, so removing them here preserves behaviour and restores the invariant.
9415
+ */
9394
9416
  /**
9395
9417
  * FNXC:Merge 2026-06-26-00:00:
9396
9418
  * New and unconfigured projects default AI merge to sync a dirty checked-out integration branch, restoring the legacy stash → fast-forward → restore landing behavior. Explicit persisted merger.allowDirtyLocalCheckoutSync values still win, and no existing-project migration stamps this default into storage.
@@ -10282,6 +10304,20 @@ function classifyWorkflowAgentNode(node) {
10282
10304
  }
10283
10305
  }
10284
10306
 
10307
+ // ../core/src/workflows/workflow-merge-region.ts
10308
+ var MERGE_REGION_ENTRY_NODE_KINDS = /* @__PURE__ */ new Set([
10309
+ "merge-gate",
10310
+ "merge-attempt",
10311
+ "manual-merge-hold",
10312
+ "retry-backoff",
10313
+ "recovery-router",
10314
+ "branch-group-member-integration",
10315
+ "branch-group-promotion",
10316
+ "pr-create",
10317
+ "pr-respond",
10318
+ "pr-merge"
10319
+ ]);
10320
+
10285
10321
  // ../core/src/workflows/workflow-extension-types.ts
10286
10322
  function workflowExtensionRegistryId(pluginId, extensionId) {
10287
10323
  return `plugin:${pluginId}:${extensionId}`;
@@ -10810,18 +10846,7 @@ function reachableFrom(start, outgoing) {
10810
10846
  }
10811
10847
  return seen;
10812
10848
  }
10813
- var INTERPRETER_ENTRY_NODE_KINDS = /* @__PURE__ */ new Set([
10814
- "merge-gate",
10815
- "merge-attempt",
10816
- "manual-merge-hold",
10817
- "retry-backoff",
10818
- "recovery-router",
10819
- "branch-group-member-integration",
10820
- "branch-group-promotion",
10821
- "pr-create",
10822
- "pr-respond",
10823
- "pr-merge"
10824
- ]);
10849
+ var INTERPRETER_ENTRY_NODE_KINDS = MERGE_REGION_ENTRY_NODE_KINDS;
10825
10850
  var MERGE_CLASS_NODE_KINDS = /* @__PURE__ */ new Set([
10826
10851
  "merge-gate",
10827
10852
  "merge-attempt",
@@ -12461,6 +12486,49 @@ var BUILTIN_REVIEW_REVISION_SETTINGS = [
12461
12486
  default: DEFAULT_CODE_REVIEW_BLOCKING_SEVERITY,
12462
12487
  description: 'Minimum finding severity that lets Code Review block merge. A REVISE carrying no finding at or above this level is recorded as APPROVE_WITH_NOTES and its findings are handed to the implementer. Choose "any" to block on every REVISE.'
12463
12488
  },
12489
+ /*
12490
+ * FNXC:ReviewConvergence 2026-08-22-05:42:
12491
+ * FN-149 keeps recovery targets workflow-native so operators choose the cost and
12492
+ * capability of automatic review convergence without widening project policy.
12493
+ */
12494
+ {
12495
+ id: "reviewConvergenceEscalationEnabled",
12496
+ name: "Review convergence escalation",
12497
+ type: "boolean",
12498
+ default: true,
12499
+ description: "Run one bounded alternate-model or replan recovery when a review repeats unchanged input."
12500
+ },
12501
+ {
12502
+ id: "reviewConvergenceEscalationProvider",
12503
+ name: "Review convergence escalation provider",
12504
+ type: "string",
12505
+ description: "Provider for the optional alternate-model review remediation target."
12506
+ },
12507
+ {
12508
+ id: "reviewConvergenceEscalationModelId",
12509
+ name: "Review convergence escalation model",
12510
+ type: "string",
12511
+ description: "Model for the optional alternate-model review remediation target."
12512
+ },
12513
+ {
12514
+ id: "reviewArbitrationEnabled",
12515
+ name: "Review arbitration",
12516
+ type: "boolean",
12517
+ default: true,
12518
+ description: "Enable bounded third-model arbitration after a review disagreement persists."
12519
+ },
12520
+ {
12521
+ id: "reviewArbitrationProvider",
12522
+ name: "Review arbitration provider",
12523
+ type: "string",
12524
+ description: "Provider for the optional review arbitration target."
12525
+ },
12526
+ {
12527
+ id: "reviewArbitrationModelId",
12528
+ name: "Review arbitration model",
12529
+ type: "string",
12530
+ description: "Model for the optional review arbitration target."
12531
+ },
12464
12532
  {
12465
12533
  id: "planReviewReplanCap",
12466
12534
  name: "Plan Review replan cap",
@@ -12666,16 +12734,11 @@ You have tools to report progress. The board updates in real-time.
12666
12734
 
12667
12735
  /*
12668
12736
  FNXC:TaskRecommendations 2026-08-09-04:06:
12669
- FN-8850 requires optional, non-blocking discoveries to be captured only at the explicit accepted
12670
- completion boundary. Immediate task creation remains for required dependency coordination or an
12671
- operator-directed filing, while workflow step sessions remain unable to write recommendations.
12737
+ FN-125 requires task-execution sessions to preserve optional, non-blocking discoveries only at the
12738
+ accepted completion boundary. Durable Workflow Executor sessions cannot create or delegate tasks;
12739
+ in-scope work remains in the current task and external blockers use the honest blocked exit.
12672
12740
  */
12673
- **Out-of-scope findings at completion:** Do not automatically create a task for optional, non-blocking work discovered outside this task. When recommendation capture is enabled, at the final accepted \`fn_task_done(outcome="completed")\` checkpoint evaluate genuine task-ready follow-ups and send \`recommendations\` (or \`recommendations: []\` when none qualify). Each recommendation needs a stable unique \`id\`, \`title\`, \`description\`, and \`category\`; never use it for a required current-task fix, blocker, secret, executable command, reasoning transcript, or filler.
12674
-
12675
- Use \`task_create\` or \`fn_delegate_task\` only when the task explicitly requires immediate filing, necessary dependency coordination, or the operator directs it. When creating multiple related tasks, declare dependencies between them:
12676
- \`task_create(description="load door sounds", dependencies=[])\` \u2192 returns KB-050
12677
- \`task_create(description="play sound on door open/close", dependencies=["KB-050"])\`
12678
-
12741
+ **Out-of-scope findings at completion:** This task-execution session cannot create or delegate tasks. When recommendation capture is enabled, at the final accepted \`fn_task_done(outcome="completed")\` checkpoint evaluate optional, non-blocking findings as genuine task-ready \`recommendations\` (or \`recommendations: []\` when none qualify). Each recommendation needs a stable unique \`id\`, \`title\`, \`description\`, and \`category\`; never use it for a required current-task fix, blocker, secret, executable command, reasoning transcript, or filler. Implement required in-scope work directly in this task.
12679
12742
  **Discovered a dependency:** \`task_add_dep(task_id="KB-XXX")\` \u2014 use when you discover mid-execution that another task must be completed first. This will return a warning first \u2014 you must call again with \`confirm=true\` to proceed. Adding a dependency stops execution, discards current work, and moves the task to triage for re-specification.
12680
12743
 
12681
12744
  ## Task Documents
@@ -12747,16 +12810,16 @@ If you attempt to write to a path outside the worktree, the file tools will reje
12747
12810
  FNXC:WorkflowRouting 2026-06-22-17:26:
12748
12811
  Executors must not move the workflow of the task they are executing unless the user explicitly asked for that task's workflow. Agents remain free to set workflows on tasks they create because they are the creator for those new tasks.
12749
12812
  -->
12750
- - Do not call \`fn_workflow_select\` to change the workflow of the task you are executing; you did not create that task, the user or triage did. The only exception is when the user explicitly requested a specific workflow for this task in a steering comment, task instruction, or similar direct instruction. You may still set the workflow on tasks you create via \`fn_task_create\` or \`fn_delegate_task\`, because you are the creator of those new tasks.
12813
+ - Do not call \`fn_workflow_select\` to change the workflow of the task you are executing; you did not create that task, the user or triage did. The only exception is when the user explicitly requested a specific workflow for this task in a steering comment, task instruction, or similar direct instruction.
12751
12814
  - **NEVER kill processes on port 4040.** Port 4040 is the production dashboard. Do not run \`kill\`, \`pkill\`, \`killall\`, or \`lsof -ti:4040 | xargs kill\` against it. If you need to start a test server, use \`--port 0\` for a random free port. If port 4040 is occupied, pick a different port \u2014 do NOT kill the occupant.
12752
12815
  - Treat the File Scope in PROMPT.md as the expected starting scope, not a hard boundary when quality gates fail
12753
12816
  - Read "Context to Read First" files before starting
12754
12817
  - Follow the "Do NOT" section strictly
12755
12818
  - If tests, lint, build, or typecheck fail and the fix requires touching code outside the declared File Scope, fix those failures directly and keep the repo green
12756
- - Use \`task_create\` for genuinely separate follow-up work, not for mandatory fixes required to make this task land cleanly
12819
+ - Implement mandatory and in-scope work directly in this task. Preserve optional out-of-scope follow-ups as completion recommendations.
12757
12820
  - Update documentation listed in "Must Update" and check "Check If Affected"
12758
12821
  - NEVER delete, remove, or gut modules, interfaces, settings, exports, or test files outside your File Scope
12759
- - NEVER remove features as "cleanup" \u2014 if something seems unused, create a task for investigation instead
12822
+ - NEVER remove features as "cleanup" \u2014 if something seems unused, record an optional completion recommendation for investigation instead
12760
12823
  - Removing code is acceptable ONLY when it is explicitly part of your task's mission
12761
12824
  - If you remove existing functionality, you MUST create a changeset in \`.changeset/\` explaining the removal and rationale
12762
12825
 
@@ -12803,6 +12866,13 @@ Lint, tests, and typecheck are also hard quality gates:
12803
12866
  - Keep fixing failures caused by your change until lint, impacted tests, build, and typecheck pass.
12804
12867
  - If the repository exposes a typecheck command, run it and fix failures caused by your change.
12805
12868
  - When tests fail, classify whether the failure is caused by your change, a pre-existing defect, an unrelated flaky test, or an outdated test expectation.
12869
+
12870
+ **A behavior change owns every test that asserts the old behavior.** Targeted verification runs the tests for files you TOUCHED; the tests encoding the behavior you just changed usually live in files you did NOT touch, so a green targeted run is not evidence that none exist. Before finishing, search for them:
12871
+ - Added a guard, validation, or required field? Grep for the FIXTURES it will now refuse \u2014 they are outside your File Scope \u2014 and fix each to state its intent explicitly.
12872
+ - Removed a feature? Delete its tests. A test asserting a deliberately removed contract guards nothing, and making it pass later means re-adding removed behavior.
12873
+ - Changed an order, default, constant, or prompt string? Grep for the literal; topology lists, prompt-content assertions, and size budgets live far from the code they describe.
12874
+ - Added a public store/service method? Update the inventory/drift guards that require every public surface to be classified.
12875
+ Fix at the SHARED FIXTURE FACTORY, not per test \u2014 one helper usually explains dozens of failures. Never make a stale test pass by weakening it: update the fixture, record the new truth, or delete the test naming the change that removed its subject.
12806
12876
  - If broad workspace verification fails on unrelated or pre-existing failures after impacted checks pass, do NOT expand this task by fixing unrelated areas. Log the evidence, quarantine flakes per project policy, or create/link a follow-up task.
12807
12877
  - Do not repeatedly rerun a broad failing or hanging workspace command without a new hypothesis and a narrower confirming command.
12808
12878
 
@@ -13075,6 +13145,7 @@ files with assertions that run via a test runner. Typechecks and builds are NOT
13075
13145
  tests. Manual verification is NOT a test.
13076
13146
 
13077
13147
  - Each implementation step should include writing tests for the code being changed
13148
+ - **If the task CHANGES, GATES, or REMOVES existing behavior, include a step to find and update the tests that assert the OLD behavior.** Name the search in that step: the fixtures a new guard will now refuse, the tests of a removed feature, or the literal to grep for a changed order/default/constant/prompt string. Those tests live OUTSIDE the File Scope, so targeted verification will not surface them and the executor will not find them by accident. Measured 2026-08-24: five such changes left ~135 stale failing tests behind, every one having passed its own targeted verification; one shared fixture line accounted for 37 of them.
13078
13149
  - For bug fixes and UI-affordance add/remove tasks, the spec MUST include a \`## Surface Enumeration\` section. The workflow Plan Review gate validates this before execution when plan review is enabled; missing coverage is a blocking REVISE.
13079
13150
  - For bug fixes and UI-affordance add/remove tasks, populate \`## Surface Enumeration\` with this checklist from \`docs/testing.md\`: providers/bridges/execution paths; desktop + mobile breakpoints/platforms; empty/undefined/duplicate/populated data states; shared hooks/components/modules/helpers; every component that renders the affordance; leftover shells after removal.
13080
13151
  - For bug fixes and UI-affordance add/remove tasks, regression tests must assert the invariant across all known surfaces \u2014 enumerate every provider/bridge, desktop + mobile breakpoints, empty/undefined/populated data states, and for UI-affordance changes every component rendering the affordance plus leftover shells after removal \u2014 not just the reported repro (see FN-5787/FN-5789/FN-5803, FN-5751, and FN-6115/FN-6118/FN-6123)
@@ -13430,7 +13501,7 @@ You have tools to report progress. The board updates in real-time.
13430
13501
 
13431
13502
  **Logging important actions:** \`task_log(message="what happened")\`
13432
13503
 
13433
- **Out-of-scope findings at completion:** When recommendation capture is enabled, retain optional, non-blocking discoveries as task-ready \`fn_task_done\` recommendations at accepted completion, or send \`recommendations: []\` when none qualify. Use \`task_create\` only for explicit immediate filing, dependency coordination, or operator direction; never recommend required current-task work, blockers, secrets, commands, reasoning, or filler.
13504
+ **Out-of-scope findings at completion:** This task-execution session cannot create or delegate tasks. When recommendation capture is enabled, retain optional, non-blocking discoveries as task-ready \`fn_task_done\` recommendations at accepted completion, or send \`recommendations: []\` when none qualify. Implement required in-scope work directly here; use the honest blocked exit only for a real external blocker. Never recommend required current-task work, blockers, secrets, commands, reasoning, or filler.
13434
13505
 
13435
13506
  **Discovered a dependency:** \`task_add_dep(task_id="KB-XXX")\` \u2014 use when you discover mid-execution that another task must be completed first. This will return a warning first \u2014 you must call again with \`confirm=true\` to proceed. Adding a dependency stops execution, discards current work, and moves the task to triage for re-specification.
13436
13507
 
@@ -13500,15 +13571,15 @@ If you attempt to write to a path outside the worktree, the file tools will reje
13500
13571
  FNXC:WorkflowRouting 2026-06-22-17:26:
13501
13572
  Executors must not move the workflow of the task they are executing unless the user explicitly asked for that task's workflow. Agents remain free to set workflows on tasks they create because they are the creator for those new tasks.
13502
13573
  -->
13503
- - Do not call \`fn_workflow_select\` to change the workflow of the task you are executing; you did not create that task, the user or triage did. The only exception is when the user explicitly requested a specific workflow for this task in a steering comment, task instruction, or similar direct instruction. You may still set the workflow on tasks you create via \`fn_task_create\` or \`fn_delegate_task\`, because you are the creator of those new tasks.
13574
+ - Do not call \`fn_workflow_select\` to change the workflow of the task you are executing; you did not create that task, the user or triage did. The only exception is when the user explicitly requested a specific workflow for this task in a steering comment, task instruction, or similar direct instruction.
13504
13575
  - **NEVER kill processes on port 4040.** Port 4040 is the production dashboard. Do not run \`kill\`, \`pkill\`, \`killall\`, or \`lsof -ti:4040 | xargs kill\` against it. If you need to start a test server, use \`--port 0\` for a random free port. If port 4040 is occupied, pick a different port \u2014 do NOT kill the occupant.
13505
13576
  - Treat the File Scope in PROMPT.md as the expected starting scope, not a hard boundary when quality gates fail
13506
13577
  - Read "Context to Read First" files before starting
13507
13578
  - Follow the "Do NOT" section strictly
13508
13579
  - If tests, lint, build, or typecheck fail and the fix requires touching code outside the declared File Scope, fix those failures directly and keep the repo green
13509
- - Use \`task_create\` for genuinely separate follow-up work, not for mandatory fixes required to make this task land cleanly
13580
+ - Implement mandatory and in-scope work directly in this task. Preserve optional out-of-scope follow-ups as completion recommendations.
13510
13581
  - NEVER delete, remove, or gut modules, interfaces, settings, exports, or test files outside your File Scope
13511
- - NEVER remove features as "cleanup" \u2014 if something seems unused, create a task for investigation instead
13582
+ - NEVER remove features as "cleanup" \u2014 if something seems unused, record an optional completion recommendation for investigation instead
13512
13583
  - If you remove existing functionality, you MUST create a changeset in \`.changeset/\` explaining the removal and rationale
13513
13584
 
13514
13585
  ## Spawning Child Agents
@@ -14375,11 +14446,15 @@ var RAW_BUILTIN_CODING_WORKFLOW_IR = {
14375
14446
  // execute → browser-verification (optional-group) → review. When the group is
14376
14447
  // disabled it passes through with outcome=success and routes straight to review.
14377
14448
  { from: "execute", to: "browser-verification", condition: "success" },
14378
- // browser-verification → code-review → review. Each optional-group passes through with
14379
- // outcome=success when disabled, so a task with both off routes straight to review.
14380
- { from: "browser-verification", to: "code-review", condition: "success" },
14381
- { from: "code-review", to: "completion-summary", condition: "success" },
14382
- { from: "completion-summary", to: "review", condition: "success" },
14449
+ /*
14450
+ FNXC:WorkspaceReviewSeal 2026-08-21-19:36:
14451
+ Completion summary runs before Code Review because its agent may acquire and write the task
14452
+ worktree. The approving review is the final write-capable pre-merge stage, so landing consumes
14453
+ evidence for the branch it will publish rather than evidence invalidated by a later summary.
14454
+ */
14455
+ { from: "browser-verification", to: "completion-summary", condition: "success" },
14456
+ { from: "completion-summary", to: "code-review", condition: "success" },
14457
+ { from: "code-review", to: "review", condition: "success" },
14383
14458
  { from: "review", to: "merge-gate", condition: "success" },
14384
14459
  { from: "merge-gate", to: "branch-group-member-integration", condition: "outcome:auto-on" },
14385
14460
  { from: "merge-gate", to: "merge-manual-hold", condition: "outcome:auto-off" },
@@ -14392,6 +14467,12 @@ var RAW_BUILTIN_CODING_WORKFLOW_IR = {
14392
14467
  { from: "merge-attempt", to: "post-merge-verification", condition: "success" },
14393
14468
  { from: "post-merge-verification", to: "end", condition: "success" },
14394
14469
  { from: "merge-attempt", to: "merge-retry", condition: "outcome:transient-failure" },
14470
+ /*
14471
+ FNXC:WorkspaceReviewReroute 2026-08-21-20:11:
14472
+ Evidence rejected during an active graph merge is a fresh Code Review obligation, never a
14473
+ merge retry. Route the typed result to the final review gate before another landing attempt.
14474
+ */
14475
+ { from: "merge-attempt", to: "code-review", condition: "outcome:workspace-review-required", kind: "rework" },
14395
14476
  { from: "merge-attempt", to: "merge-manual-hold", condition: "outcome:manual-required" },
14396
14477
  { from: "recovery-router", to: "merge-attempt", condition: "outcome:wake-merge", kind: "rework" },
14397
14478
  { from: "planning", to: "end", condition: "failure" },
@@ -14689,12 +14770,15 @@ var RAW_BUILTIN_STEPWISE_CODING_WORKFLOW_IR = {
14689
14770
  // KTD-5: bounded rework exhaustion → manual hold; release re-enters the group.
14690
14771
  { from: "steps", to: "rework-hold", condition: "outcome:rework-exhausted" },
14691
14772
  { from: "rework-hold", to: "browser-verification", condition: "success" },
14692
- // browser-verification → code-review → completion-summary → merge-gate; each
14693
- // optional-group passes through (outcome=success) when disabled, so a task with
14694
- // both off routes straight to completion summary and merge policy.
14695
- { from: "browser-verification", to: "code-review", condition: "success" },
14696
- { from: "code-review", to: "completion-summary", condition: "success" },
14697
- { from: "completion-summary", to: "merge-gate", condition: "success" },
14773
+ /*
14774
+ FNXC:WorkspaceReviewSeal 2026-08-21-19:36:
14775
+ A completion-summary agent can acquire the task worktree. It therefore precedes Code Review;
14776
+ the approval becomes the final write-sensitive pre-merge gate and cannot be invalidated by the
14777
+ built-in workflow after it is recorded.
14778
+ */
14779
+ { from: "browser-verification", to: "completion-summary", condition: "success" },
14780
+ { from: "completion-summary", to: "code-review", condition: "success" },
14781
+ { from: "code-review", to: "merge-gate", condition: "success" },
14698
14782
  { from: "browser-verification", to: "browser-verification-remediation", condition: "failure" },
14699
14783
  { from: "browser-verification-remediation", to: "browser-verification", condition: "success", kind: "rework" },
14700
14784
  { from: "code-review", to: "code-review-remediation", condition: "failure" },
@@ -14720,6 +14804,12 @@ var RAW_BUILTIN_STEPWISE_CODING_WORKFLOW_IR = {
14720
14804
  { from: "merge-attempt", to: "post-merge-verification", condition: "success" },
14721
14805
  { from: "post-merge-verification", to: "end", condition: "success" },
14722
14806
  { from: "merge-attempt", to: "merge-retry", condition: "outcome:transient-failure" },
14807
+ /*
14808
+ FNXC:WorkspaceReviewReroute 2026-08-21-20:11:
14809
+ A stale workspace approval returns to the final Code Review gate through a bounded rework
14810
+ edge, preserving the existing graph owner instead of burning a merge retry.
14811
+ */
14812
+ { from: "merge-attempt", to: "code-review", condition: "outcome:workspace-review-required", kind: "rework" },
14723
14813
  { from: "merge-attempt", to: "merge-manual-hold", condition: "outcome:manual-required" },
14724
14814
  { from: "recovery-router", to: "merge-attempt", condition: "outcome:wake-merge", kind: "rework" },
14725
14815
  { from: "merge-attempt", to: "end", condition: "failure" }
@@ -14782,11 +14872,11 @@ var RAW_BUILTIN_STEPWISE_FINAL_REVIEW_CODING_WORKFLOW_IR = (() => {
14782
14872
  if (!ir.edges.some((edge) => edge.from === "plan-replan" && edge.to === "plan-review" && edge.condition === "success")) {
14783
14873
  ir.edges.push({ from: "plan-replan", to: "plan-review", condition: "success", kind: "rework" });
14784
14874
  }
14785
- if (!ir.edges.some((edge) => edge.from === "code-review" && edge.to === "completion-summary" && edge.condition === "success")) {
14786
- ir.edges.push({ from: "code-review", to: "completion-summary", condition: "success" });
14875
+ if (!ir.edges.some((edge) => edge.from === "completion-summary" && edge.to === "code-review" && edge.condition === "success")) {
14876
+ ir.edges.push({ from: "completion-summary", to: "code-review", condition: "success" });
14787
14877
  }
14788
- if (!ir.edges.some((edge) => edge.from === "completion-summary" && edge.to === "merge-gate" && edge.condition === "success")) {
14789
- ir.edges.push({ from: "completion-summary", to: "merge-gate", condition: "success" });
14878
+ if (!ir.edges.some((edge) => edge.from === "code-review" && edge.to === "merge-gate" && edge.condition === "success")) {
14879
+ ir.edges.push({ from: "code-review", to: "merge-gate", condition: "success" });
14790
14880
  }
14791
14881
  return ir;
14792
14882
  })();
@@ -14866,8 +14956,8 @@ var RAW_BUILTIN_CODING_IDEAS_WORKFLOW_IR = (() => {
14866
14956
  ]);
14867
14957
  v2.nodes = v2.nodes.filter((node) => !removedNodeIds.has(node.id));
14868
14958
  v2.edges = v2.edges.filter((edge) => !removedNodeIds.has(edge.from) && !removedNodeIds.has(edge.to));
14869
- if (!v2.edges.some((edge) => edge.from === "steps" && edge.to === "code-review")) {
14870
- v2.edges.push({ from: "steps", to: "code-review", condition: "success" });
14959
+ if (!v2.edges.some((edge) => edge.from === "steps" && edge.to === "completion-summary")) {
14960
+ v2.edges.push({ from: "steps", to: "completion-summary", condition: "success" });
14871
14961
  }
14872
14962
  if (!v2.edges.some((edge) => edge.from === "merge-attempt" && edge.to === "end" && edge.condition === "success")) {
14873
14963
  v2.edges.push({ from: "merge-attempt", to: "end", condition: "success" });
@@ -15454,10 +15544,12 @@ function linear(spec) {
15454
15544
  ...hasBrowserVerification ? [browserVerificationRemediationNode("in-progress")] : [],
15455
15545
  ...hasCodeReview ? [codeReviewRemediationNode("in-progress")] : []
15456
15546
  ] : [];
15547
+ const noOpTerminalNode = hasPlanReview ? { id: "plan-review-no-op", kind: "gate", column: "todo", config: { workflowAction: "plan-review-no-op" } } : void 0;
15457
15548
  const nodes2 = [
15458
15549
  { id: "start", kind: "start" },
15459
15550
  ...workflowNodes,
15460
15551
  ...remediationNodes,
15552
+ ...noOpTerminalNode ? [noOpTerminalNode] : [],
15461
15553
  { id: "end", kind: "end" }
15462
15554
  ];
15463
15555
  const edges = [];
@@ -15473,6 +15565,8 @@ function linear(spec) {
15473
15565
  }
15474
15566
  if (hasPlanReview) {
15475
15567
  edges.push({ from: "plan-replan", to: "plan-review", condition: "success", kind: "rework" });
15568
+ edges.push({ from: "plan-review", to: "plan-review-no-op", condition: "outcome:close-no-op" });
15569
+ edges.push({ from: "plan-review-no-op", to: "end", condition: "success" });
15476
15570
  }
15477
15571
  if (hasBrowserVerification) {
15478
15572
  edges.push({