@runfusion/fusion 0.75.0-beta.1 → 0.75.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +389 -134
- package/dist/child-process-worker.js +224 -123
- package/dist/client/.vite/manifest.json +249 -249
- package/dist/client/assets/{AgentDetailView-CsCVX96A.js → AgentDetailView-C4Xpag_i.js} +1 -1
- package/dist/client/assets/{AgentPermissionPolicyEditor-Dh5wDe8g.js → AgentPermissionPolicyEditor-D-Fp7-sy.js} +1 -1
- package/dist/client/assets/{AgentsView-Dd_oZbFn.js → AgentsView-BmFsoY1Q.js} +3 -3
- package/dist/client/assets/{ChatView-gC7_BCmZ.js → ChatView-5KsB3BVO.js} +1 -1
- package/dist/client/assets/{CommandCenter-Bk6RQ-hm.js → CommandCenter-CacGI8AV.js} +1 -1
- package/dist/client/assets/{DevServerView-Da8h5OC-.js → DevServerView-DufjauVn.js} +1 -1
- package/dist/client/assets/{DirectoryPicker-DX9H1EdH.js → DirectoryPicker-DvwqfQDS.js} +1 -1
- package/dist/client/assets/{DocumentsView-BZ0g_Am7.js → DocumentsView-BbYJFIQ1.js} +1 -1
- package/dist/client/assets/{EvalsView-DsI_X6eQ.js → EvalsView-NBC8kOc-.js} +1 -1
- package/dist/client/assets/{ExperimentalAgentOnboardingModal-BfE5f-XK.js → ExperimentalAgentOnboardingModal-C809yXXY.js} +1 -1
- package/dist/client/assets/{GoalsView-43sqRFfC.js → GoalsView-CpNO9eI0.js} +1 -1
- package/dist/client/assets/{InsightsView-Dvgn_hrA.js → InsightsView-Cahy5FcR.js} +1 -1
- package/dist/client/assets/{MemoryView-DWbHznu3.js → MemoryView-BNJAQjqn.js} +1 -1
- package/dist/client/assets/{PiExtensionsManager-BKfmIRDt.js → PiExtensionsManager-DCHTyOmJ.js} +1 -1
- package/dist/client/assets/{PluginManager-xhkrAjSK.js → PluginManager-CBt-CqUz.js} +1 -1
- package/dist/client/assets/{PullRequestView-CyEwGgRD.js → PullRequestView-Dsb9RwmX.js} +1 -1
- package/dist/client/assets/{ReportModal--NSmch5M.js → ReportModal-8FjZOcbC.js} +1 -1
- package/dist/client/assets/{ResearchView-CgqZlNMD.js → ResearchView-DlSG7dOd.js} +1 -1
- package/dist/client/assets/{SecretsView-am_ZT9z8.js → SecretsView-BSajNE-f.js} +1 -1
- package/dist/client/assets/{SessionTerminal-DSc_7NQ-.js → SessionTerminal-M2fIpHrL.js} +1 -1
- package/dist/client/assets/{SettingsModal-Bp6sytUe.js → SettingsModal-DLcvlp44.js} +3 -3
- package/dist/client/assets/{SettingsModal-D2jjC8m8.js → SettingsModal-z6gOf7dG.js} +1 -1
- package/dist/client/assets/{SettingsTextareaRow-DjJJD-Af.js → SettingsTextareaRow-DeC19053.js} +1 -1
- package/dist/client/assets/{SetupWizardModal-DLIeefbh.js → SetupWizardModal-BOjMePFh.js} +2 -2
- package/dist/client/assets/{SkillsView-C67Gdb5y.js → SkillsView-BSBEC-Xm.js} +1 -1
- package/dist/client/assets/{WorkflowNodeEditor-BxhdNPdn.js → WorkflowNodeEditor-DZ9-RBqo.js} +1 -1
- package/dist/client/assets/{agent-import-generation-Bk9fEowy.js → agent-import-generation-COItiXMT.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-s2YViNU1.js → architectureDiagram-3BPJPVTR-BwlCePoB.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DMsf6VWl.js → blockDiagram-GPEHLZMM-KKrLi9v4.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-DXJExfmV.js → c4Diagram-AAUBKEIU-CkIDt_8M.js} +1 -1
- package/dist/client/assets/channel-CeYcnOtQ.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CH99GAl7.js → chunk-2J33WTMH-D9sbdaqY.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-BTV9SXg5.js → chunk-4BX2VUAB-D3DtFoAY.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-ntvLX3jz.js → chunk-55IACEB6-gxblxRIN.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DBNBtu-e.js → chunk-727SXJPM-D0AEDoHN.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DvbtWh_x.js → chunk-AQP2D5EJ-BweoM7qY.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CUdRlAnf.js → chunk-FMBD7UC4-sjblhrjI.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-B7J-met1.js → chunk-ND2GUHAM-CYuRENSs.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-D7CahWp7.js → chunk-QZHKN3VN-CFKJr4kG.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CZwh2k1X.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CZwh2k1X.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-6E0Aaw7K.js → cose-bilkent-S5V4N54A-6Jb6SgHM.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-Wi236AfH.js → dagre-BM42HDAG-FQJ87Ol3.js} +1 -1
- package/dist/client/assets/{dashboard-view-CrHqKsfL.js → dashboard-view-B1Rq2-73.js} +1 -1
- package/dist/client/assets/{dashboard-view-NpkFaG9s.js → dashboard-view-DH1Zo0m4.js} +1 -1
- package/dist/client/assets/{dashboard-view-hLsXVJJN.js → dashboard-view-DVMZNVoc.js} +1 -1
- package/dist/client/assets/{dashboard-view-BZDf9tzC.js → dashboard-view-DgLbkn5n.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-B3TxtVcq.js → diagram-2AECGRRQ-CKYOu9to.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-45Y_FHjp.js → diagram-5GNKFQAL-DPwjFnde.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-D4w3m4cp.js → diagram-KO2AKTUF-DzZS9Nk3.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-Dv5F4ha2.js → diagram-LMA3HP47-DW9e5YSP.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CvOQ1IYN.js → diagram-OG6HWLK6-C7V3Mj63.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DYcp25dX.js → erDiagram-TEJ5UH35-DSQzBA0e.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DnjuETCJ.js → flowDiagram-I6XJVG4X-BUuOq9tO.js} +1 -1
- package/dist/client/assets/{folder-open-ovJcpdOX.js → folder-open-DXNu4ED4.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-SU7_CTa4.js → ganttDiagram-6RSMTGT7-Bc32G_Ef.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DFvxZu8I.js → gitGraphDiagram-PVQCEYII-Cvfa0W6a.js} +1 -1
- package/dist/client/assets/{index-C_ZHzU4F.js → index-C5YdAqNQ.js} +14 -14
- package/dist/client/assets/index-DHk_s6rA.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-DgMEfdKk.js → infoDiagram-5YYISTIA-TqRUTfvy.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CFjnOb7V.js → ishikawaDiagram-YF4QCWOH-D33iop1_.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-46dGsf_j.js → journeyDiagram-JHISSGLW-DH-TDR5Y.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-9-nz-BFT.js → kanban-definition-UN3LZRKU-CAcebzyW.js} +1 -1
- package/dist/client/assets/{mermaid.core-CYHDO5ss.js → mermaid.core-C3Nh1Sak.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BYQE0Nqo.js → mindmap-definition-RKZ34NQL-CSIccWV8.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BNSMLSjW.js → pieDiagram-4H26LBE5-hXJ3G3MR.js} +1 -1
- package/dist/client/assets/{puzzle-D2SwAtRX.js → puzzle-DI3elldh.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CNdSBA7P.js → quadrantDiagram-W4KKPZXB-B3wpvneC.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-B6EJvc9H.js → requirementDiagram-4Y6WPE33-DPpYL2ca.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-8DcYdUmL.js → sankeyDiagram-5OEKKPKP-BS9QXSEF.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BjRXhtKa.js → sequenceDiagram-3UESZ5HK-C_fqU0MW.js} +1 -1
- package/dist/client/assets/{shield-alert-b4thCabv.js → shield-alert-CzZYSqmH.js} +1 -1
- package/dist/client/assets/{standing-instructions-template-B1X-jWip.js → standing-instructions-template-CsXA4WMZ.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-Btrn_84P.js → stateDiagram-AJRCARHV-DbSZrprS.js} +1 -1
- package/dist/client/assets/{stateDiagram-v2-BHNVJYJU-DiyZxQF1.js → stateDiagram-v2-BHNVJYJU-Cf_ckwmM.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CjEYU1kO.js → timeline-definition-PNZ67QCA-B1ohvKjs.js} +1 -1
- package/dist/client/assets/{upload-DMts5fzZ.js → upload-D7nNe9wD.js} +1 -1
- package/dist/client/assets/{users-C9O98ACz.js → users-B79Dvre4.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DtEb-r3I.js → vennDiagram-CIIHVFJN-CxZYCQ72.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-Ds-v1VZi.js → wardley-L42UT6IY-clJem8VU.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-C15pYn-T.js → wardleyDiagram-YWT4CUSO-zE8lyaWe.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-ChJ77iYU.js → xychartDiagram-2RQKCTM6-DsdjuSxQ.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/version.json +1 -1
- package/dist/droid-cli/package.json +1 -1
- package/dist/extension.js +242 -125
- package/dist/migrations/0000_initial.sql +1 -0
- package/dist/migrations/0044_fn_8785_queued_episode_signature.sql +3 -0
- package/dist/pi-claude-cli/package.json +1 -1
- package/dist/plugin-sdk/index.d.ts +16 -0
- package/dist/plugin-sdk/index.js +6 -5
- package/dist/plugins/fusion-plugin-acp-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-acp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-claude-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-claude-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-cli-printing-press/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
- package/dist/plugins/fusion-plugin-compound-engineering/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-compound-engineering/package.json +1 -1
- package/dist/plugins/fusion-plugin-cursor-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-dependency-graph/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
- package/dist/plugins/fusion-plugin-droid-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-grok-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-grok-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-hermes-runtime/.bundled.reload-3.js +19167 -0
- package/dist/plugins/fusion-plugin-hermes-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-linear-import/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-linear-import/package.json +1 -1
- package/dist/plugins/fusion-plugin-omp-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-omp-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-openclaw-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-paperclip-runtime/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
- package/dist/plugins/fusion-plugin-quality/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-quality/package.json +1 -1
- package/dist/plugins/fusion-plugin-reports/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-reports/package.json +1 -1
- package/dist/plugins/fusion-plugin-roadmap/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
- package/dist/plugins/fusion-plugin-todos/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-todos/package.json +1 -1
- package/dist/plugins/fusion-plugin-whatsapp-chat/bundled.js +6 -5
- package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
- package/package.json +1 -1
- package/dist/client/assets/channel-BRBjryTS.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-26ZYCgHv.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-26ZYCgHv.js +0 -1
- package/dist/client/assets/index-CJRmyxnw.css +0 -1
package/dist/extension.js
CHANGED
|
@@ -11845,6 +11845,11 @@ APPROVE when the plan is executable and verifiable, not when it is cosmetically
|
|
|
11845
11845
|
});
|
|
11846
11846
|
|
|
11847
11847
|
// ../core/src/agents/agent-prompts.ts
|
|
11848
|
+
function buildPlanningDuplicatePolicyInstruction() {
|
|
11849
|
+
return `## Duplicate policy for this task
|
|
11850
|
+
|
|
11851
|
+
Only active tasks can be duplicate blockers. A matching task in a done or archived column is historical evidence, not a duplicate verdict: inspect it for context, then write a new plan for the reported work or regression. Do not emit \`DUPLICATE: ...\` for completed or archived work.`;
|
|
11852
|
+
}
|
|
11848
11853
|
function buildTriageHeartbeatGuidance(options = {}) {
|
|
11849
11854
|
const noTaskLine = options.plannerHeartbeatPatrolEnabled === false ? TRIAGE_HEARTBEAT_PATROL_DISABLED_INSTRUCTION : "If no task is assigned: execute your planning instructions. Patrol for vague requests, blocked tasks that need better specification, review follow-ups that should become new tasks, and dependency gaps that are slowing executors down.";
|
|
11850
11855
|
const patrolSafetyLines = options.plannerHeartbeatPatrolEnabled === false ? "" : `
|
|
@@ -12136,7 +12141,7 @@ Write a lean, executable PROMPT.md quickly. Preserve safety gates, but skip heav
|
|
|
12136
12141
|
- Preserve required safety sections for bugs, workflow routing, forensic tasks, and decision-only work.
|
|
12137
12142
|
|
|
12138
12143
|
## Duplicate check
|
|
12139
|
-
Before writing a spec, call \`fn_task_list\` for active work, then call \`fn_task_search\` with 2-4 targeted keyword phrases from the title/description, such as file paths, symptoms, and symbols.
|
|
12144
|
+
Before writing a spec, call \`fn_task_list\` for active work, then call \`fn_task_search\` with \`includeDone: false\` and \`includeArchived: false\` for 2-4 targeted keyword phrases from the title/description, such as file paths, symptoms, and symbols. Do not search completed or archived work for duplicate candidates. When an active match is a duplicate, do not write a spec \u2014 but still write PROMPT.md, with its entire contents being the single line \`DUPLICATE: {existing-task-id}\` and nothing else. That file is how the duplicate is recorded; announcing it only in your reply leaves no plan behind and re-plans the task in a loop.
|
|
12140
12145
|
|
|
12141
12146
|
## Required PROMPT.md shape
|
|
12142
12147
|
Write PROMPT.md with Original Description, Before \u2192 After Transformation, Mission, Dependencies, Context to Read First, File Scope, Steps, Documentation Requirements, Completion Criteria, Git Commit Convention, and Do NOT. Put \`## Original Description\` immediately after the title/\`Created\`/\`Size\` metadata with the operator's original task description copied **verbatim** (do not paraphrase). Put \`## Before \u2192 After Transformation\` next, before \`## Mission\`, with concise Before/After bullets: current state, target state, why it satisfies the user's request at a glance. In \`## Steps\`, every executable heading MUST use \`### Step N: <name>\` (e.g. \`### Step 1: Preflight\`). Do not write bare \`### Preflight\` / \`### Implementation\` headings, and do not add review-level, triage subtask, or proactive subtask headings.
|
|
@@ -12404,9 +12409,9 @@ Verified facts about this codebase's storage \u2014 cite these correctly so Plan
|
|
|
12404
12409
|
- New Postgres migrations must be **registered explicitly** in \`packages/core/src/postgres/schema-applier.ts\` (version constant + bookkeeping check); a \`.sql\` file dropped in the migrations dir that is not wired there silently never runs.
|
|
12405
12410
|
|
|
12406
12411
|
## Duplicate check
|
|
12407
|
-
Before writing a spec, first call \`fn_task_list\` to see active tasks, then call \`fn_task_search\` with 2-4 distinct keyword phrases from the task title and description (for example file paths, error symptoms, and symbol names).
|
|
12408
|
-
|
|
12409
|
-
If
|
|
12412
|
+
Before writing a spec, first call \`fn_task_list\` to see active tasks, then call \`fn_task_search\` with \`includeDone: false\` and \`includeArchived: false\` for 2-4 distinct keyword phrases from the task title and description (for example file paths, error symptoms, and symbol names).
|
|
12413
|
+
Do not search completed or archived work for duplicate candidates.
|
|
12414
|
+
If an actionable task already covers the same work (even if worded differently), do not write a spec.
|
|
12410
12415
|
Instead you MUST still write PROMPT.md, with its ENTIRE contents being this one line and nothing else:
|
|
12411
12416
|
\`DUPLICATE: {existing-task-id}\`
|
|
12412
12417
|
Writing that file IS how you report the duplicate. Reporting it only in your reply is not recorded:
|
|
@@ -12437,7 +12442,7 @@ Workflow policy can disable proactive oversized-task splitting for operators who
|
|
|
12437
12442
|
## Triage tools
|
|
12438
12443
|
You have these extra tools during triage:
|
|
12439
12444
|
- \`fn_task_list\` \u2014 list existing active tasks
|
|
12440
|
-
- \`fn_task_search\` \u2014 keyword search across tasks
|
|
12445
|
+
- \`fn_task_search\` \u2014 keyword search across active tasks by default; history is opt-in for non-duplicate research
|
|
12441
12446
|
- \`fn_task_show\` \u2014 inspect a task and its PROMPT.md
|
|
12442
12447
|
- \`fn_task_create\` \u2014 create a child/follow-up task while triaging
|
|
12443
12448
|
- \`fn_task_document_write\` \u2014 save a planning document (e.g., key="plan")
|
|
@@ -20177,6 +20182,7 @@ var init_project = __esm({
|
|
|
20177
20182
|
worktree: text("worktree"),
|
|
20178
20183
|
blockedBy: text("blocked_by"),
|
|
20179
20184
|
overlapBlockedBy: text("overlap_blocked_by"),
|
|
20185
|
+
queuedLogEpisodeSignature: text("queued_log_episode_signature"),
|
|
20180
20186
|
paused: integer("paused").default(0),
|
|
20181
20187
|
userPaused: integer("user_paused").default(0),
|
|
20182
20188
|
pausedReason: text("paused_reason"),
|
|
@@ -24327,6 +24333,22 @@ var init_near_duplicate_canonical = __esm({
|
|
|
24327
24333
|
}
|
|
24328
24334
|
});
|
|
24329
24335
|
|
|
24336
|
+
// ../core/src/duplicates/near-duplicate-canonical-flags.ts
|
|
24337
|
+
async function resolveNearDuplicateCanonicalFlags(store, canonical) {
|
|
24338
|
+
if (!canonical?.column) return void 0;
|
|
24339
|
+
const workflow = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
24340
|
+
if (!workflow || workflow.version !== "v2") return void 0;
|
|
24341
|
+
const column = workflow.columns.find((candidate) => candidate.id === canonical.column);
|
|
24342
|
+
return column ? resolveColumnFlags(column) : void 0;
|
|
24343
|
+
}
|
|
24344
|
+
var init_near_duplicate_canonical_flags = __esm({
|
|
24345
|
+
"../core/src/duplicates/near-duplicate-canonical-flags.ts"() {
|
|
24346
|
+
"use strict";
|
|
24347
|
+
init_trait_registry();
|
|
24348
|
+
init_workflow_ir_resolver();
|
|
24349
|
+
}
|
|
24350
|
+
});
|
|
24351
|
+
|
|
24330
24352
|
// ../core/src/git/gitlab-tracking.ts
|
|
24331
24353
|
function formatGitLabTrackedItemRef(item) {
|
|
24332
24354
|
const marker = item.kind === "merge_request" ? "!" : "#";
|
|
@@ -38088,6 +38110,7 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
38088
38110
|
const taskLifecycleConsumersAlreadyApplied = applied.includes(TASK_LIFECYCLE_CONSUMERS_VERSION);
|
|
38089
38111
|
const validatorInputFingerprintAlreadyApplied = applied.includes(VALIDATOR_INPUT_FINGERPRINT_VERSION);
|
|
38090
38112
|
const unplannedExecutionBlockDedupeAlreadyApplied = applied.includes(UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION);
|
|
38113
|
+
const queuedEpisodeSignatureAlreadyApplied = applied.includes(QUEUED_EPISODE_SIGNATURE_VERSION);
|
|
38091
38114
|
assertBinaryNotOlderThanDatabase(applied);
|
|
38092
38115
|
let schemaChanged = false;
|
|
38093
38116
|
if (!baselineAlreadyApplied) {
|
|
@@ -38481,17 +38504,23 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
38481
38504
|
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
38482
38505
|
schemaChanged = true;
|
|
38483
38506
|
}
|
|
38507
|
+
if (!queuedEpisodeSignatureAlreadyApplied) {
|
|
38508
|
+
const migrationSql = await readFile4(QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, "utf8");
|
|
38509
|
+
await tx.execute(sql.raw(migrationSql));
|
|
38510
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${QUEUED_EPISODE_SIGNATURE_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
38511
|
+
schemaChanged = true;
|
|
38512
|
+
}
|
|
38484
38513
|
return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
|
|
38485
38514
|
});
|
|
38486
38515
|
}
|
|
38487
|
-
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH;
|
|
38516
|
+
var SCHEMA_BASELINE_VERSION, TASK_DECLARED_SYMBOLS_VERSION, INITIAL_SCHEMA_VERSION, AUTOMATION_ISOLATION_SCHEMA_VERSION, ANALYTICS_ISOLATION_SCHEMA_VERSION, MONITOR_APPROVAL_ISOLATION_SCHEMA_VERSION, LEGACY_CUTOVER_PRESERVATION_SCHEMA_VERSION, MULTI_PROJECT_CUTOVER_SCHEMA_VERSION, PROJECT_OWNERSHIP_SCHEMA_VERSION, SQLITE_SCHEMA_PARITY_VERSION, SESSION_ADVISOR_ENABLED_SCHEMA_VERSION, MISSION_FIX_IDEMPOTENCY_VERSION, IMPORT_TRANSLATION_CACHE_VERSION, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_VERSION, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_VERSION, OWNER_PROJECT_ID_SPLIT_VERSION, CHAT_SESSION_PINS_VERSION, EXECUTOR_TOOL_FAILURE_RETRY_VERSION, EXECUTOR_ESCALATION_ATTEMPT_VERSION, GLOBAL_ROUTINES_SCHEMA_VERSION, TASK_MERGER_MODEL_LANE_VERSION, BULK_COMPLETION_REFUSAL_AT_VERSION, TASK_PROPOSAL_CLAIM_VERSION, CONFIGURATION_REVISIONS_VERSION, IDEATION_SCHEMA_VERSION, RESEARCH_FEATURE_PROVENANCE_VERSION, TASK_VERIFICATION_REQUEST_VERSION, SYMBOL_LOCKS_SCHEMA_VERSION, BIGINT_COUNTERS_VERSION, PLANNING_ACTIVE_TIMING_VERSION, SQLITE_MIGRATION_RUNTIME_READ_VERSION, WORKFLOW_TASK_CONTINUATIONS_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_VERSION, TASK_WEDGE_NOTIFICATION_VERSION, MILESTONE_ASSERTION_PROVENANCE_VERSION, MISSION_LINEAGE_STOP_VERSION, CHAT_SESSION_TAGS_VERSION, DROP_GLOBAL_CONCURRENCY_VERSION, MISSION_TASK_PREFIX_VERSION, CREDENTIAL_INSTANCE_SELECTION_VERSION, TASK_LIFECYCLE_OUTBOX_VERSION, TASK_LIFECYCLE_CONSUMERS_VERSION, VALIDATOR_INPUT_FINGERPRINT_VERSION, UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION, QUEUED_EPISODE_SIGNATURE_VERSION, LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION, StaleBinarySchemaError, MIGRATION_BOOKKEEPING_TABLE, LEGACY_ADOPTION_DRAINED_MARKER, __dirname, MIGRATIONS_DIR, BASELINE_MIGRATION_PATH, AUTOMATION_ISOLATION_MIGRATION_PATH, ANALYTICS_ISOLATION_MIGRATION_PATH, MONITOR_APPROVAL_ISOLATION_MIGRATION_PATH, LEGACY_CUTOVER_PRESERVATION_MIGRATION_PATH, MULTI_PROJECT_CUTOVER_MIGRATION_PATH, PROJECT_OWNERSHIP_MIGRATION_PATH, SQLITE_SCHEMA_PARITY_MIGRATION_PATH, SESSION_ADVISOR_ENABLED_MIGRATION_PATH, MISSION_FIX_IDEMPOTENCY_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_SCOPE_FIX_MIGRATION_PATH, IMPORT_TRANSLATION_CACHE_LEGACY_PARTITION_BACKFILL_MIGRATION_PATH, OWNER_PROJECT_ID_SPLIT_MIGRATION_PATH, CHAT_SESSION_PINS_MIGRATION_PATH, EXECUTOR_TOOL_FAILURE_RETRY_MIGRATION_PATH, EXECUTOR_ESCALATION_ATTEMPT_MIGRATION_PATH, GLOBAL_ROUTINES_MIGRATION_PATH, TASK_MERGER_MODEL_LANE_MIGRATION_PATH, BULK_COMPLETION_REFUSAL_AT_MIGRATION_PATH, TASK_PROPOSAL_CLAIM_MIGRATION_PATH, CONFIGURATION_REVISIONS_MIGRATION_PATH, IDEATION_MIGRATION_PATH, RESEARCH_FEATURE_PROVENANCE_MIGRATION_PATH, TASK_VERIFICATION_REQUEST_MIGRATION_PATH, SYMBOL_LOCKS_MIGRATION_PATH, BIGINT_COUNTERS_MIGRATION_PATH, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_VERSION, WORKFLOW_IR_PIN_AND_LEGACY_ADOPTION_MIGRATION_PATH, PLANNING_ACTIVE_TIMING_MIGRATION_PATH, TASK_DECLARED_SYMBOLS_MIGRATION_PATH, SQLITE_MIGRATION_RUNTIME_READ_PATH, WORKFLOW_TASK_CONTINUATIONS_PATH, LEGACY_ADOPTION_DRAINED_MARKER_RUNTIME_GRANTS_PATH, TASK_WEDGE_NOTIFICATION_MIGRATION_PATH, MILESTONE_ASSERTION_PROVENANCE_MIGRATION_PATH, MISSION_LINEAGE_STOP_MIGRATION_PATH, CHAT_SESSION_TAGS_MIGRATION_PATH, DROP_GLOBAL_CONCURRENCY_MIGRATION_PATH, MISSION_TASK_PREFIX_MIGRATION_PATH, CREDENTIAL_INSTANCE_SELECTION_MIGRATION_PATH, TASK_LIFECYCLE_OUTBOX_MIGRATION_PATH, TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH, VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH, UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH, QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH;
|
|
38488
38517
|
var init_schema_applier = __esm({
|
|
38489
38518
|
"../core/src/postgres/schema-applier.ts"() {
|
|
38490
38519
|
"use strict";
|
|
38491
38520
|
init_drizzle_orm();
|
|
38492
38521
|
init_plugin_schema_hook();
|
|
38493
38522
|
init_advisory_locks();
|
|
38494
|
-
SCHEMA_BASELINE_VERSION = "
|
|
38523
|
+
SCHEMA_BASELINE_VERSION = "0044";
|
|
38495
38524
|
TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
|
38496
38525
|
INITIAL_SCHEMA_VERSION = "0000";
|
|
38497
38526
|
AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
|
|
@@ -38535,6 +38564,7 @@ var init_schema_applier = __esm({
|
|
|
38535
38564
|
TASK_LIFECYCLE_CONSUMERS_VERSION = "0041";
|
|
38536
38565
|
VALIDATOR_INPUT_FINGERPRINT_VERSION = "0042";
|
|
38537
38566
|
UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION = "0043";
|
|
38567
|
+
QUEUED_EPISODE_SIGNATURE_VERSION = "0044";
|
|
38538
38568
|
LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
|
|
38539
38569
|
StaleBinarySchemaError = class extends Error {
|
|
38540
38570
|
constructor(databaseVersion, binaryVersion) {
|
|
@@ -38658,6 +38688,7 @@ var init_schema_applier = __esm({
|
|
|
38658
38688
|
TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0041_fn_8685_task_lifecycle_consumers.sql");
|
|
38659
38689
|
VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0042_fn_8694_validator_input_fingerprint.sql");
|
|
38660
38690
|
UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0043_fn8768_dispatch_dedupe.sql");
|
|
38691
|
+
QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0044_fn_8785_queued_episode_signature.sql");
|
|
38661
38692
|
}
|
|
38662
38693
|
});
|
|
38663
38694
|
|
|
@@ -61597,9 +61628,14 @@ var init_central_core = __esm({
|
|
|
61597
61628
|
incremented by real work and the durable counter it maintained was fiction.
|
|
61598
61629
|
|
|
61599
61630
|
`getLiveRunningAgentCounts` SURVIVES and is now the only global readout. It is
|
|
61600
|
-
TELEMETRY, not a limiter: it derives live per-project agent counts
|
|
61601
|
-
registered side-effect-safe source so the dashboard can show "N
|
|
61602
|
-
projects)".
|
|
61631
|
+
TELEMETRY, not a capacity limiter: it derives live per-project agent counts
|
|
61632
|
+
from the registered side-effect-safe source so the dashboard can show "N
|
|
61633
|
+
running (all projects)". Task admission does not gate on it.
|
|
61634
|
+
|
|
61635
|
+
FNXC:DevEngineWatch 2026-08-04-01:25:
|
|
61636
|
+
The opt-in source-development restart also reads this conservative telemetry
|
|
61637
|
+
to wait for active work to drain. That is shutdown safety, not capacity
|
|
61638
|
+
arbitration; it never reserves slots or changes task admission.
|
|
61603
61639
|
*/
|
|
61604
61640
|
async getLiveRunningAgentCounts(options) {
|
|
61605
61641
|
this.ensureInitialized();
|
|
@@ -62861,6 +62897,7 @@ var init_persistence = __esm({
|
|
|
62861
62897
|
defineTaskColumn("worktree", (task) => task.worktree ?? null),
|
|
62862
62898
|
defineTaskColumn("blockedBy", (task) => task.blockedBy ?? null),
|
|
62863
62899
|
defineTaskColumn("overlapBlockedBy", (task) => task.overlapBlockedBy ?? null),
|
|
62900
|
+
defineTaskColumn("queuedLogEpisodeSignature", (task) => task.queuedLogEpisodeSignature ?? null),
|
|
62864
62901
|
defineTaskColumn("paused", (task) => task.paused ? 1 : 0),
|
|
62865
62902
|
defineTaskColumn("pausedReason", (task) => task.pausedReason ?? null),
|
|
62866
62903
|
defineTaskColumn("wedgeNotification", (task) => toJsonNullable(task.wedgeNotification)),
|
|
@@ -63275,6 +63312,7 @@ function rowToTask(row) {
|
|
|
63275
63312
|
worktree: row.worktree || void 0,
|
|
63276
63313
|
blockedBy: row.blockedBy || void 0,
|
|
63277
63314
|
overlapBlockedBy: row.overlapBlockedBy || void 0,
|
|
63315
|
+
queuedLogEpisodeSignature: row.queuedLogEpisodeSignature || void 0,
|
|
63278
63316
|
paused: row.paused ? true : void 0,
|
|
63279
63317
|
pausedReason: row.pausedReason || void 0,
|
|
63280
63318
|
wedgeNotification: fromJson(row.wedgeNotification) ?? void 0,
|
|
@@ -69394,6 +69432,14 @@ function noop3() {
|
|
|
69394
69432
|
function matchesParentScope(task, sourceParentTaskId) {
|
|
69395
69433
|
return !sourceParentTaskId || task.sourceParentTaskId === sourceParentTaskId;
|
|
69396
69434
|
}
|
|
69435
|
+
async function findActiveDuplicate(store, candidates, predicate) {
|
|
69436
|
+
for (const candidate of candidates) {
|
|
69437
|
+
if (!predicate(candidate)) continue;
|
|
69438
|
+
const flags = await resolveNearDuplicateCanonicalFlags(store, candidate);
|
|
69439
|
+
if (!isNearDuplicateCanonicalInactive(candidate, flags)) return candidate;
|
|
69440
|
+
}
|
|
69441
|
+
return void 0;
|
|
69442
|
+
}
|
|
69397
69443
|
async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
69398
69444
|
const fingerprint = computeContentFingerprint(input);
|
|
69399
69445
|
if (opts?.bypass === true || !fingerprint) {
|
|
@@ -69407,7 +69453,9 @@ async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
|
69407
69453
|
windowMs,
|
|
69408
69454
|
includeArchived: false
|
|
69409
69455
|
});
|
|
69410
|
-
const deterministicConflict =
|
|
69456
|
+
const deterministicConflict = await findActiveDuplicate(
|
|
69457
|
+
store,
|
|
69458
|
+
deterministicMatches,
|
|
69411
69459
|
(match) => matchesParentScope(match, opts?.sourceParentTaskId) && !acknowledged.has(match.id)
|
|
69412
69460
|
);
|
|
69413
69461
|
if (deterministicConflict) {
|
|
@@ -69454,7 +69502,9 @@ async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
|
69454
69502
|
windowMs,
|
|
69455
69503
|
includeArchived: false
|
|
69456
69504
|
});
|
|
69457
|
-
const deterministicConflict =
|
|
69505
|
+
const deterministicConflict = await findActiveDuplicate(
|
|
69506
|
+
store,
|
|
69507
|
+
deterministicMatches,
|
|
69458
69508
|
(match) => matchesParentScope(match, opts.sourceParentTaskId) && !acknowledged.has(match.id)
|
|
69459
69509
|
);
|
|
69460
69510
|
if (deterministicConflict) {
|
|
@@ -69478,7 +69528,9 @@ async function reconcileDeterministicDuplicate(store, args) {
|
|
|
69478
69528
|
windowMs: clampWindowMs(args.windowMs),
|
|
69479
69529
|
includeArchived: false
|
|
69480
69530
|
});
|
|
69481
|
-
const olderSibling =
|
|
69531
|
+
const olderSibling = await findActiveDuplicate(
|
|
69532
|
+
store,
|
|
69533
|
+
siblings,
|
|
69482
69534
|
(sibling) => sibling.id !== args.createdTask.id && sibling.createdAt < args.createdTask.createdAt && matchesParentScope(sibling, args.sourceParentTaskId)
|
|
69483
69535
|
);
|
|
69484
69536
|
if (!olderSibling) {
|
|
@@ -69537,6 +69589,8 @@ var init_duplicate_guard = __esm({
|
|
|
69537
69589
|
"../core/src/duplicates/duplicate-guard.ts"() {
|
|
69538
69590
|
"use strict";
|
|
69539
69591
|
init_duplicate_detection();
|
|
69592
|
+
init_near_duplicate_canonical();
|
|
69593
|
+
init_near_duplicate_canonical_flags();
|
|
69540
69594
|
init_workflow_lifecycle_traits();
|
|
69541
69595
|
FINGERPRINT_WINDOW_DEFAULT_MS = 6e5;
|
|
69542
69596
|
FINGERPRINT_WINDOW_MAX_MS = 36e5;
|
|
@@ -93148,6 +93202,50 @@ async function runPluginColumnTransitionHooksImpl(store, taskId, workflowIr, fro
|
|
|
93148
93202
|
await writeMarker2(remaining);
|
|
93149
93203
|
}
|
|
93150
93204
|
}
|
|
93205
|
+
async function transitionQueuedEpisodeImpl(store, id, transition) {
|
|
93206
|
+
const layer = store.asyncLayer;
|
|
93207
|
+
const projectId = layer.projectId?.trim() || "__legacy_unscoped__";
|
|
93208
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
93209
|
+
const result2 = await layer.transactionImmediate(async (tx) => {
|
|
93210
|
+
await acquireTaskAdvisoryXactLock(tx, projectId, id);
|
|
93211
|
+
const rows = await tx.select().from(project_exports.tasks).where(and(
|
|
93212
|
+
eq(project_exports.tasks.projectId, projectId),
|
|
93213
|
+
eq(project_exports.tasks.id, id),
|
|
93214
|
+
isNull(project_exports.tasks.deletedAt)
|
|
93215
|
+
));
|
|
93216
|
+
const current = rows[0];
|
|
93217
|
+
if (!current) throw new Error(`Task ${id} not found or archived while queuing`);
|
|
93218
|
+
const appended = !(current.status === "queued" && (current.blockedBy ?? null) === transition.blockedBy && (current.overlapBlockedBy ?? null) === transition.overlapBlockedBy && (current.queuedLogEpisodeSignature ?? null) === transition.signature);
|
|
93219
|
+
const log41 = Array.isArray(current.log) ? [...current.log] : [];
|
|
93220
|
+
if (appended) {
|
|
93221
|
+
log41.push({
|
|
93222
|
+
timestamp: now,
|
|
93223
|
+
action: transition.action,
|
|
93224
|
+
outcome: truncateTaskLogOutcome(transition.outcome),
|
|
93225
|
+
...transition.runContext ? { runContext: transition.runContext } : {}
|
|
93226
|
+
});
|
|
93227
|
+
const limit = getTaskActivityLogEntryLimit();
|
|
93228
|
+
if (log41.length > limit) log41.splice(0, log41.length - limit);
|
|
93229
|
+
}
|
|
93230
|
+
const updated = await tx.update(project_exports.tasks).set({
|
|
93231
|
+
status: "queued",
|
|
93232
|
+
blockedBy: transition.blockedBy,
|
|
93233
|
+
overlapBlockedBy: transition.overlapBlockedBy,
|
|
93234
|
+
queuedLogEpisodeSignature: transition.signature,
|
|
93235
|
+
...appended ? { log: log41 } : {},
|
|
93236
|
+
updatedAt: now
|
|
93237
|
+
}).where(and(
|
|
93238
|
+
eq(project_exports.tasks.projectId, projectId),
|
|
93239
|
+
eq(project_exports.tasks.id, id)
|
|
93240
|
+
)).returning();
|
|
93241
|
+
return { appended, task: updated[0] };
|
|
93242
|
+
});
|
|
93243
|
+
const task = store.rowToTask(store.pgRowToTaskRow(result2.task));
|
|
93244
|
+
await store.writeTaskJsonFile(store.taskDir(id), task);
|
|
93245
|
+
if (store.isWatching) store.taskCache.set(id, { ...task });
|
|
93246
|
+
store.emitTaskLifecycleEventSafely("task:updated", [task]);
|
|
93247
|
+
return { appended: result2.appended, task };
|
|
93248
|
+
}
|
|
93151
93249
|
async function checkAndRecordUnplannedExecutionBlockImpl(store, id, episode) {
|
|
93152
93250
|
const layer = store.asyncLayer;
|
|
93153
93251
|
const projectId = layer.projectId ?? "__legacy_unscoped__";
|
|
@@ -93259,6 +93357,7 @@ var init_audit_ops = __esm({
|
|
|
93259
93357
|
init_comments();
|
|
93260
93358
|
init_async_persistence();
|
|
93261
93359
|
init_async_comments_attachments();
|
|
93360
|
+
init_task_advisory_lock();
|
|
93262
93361
|
init_project_lane_vocabulary();
|
|
93263
93362
|
init_schema2();
|
|
93264
93363
|
}
|
|
@@ -99041,6 +99140,9 @@ var init_store = __esm({
|
|
|
99041
99140
|
async checkAndRecordUnplannedExecutionBlock(id, episode) {
|
|
99042
99141
|
return checkAndRecordUnplannedExecutionBlockImpl(this, id, episode);
|
|
99043
99142
|
}
|
|
99143
|
+
async transitionQueuedEpisode(id, transition) {
|
|
99144
|
+
return transitionQueuedEpisodeImpl(this, id, transition);
|
|
99145
|
+
}
|
|
99044
99146
|
async logEntry(id, action, outcome, runContext) {
|
|
99045
99147
|
return logEntryImpl(this, id, action, outcome, runContext);
|
|
99046
99148
|
}
|
|
@@ -127807,6 +127909,7 @@ __export(src_exports, {
|
|
|
127807
127909
|
buildInsightExtractionPrompt: () => buildInsightExtractionPrompt,
|
|
127808
127910
|
buildManualRetryResetPatch: () => buildManualRetryResetPatch,
|
|
127809
127911
|
buildOriginalDescriptionSection: () => buildOriginalDescriptionSection,
|
|
127912
|
+
buildPlanningDuplicatePolicyInstruction: () => buildPlanningDuplicatePolicyInstruction,
|
|
127810
127913
|
buildQmdCollectionAddArgs: () => buildQmdCollectionAddArgs,
|
|
127811
127914
|
buildQmdRefreshCommands: () => buildQmdRefreshCommands,
|
|
127812
127915
|
buildQmdSearchArgs: () => buildQmdSearchArgs,
|
|
@@ -128501,6 +128604,7 @@ __export(src_exports, {
|
|
|
128501
128604
|
resolveMergerFallbackModel: () => resolveMergerFallbackModel,
|
|
128502
128605
|
resolveMergerSettingsModel: () => resolveMergerSettingsModel,
|
|
128503
128606
|
resolveMobileNavPrimaryItems: () => resolveMobileNavPrimaryItems,
|
|
128607
|
+
resolveNearDuplicateCanonicalFlags: () => resolveNearDuplicateCanonicalFlags,
|
|
128504
128608
|
resolveNodeOverrideLanes: () => resolveNodeOverrideLanes,
|
|
128505
128609
|
resolveOptionalReviewRevisionBudget: () => resolveOptionalReviewRevisionBudget,
|
|
128506
128610
|
resolveOptionalStepRevisionBudget: () => resolveOptionalStepRevisionBudget,
|
|
@@ -128733,6 +128837,7 @@ var init_src2 = __esm({
|
|
|
128733
128837
|
init_plugin_prompt_condition();
|
|
128734
128838
|
init_plan_approval();
|
|
128735
128839
|
init_near_duplicate_canonical();
|
|
128840
|
+
init_near_duplicate_canonical_flags();
|
|
128736
128841
|
init_gitlab_tracking();
|
|
128737
128842
|
init_planner_intervention2();
|
|
128738
128843
|
init_planner_overseer_events();
|
|
@@ -168299,14 +168404,14 @@ async function findDefinedFeatureBootstrapDuplicate(store, input, sourceAgentId,
|
|
|
168299
168404
|
if (!sourceAgentId && !sourceParentTaskId) return void 0;
|
|
168300
168405
|
const candidates = await store.listTasks({ slim: true, includeArchived: true, includeDeleted: true });
|
|
168301
168406
|
const byId = new Map(candidates.map((task) => [task.id, task]));
|
|
168302
|
-
const
|
|
168407
|
+
const isTerminalCandidate = await resolveTerminalColumnsForTasks(store, candidates);
|
|
168303
168408
|
const matches = findSameAgentDuplicates({
|
|
168304
168409
|
title: input.title,
|
|
168305
168410
|
description: input.description,
|
|
168306
168411
|
sourceParentTaskId
|
|
168307
168412
|
}, candidates.flatMap((task) => {
|
|
168308
168413
|
const createdAt = Date.parse(task.createdAt);
|
|
168309
|
-
if (Number.isNaN(createdAt) || task.deletedAt ||
|
|
168414
|
+
if (Number.isNaN(createdAt) || task.deletedAt || isTerminalCandidate(task)) return [];
|
|
168310
168415
|
return [{
|
|
168311
168416
|
id: task.id,
|
|
168312
168417
|
title: task.title ?? "",
|
|
@@ -168357,21 +168462,6 @@ async function resolveTerminalColumnsForTasks(store, tasks2) {
|
|
|
168357
168462
|
}
|
|
168358
168463
|
return (task) => terminalByTaskId.get(task.id)?.has(task.column) === true;
|
|
168359
168464
|
}
|
|
168360
|
-
async function resolveArchivedColumnsForTasks(store, tasks2) {
|
|
168361
|
-
const cache = /* @__PURE__ */ new Map();
|
|
168362
|
-
const archivedByTaskId = /* @__PURE__ */ new Map();
|
|
168363
|
-
for (const task of tasks2) {
|
|
168364
|
-
if (archivedByTaskId.has(task.id)) continue;
|
|
168365
|
-
const columns = /* @__PURE__ */ new Set(["archived"]);
|
|
168366
|
-
try {
|
|
168367
|
-
const ir2 = await resolveWorkflowIrForTask(store, task.id, cache);
|
|
168368
|
-
if (ir2) for (const id of columnsWithFlag(ir2, "archived")) columns.add(id);
|
|
168369
|
-
} catch {
|
|
168370
|
-
}
|
|
168371
|
-
archivedByTaskId.set(task.id, columns);
|
|
168372
|
-
}
|
|
168373
|
-
return (task) => archivedByTaskId.get(task.id)?.has(task.column) === true;
|
|
168374
|
-
}
|
|
168375
168465
|
async function createAgentTask(store, input, options) {
|
|
168376
168466
|
const validateDuplicateCanonical = input.validateDuplicateCanonical;
|
|
168377
168467
|
const settings = typeof store.getSettings === "function" ? await store.getSettings() : {};
|
|
@@ -168436,11 +168526,12 @@ async function createAgentTask(store, input, options) {
|
|
|
168436
168526
|
try {
|
|
168437
168527
|
const acknowledged = new Set(options?.acknowledgedDuplicates ?? []);
|
|
168438
168528
|
const candidates = await store.findRecentTasksBySourceParentTaskId(sourceParentTaskId);
|
|
168529
|
+
const isTerminalCandidate = await resolveTerminalColumnsForTasks(store, candidates);
|
|
168439
168530
|
const matches = findSameAgentDuplicates({
|
|
168440
168531
|
title: input.title,
|
|
168441
168532
|
description: input.description,
|
|
168442
168533
|
sourceParentTaskId
|
|
168443
|
-
}, candidates.map((candidate) => ({
|
|
168534
|
+
}, candidates.filter((candidate) => !isTerminalCandidate(candidate)).map((candidate) => ({
|
|
168444
168535
|
id: candidate.id,
|
|
168445
168536
|
title: candidate.title ?? "",
|
|
168446
168537
|
description: candidate.description,
|
|
@@ -168668,7 +168759,7 @@ function createTaskSearchTool(store) {
|
|
|
168668
168759
|
return {
|
|
168669
168760
|
name: "fn_task_search",
|
|
168670
168761
|
label: "Search Tasks",
|
|
168671
|
-
description: "Keyword search across
|
|
168762
|
+
description: "Keyword search across active tasks by default. Done and archived history is opt-in and must not be used for duplicate detection.",
|
|
168672
168763
|
parameters: taskSearchParams,
|
|
168673
168764
|
execute: async (_id, params) => {
|
|
168674
168765
|
const query = params.query.trim();
|
|
@@ -168681,10 +168772,10 @@ function createTaskSearchTool(store) {
|
|
|
168681
168772
|
const limit = Math.min(50, Math.max(1, Math.floor(params.limit ?? 20)));
|
|
168682
168773
|
const results = await store.searchTasks(query, {
|
|
168683
168774
|
slim: true,
|
|
168684
|
-
includeArchived: params.includeArchived ??
|
|
168775
|
+
includeArchived: params.includeArchived ?? false,
|
|
168685
168776
|
limit
|
|
168686
168777
|
});
|
|
168687
|
-
const includeDone = params.includeDone ??
|
|
168778
|
+
const includeDone = params.includeDone ?? false;
|
|
168688
168779
|
const isTerminalResult = includeDone ? void 0 : await resolveTerminalColumnsForTasks(store, results);
|
|
168689
168780
|
const filtered = includeDone ? results : results.filter((task) => !isTerminalResult(task));
|
|
168690
168781
|
const lines = filtered.map(formatTaskSummaryLine);
|
|
@@ -185518,6 +185609,9 @@ var init_scheduler = __esm({
|
|
|
185518
185609
|
}
|
|
185519
185610
|
}
|
|
185520
185611
|
}
|
|
185612
|
+
async transitionQueuedEpisode(task, input) {
|
|
185613
|
+
return (await this.store.transitionQueuedEpisode(task.id, input)).appended;
|
|
185614
|
+
}
|
|
185521
185615
|
async logDispatchQueuedReason(taskId, reason, memoKey) {
|
|
185522
185616
|
const key = `${taskId}:${memoKey ?? reason}`;
|
|
185523
185617
|
if (this.wasDispatchQueuedReasonLogged.has(key)) {
|
|
@@ -186030,11 +186124,13 @@ var init_scheduler = __esm({
|
|
|
186030
186124
|
}
|
|
186031
186125
|
const unmetDeps = getUnmetSchedulingDependencies(task, tasks2, schedulingDependencyOptions);
|
|
186032
186126
|
if (unmetDeps.length > 0) {
|
|
186033
|
-
|
|
186034
|
-
|
|
186035
|
-
|
|
186127
|
+
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
186128
|
+
await this.transitionQueuedEpisode(task, {
|
|
186129
|
+
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
186130
|
+
blockedBy: unmetDeps[0] ?? null,
|
|
186131
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
186132
|
+
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`
|
|
186036
186133
|
});
|
|
186037
|
-
await this.logDispatchQueuedReason(task.id, `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`);
|
|
186038
186134
|
this.options.onBlocked?.(task, unmetDeps);
|
|
186039
186135
|
return null;
|
|
186040
186136
|
}
|
|
@@ -186395,16 +186491,13 @@ var init_scheduler = __esm({
|
|
|
186395
186491
|
const overlappingTaskId = Array.from(activeScopes.entries()).sort(([aId], [bId]) => aId.localeCompare(bId)).find(([, activeScope]) => this.pathsOverlap(taskScope, activeScope))?.[0] ?? null;
|
|
186396
186492
|
if (overlappingTaskId) {
|
|
186397
186493
|
const activeLeaseColumn = activeScopeColumns.get(overlappingTaskId) ?? "in-progress";
|
|
186398
|
-
await this.
|
|
186399
|
-
|
|
186494
|
+
await this.transitionQueuedEpisode(task, {
|
|
186495
|
+
signature: `file-scope:${overlappingTaskId}`,
|
|
186400
186496
|
blockedBy: null,
|
|
186401
|
-
overlapBlockedBy: overlappingTaskId
|
|
186497
|
+
overlapBlockedBy: overlappingTaskId,
|
|
186498
|
+
action: `queued \u2014 blocked by active file-scope lease ${overlappingTaskId} (column=${activeLeaseColumn})`
|
|
186402
186499
|
});
|
|
186403
186500
|
await this.rollbackRunningAgentsForQueuedTodoTask(task.id);
|
|
186404
|
-
await this.logDispatchQueuedReason(
|
|
186405
|
-
task.id,
|
|
186406
|
-
`queued \u2014 blocked by active file-scope lease ${overlappingTaskId} (column=${activeLeaseColumn})`
|
|
186407
|
-
);
|
|
186408
186501
|
return null;
|
|
186409
186502
|
}
|
|
186410
186503
|
if (task.overlapBlockedBy) {
|
|
@@ -201883,13 +201976,6 @@ function hasTerminalInvalidDoneTransition(task) {
|
|
|
201883
201976
|
const error3 = task.error ?? "";
|
|
201884
201977
|
return error3.includes("Invalid transition:") && error3.includes("\u2192 'done'");
|
|
201885
201978
|
}
|
|
201886
|
-
async function resolveNearDuplicateCanonicalFlags(store, canonical) {
|
|
201887
|
-
if (!canonical?.column) return void 0;
|
|
201888
|
-
const ir2 = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
201889
|
-
if (!ir2 || ir2.version !== "v2") return void 0;
|
|
201890
|
-
const column = ir2.columns.find((candidate) => candidate.id === canonical.column);
|
|
201891
|
-
return column ? resolveColumnFlags(column) : void 0;
|
|
201892
|
-
}
|
|
201893
201979
|
function isTaskWorkComplete(task) {
|
|
201894
201980
|
if (task.steps.length === 0) return false;
|
|
201895
201981
|
return task.steps.every((step) => step.status === "done" || step.status === "skipped");
|
|
@@ -202049,7 +202135,6 @@ var init_self_healing = __esm({
|
|
|
202049
202135
|
strandedHoldContinuationNoActionAudited = /* @__PURE__ */ new Set();
|
|
202050
202136
|
/* FNXC:SymbolLock 2026-07-30-14:20: idle symbol-lock sweeps emit one no-action audit until a stale lock re-arms the diagnostic. */
|
|
202051
202137
|
symbolLockNoActionAudited = false;
|
|
202052
|
-
preservedQueuedOverlapLogged = /* @__PURE__ */ new Map();
|
|
202053
202138
|
maintenanceTickCounter = 0;
|
|
202054
202139
|
taskLifecycleRetentionLastPrunedAt = /* @__PURE__ */ new Map();
|
|
202055
202140
|
processBootStartedAt = Date.now();
|
|
@@ -202709,7 +202794,6 @@ var init_self_healing = __esm({
|
|
|
202709
202794
|
}
|
|
202710
202795
|
this.finalizeUnprovenWarned.clear();
|
|
202711
202796
|
this.strandedCompletedFailureProvenanceWarned.clear();
|
|
202712
|
-
this.preservedQueuedOverlapLogged.clear();
|
|
202713
202797
|
log33.debug("Stopped");
|
|
202714
202798
|
}
|
|
202715
202799
|
// ── Auto-unpause ───────────────────────────────────────────────────
|
|
@@ -205278,17 +205362,20 @@ var init_self_healing = __esm({
|
|
|
205278
205362
|
if (todoTaskIds.has(dependent.id)) {
|
|
205279
205363
|
if (unresolvedDeps.length > 0) {
|
|
205280
205364
|
const nextBlocker = unresolvedDeps[0];
|
|
205281
|
-
|
|
205282
|
-
await this.store.
|
|
205283
|
-
|
|
205284
|
-
|
|
205285
|
-
|
|
205365
|
+
const normalizedUnresolvedDeps = [...new Set(unresolvedDeps)].sort();
|
|
205366
|
+
await this.store.transitionQueuedEpisode(dependent.id, {
|
|
205367
|
+
signature: `dependency:${normalizedUnresolvedDeps.join(",")}`,
|
|
205368
|
+
blockedBy: nextBlocker,
|
|
205369
|
+
overlapBlockedBy,
|
|
205370
|
+
action: `Auto-recovered (FN-4523): cleared stale blockedBy \u2014 blocker ${taskId} is done; now blocked by ${nextBlocker}`
|
|
205371
|
+
});
|
|
205286
205372
|
} else if (hasActiveOverlapBlocker) {
|
|
205287
|
-
await this.store.
|
|
205288
|
-
|
|
205289
|
-
|
|
205290
|
-
|
|
205291
|
-
|
|
205373
|
+
await this.store.transitionQueuedEpisode(dependent.id, {
|
|
205374
|
+
signature: `file-scope:${overlapBlockedBy}`,
|
|
205375
|
+
blockedBy: null,
|
|
205376
|
+
overlapBlockedBy,
|
|
205377
|
+
action: `Auto-recovered (FN-4523): preserved queued status \u2014 still blocked by file scope overlap with ${overlapBlockedBy}`
|
|
205378
|
+
});
|
|
205292
205379
|
} else {
|
|
205293
205380
|
await this.store.updateTask(dependent.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
205294
205381
|
await this.store.logEntry(
|
|
@@ -205801,16 +205888,6 @@ var init_self_healing = __esm({
|
|
|
205801
205888
|
countBlockedDepth(tasks2) {
|
|
205802
205889
|
return tasks2.filter((task) => typeof task.blockedBy === "string" && task.blockedBy.trim().length > 0).length;
|
|
205803
205890
|
}
|
|
205804
|
-
shouldLogPreservedQueuedOverlap(taskId, overlapBlockedBy) {
|
|
205805
|
-
if (!overlapBlockedBy) return false;
|
|
205806
|
-
const previous = this.preservedQueuedOverlapLogged.get(taskId);
|
|
205807
|
-
if (previous === overlapBlockedBy) return false;
|
|
205808
|
-
this.preservedQueuedOverlapLogged.set(taskId, overlapBlockedBy);
|
|
205809
|
-
return true;
|
|
205810
|
-
}
|
|
205811
|
-
clearPreservedQueuedOverlapMemo(taskId) {
|
|
205812
|
-
this.preservedQueuedOverlapLogged.delete(taskId);
|
|
205813
|
-
}
|
|
205814
205891
|
/**
|
|
205815
205892
|
* #1401: periodic transitionPending recovery sweep. Delegates to the store's
|
|
205816
205893
|
* idempotent recovery method (a no-op when no stale markers exist), keeping
|
|
@@ -206043,7 +206120,6 @@ var init_self_healing = __esm({
|
|
|
206043
206120
|
(task) => task.status === "queued" && (task.dependencies.length > 0 || Boolean(task.overlapBlockedBy))
|
|
206044
206121
|
);
|
|
206045
206122
|
if (blockedTasks.length === 0 && queuedDependencyTasks.length === 0) {
|
|
206046
|
-
this.preservedQueuedOverlapLogged.clear();
|
|
206047
206123
|
return 0;
|
|
206048
206124
|
}
|
|
206049
206125
|
const allTasks = await this.store.listTasks({ includeArchived: true });
|
|
@@ -206115,13 +206191,6 @@ var init_self_healing = __esm({
|
|
|
206115
206191
|
hold: /* @__PURE__ */ new Set(["todo"]),
|
|
206116
206192
|
review: /* @__PURE__ */ new Set(["in-review"])
|
|
206117
206193
|
};
|
|
206118
|
-
for (const [taskId, lastLoggedBlockerId] of this.preservedQueuedOverlapLogged) {
|
|
206119
|
-
const memoTask = taskById.get(taskId);
|
|
206120
|
-
const memoHasActiveOverlapBlocker = memoTask ? await hasActiveFileScopeOverlapBlocker(memoTask, memoTask.overlapBlockedBy) : false;
|
|
206121
|
-
if (!candidates.has(taskId) || !memoTask || !lanesOf(taskId).hold.has(memoTask.column) || memoTask.status !== "queued" || memoTask.overlapBlockedBy !== lastLoggedBlockerId || !memoHasActiveOverlapBlocker) {
|
|
206122
|
-
this.clearPreservedQueuedOverlapMemo(taskId);
|
|
206123
|
-
}
|
|
206124
|
-
}
|
|
206125
206194
|
for (const task of candidates.values()) {
|
|
206126
206195
|
const blockerId = task.blockedBy;
|
|
206127
206196
|
const unresolvedDeps = task.dependencies.filter((depId) => {
|
|
@@ -206194,7 +206263,6 @@ var init_self_healing = __esm({
|
|
|
206194
206263
|
let didRecover = false;
|
|
206195
206264
|
if (todoTaskIds.has(task.id)) {
|
|
206196
206265
|
if (unresolvedDeps.length > 0) {
|
|
206197
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
206198
206266
|
const nextBlocker2 = unresolvedDeps[0];
|
|
206199
206267
|
if (nextBlocker2 === blockerId) {
|
|
206200
206268
|
continue;
|
|
@@ -206203,19 +206271,19 @@ var init_self_healing = __esm({
|
|
|
206203
206271
|
await this.store.logEntry(task.id, `Auto-recovered (FN-5488): refreshed stale blockedBy \u2014 blocker=${blockerId} blockerStatus=${blocker?.status ?? "none"} reason=${reasonCode ?? "unspecified"}; ${reason}; now blocked by ${nextBlocker2}`);
|
|
206204
206272
|
didRecover = true;
|
|
206205
206273
|
} else if (hasActiveOverlapBlocker) {
|
|
206206
|
-
await this.store.
|
|
206207
|
-
|
|
206208
|
-
|
|
206209
|
-
|
|
206210
|
-
|
|
206274
|
+
const transition = await this.store.transitionQueuedEpisode(task.id, {
|
|
206275
|
+
signature: `file-scope:${task.overlapBlockedBy}`,
|
|
206276
|
+
blockedBy: null,
|
|
206277
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
206278
|
+
action: `Auto-recovered (FN-5488): preserved queued status \u2014 blocker=${blockerId} blockerStatus=${blocker?.status ?? "none"} reason=${reasonCode ?? "unspecified"}; still blocked by file scope overlap with ${task.overlapBlockedBy}`
|
|
206279
|
+
});
|
|
206280
|
+
didRecover = transition.appended;
|
|
206211
206281
|
} else {
|
|
206212
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
206213
206282
|
await this.store.updateTask(task.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
206214
206283
|
await this.store.logEntry(task.id, `Auto-recovered (FN-5488): cleared stale blockedBy \u2014 blocker=${blockerId} blockerStatus=${blocker?.status ?? "none"} reason=${reasonCode ?? "unspecified"}; ${reason}`);
|
|
206215
206284
|
didRecover = true;
|
|
206216
206285
|
}
|
|
206217
206286
|
} else {
|
|
206218
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
206219
206287
|
await this.store.updateTask(task.id, { blockedBy: null });
|
|
206220
206288
|
await this.store.logEntry(task.id, `Auto-recovered (FN-4091): cleared stale blockedBy \u2014 ${reason}`);
|
|
206221
206289
|
didRecover = true;
|
|
@@ -206235,13 +206303,14 @@ var init_self_healing = __esm({
|
|
|
206235
206303
|
if (queuedDependencyTaskIds.has(task.id)) {
|
|
206236
206304
|
try {
|
|
206237
206305
|
if (hasActiveOverlapBlocker) {
|
|
206238
|
-
await this.store.
|
|
206239
|
-
|
|
206240
|
-
|
|
206241
|
-
|
|
206242
|
-
|
|
206306
|
+
const transition = await this.store.transitionQueuedEpisode(task.id, {
|
|
206307
|
+
signature: `file-scope:${task.overlapBlockedBy}`,
|
|
206308
|
+
blockedBy: null,
|
|
206309
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
206310
|
+
action: `Auto-recovered: preserved queued status \u2014 still blocked by file scope overlap with ${task.overlapBlockedBy}`
|
|
206311
|
+
});
|
|
206312
|
+
if (transition.appended) recovered++;
|
|
206243
206313
|
} else {
|
|
206244
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
206245
206314
|
await this.store.updateTask(task.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
206246
206315
|
}
|
|
206247
206316
|
} catch (err) {
|
|
@@ -206251,7 +206320,6 @@ var init_self_healing = __esm({
|
|
|
206251
206320
|
}
|
|
206252
206321
|
continue;
|
|
206253
206322
|
}
|
|
206254
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
206255
206323
|
const nextBlocker = unresolvedDeps[0] ?? null;
|
|
206256
206324
|
if (nextBlocker && task.blockedBy !== nextBlocker) {
|
|
206257
206325
|
try {
|
|
@@ -212462,14 +212530,12 @@ var init_self_healing = __esm({
|
|
|
212462
212530
|
if (canClearInactiveMarker) {
|
|
212463
212531
|
rmSync7(promptPath, { force: true });
|
|
212464
212532
|
const priorClearCount = typeof task.sourceMetadata?.duplicateMarkerClearCount === "number" ? task.sourceMetadata.duplicateMarkerClearCount : 0;
|
|
212465
|
-
const
|
|
212466
|
-
const exhausted = alreadyDismissed || priorClearCount >= 1;
|
|
212467
|
-
const patch = exhausted ? buildMarkerExhaustedFailedTaskPatch(marker.canonicalId, priorClearCount) : buildMarkerClearedReplanTaskPatch(marker.canonicalId, priorClearCount);
|
|
212533
|
+
const patch = buildMarkerClearedReplanTaskPatch(marker.canonicalId, priorClearCount);
|
|
212468
212534
|
await this.store.updateTask(task.id, patch);
|
|
212469
212535
|
if (typeof this.store.logEntry === "function") {
|
|
212470
212536
|
await Promise.resolve(this.store.logEntry(
|
|
212471
212537
|
task.id,
|
|
212472
|
-
|
|
212538
|
+
TRIAGE_MARKER_CLEARED_REPLAN_LOG_ACTION,
|
|
212473
212539
|
buildInactiveDuplicateClearFeedback(marker.canonicalId)
|
|
212474
212540
|
)).catch(() => {
|
|
212475
212541
|
});
|
|
@@ -213281,13 +213347,6 @@ function inlineTaskListFallback(lines, opts = {}) {
|
|
|
213281
213347
|
function resolveTaskListFormatter(core) {
|
|
213282
213348
|
return typeof core.formatTaskListText === "function" ? core.formatTaskListText : inlineTaskListFallback;
|
|
213283
213349
|
}
|
|
213284
|
-
async function resolveNearDuplicateCanonicalFlags2(store, canonical) {
|
|
213285
|
-
if (!canonical?.column) return void 0;
|
|
213286
|
-
const ir2 = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
213287
|
-
if (!ir2 || ir2.version !== "v2") return void 0;
|
|
213288
|
-
const column = ir2.columns.find((candidate) => candidate.id === canonical.column);
|
|
213289
|
-
return column ? resolveColumnFlags(column) : void 0;
|
|
213290
|
-
}
|
|
213291
213350
|
function isOrphanedLegacyTriageRow(column, declaresTriage) {
|
|
213292
213351
|
return column === "triage" && !declaresTriage;
|
|
213293
213352
|
}
|
|
@@ -215016,11 +215075,13 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
215016
215075
|
const defaultTriagePrompt = resolveAgentPrompt("triage", void 0, { plannerHeartbeatPatrolEnabled });
|
|
215017
215076
|
const resolvedBasePrompt = userTriagePrompt || (leanPlanning ? workflowFastPlanningPrompt || builtinSeamPrompt("planning-fast") || defaultTriagePrompt : workflowPlanningPrompt || defaultTriagePrompt);
|
|
215018
215077
|
const renderedBasePrompt = renderTriagePolicyPlaceholders(resolvedBasePrompt, triagePolicySettings);
|
|
215078
|
+
const duplicatePolicyInstruction = buildPlanningDuplicatePolicyInstruction();
|
|
215019
215079
|
const triageLayers = buildPromptLayers({
|
|
215020
215080
|
basePrompt: renderedBasePrompt,
|
|
215021
215081
|
goalContext: triageGoalResolution.goalContext,
|
|
215022
215082
|
agentInstructions: [
|
|
215023
215083
|
triageIdentitySection,
|
|
215084
|
+
duplicatePolicyInstruction,
|
|
215024
215085
|
triageInstructions,
|
|
215025
215086
|
isResearchToolSurfaceEnabled(settings) ? getResearchGuidanceForSurface("triage") : ""
|
|
215026
215087
|
].filter((section) => section.trim()).join("\n\n"),
|
|
@@ -215649,7 +215710,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
215649
215710
|
const taskSearch = {
|
|
215650
215711
|
name: "fn_task_search",
|
|
215651
215712
|
label: "Search Tasks",
|
|
215652
|
-
description: "Keyword search across tasks
|
|
215713
|
+
description: "Keyword search across active tasks by default. Done and archived history is opt-in and must not be used for duplicate detection.",
|
|
215653
215714
|
parameters: taskSearchParams2,
|
|
215654
215715
|
execute: async (_callId, params) => {
|
|
215655
215716
|
const query = params.query.trim();
|
|
@@ -215661,10 +215722,10 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
215661
215722
|
}
|
|
215662
215723
|
const results = await store.searchTasks(query, {
|
|
215663
215724
|
slim: true,
|
|
215664
|
-
includeArchived: params.includeArchived ??
|
|
215725
|
+
includeArchived: params.includeArchived ?? false,
|
|
215665
215726
|
limit: params.limit ?? 20
|
|
215666
215727
|
});
|
|
215667
|
-
const includeDone = params.includeDone ??
|
|
215728
|
+
const includeDone = params.includeDone ?? false;
|
|
215668
215729
|
const isTerminalResult = includeDone ? void 0 : await resolveTerminalColumnsForTasks(store, results);
|
|
215669
215730
|
const filtered = includeDone ? results : results.filter((t) => !isTerminalResult(t));
|
|
215670
215731
|
if (filtered.length === 0) {
|
|
@@ -215903,7 +215964,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
215903
215964
|
if (canonicalTask?.id.toLowerCase() === task.id.toLowerCase()) {
|
|
215904
215965
|
return false;
|
|
215905
215966
|
}
|
|
215906
|
-
const canonicalFlags = await
|
|
215967
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
215907
215968
|
if (isNearDuplicateCanonicalInactive(canonicalTask, canonicalFlags)) {
|
|
215908
215969
|
planLog.log(`${task.id} explicit duplicate marker targets inactive ${canonicalId}; clearing marker for replanning`);
|
|
215909
215970
|
} else {
|
|
@@ -216047,17 +216108,16 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
216047
216108
|
const canonicalId = explicitDuplicateMarker.canonicalId;
|
|
216048
216109
|
const canonicalTask = await this.store.getTask(canonicalId).catch(() => null);
|
|
216049
216110
|
const canClearInactiveMarker = task.userPaused !== true && (task.paused !== true || task.pausedReason === "duplicate-decision-required") && (task.pausedReason == null || task.pausedReason === "duplicate-decision-required");
|
|
216050
|
-
const canonicalFlags = await
|
|
216111
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
216051
216112
|
const liveMeta = (await this.store.getTask(task.id).catch(() => null))?.sourceMetadata ?? task.sourceMetadata;
|
|
216052
216113
|
const priorClearCount = typeof liveMeta?.duplicateMarkerClearCount === "number" ? liveMeta.duplicateMarkerClearCount : 0;
|
|
216053
216114
|
if (isNearDuplicateCanonicalInactive(canonicalTask ?? void 0, canonicalFlags)) {
|
|
216054
216115
|
if (canClearInactiveMarker) {
|
|
216055
|
-
const alreadyDismissed = isTriageDuplicateKeepAcknowledged(liveMeta, canonicalId);
|
|
216056
216116
|
await this.clearDuplicateMarkerForReplan(
|
|
216057
216117
|
task,
|
|
216058
216118
|
canonicalId,
|
|
216059
216119
|
buildInactiveDuplicateClearFeedback(canonicalId),
|
|
216060
|
-
{ exhausted:
|
|
216120
|
+
{ exhausted: false, priorClearCount }
|
|
216061
216121
|
);
|
|
216062
216122
|
}
|
|
216063
216123
|
return;
|
|
@@ -216297,7 +216357,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
216297
216357
|
if (!canonicalTask) {
|
|
216298
216358
|
return;
|
|
216299
216359
|
}
|
|
216300
|
-
const canonicalFlags = await
|
|
216360
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
216301
216361
|
if (isNearDuplicateCanonicalInactive(canonicalTask, canonicalFlags)) {
|
|
216302
216362
|
planLog.log(`${task.id}: near-duplicate candidate ${canonical.id} is inactive; skipping near-duplicate flag`);
|
|
216303
216363
|
return;
|
|
@@ -232168,13 +232228,15 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
232168
232228
|
recoveryRehome: true
|
|
232169
232229
|
});
|
|
232170
232230
|
}
|
|
232171
|
-
|
|
232172
|
-
await this.store.
|
|
232173
|
-
|
|
232174
|
-
|
|
232175
|
-
|
|
232176
|
-
|
|
232177
|
-
|
|
232231
|
+
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
232232
|
+
await this.store.transitionQueuedEpisode(liveTask.id, {
|
|
232233
|
+
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
232234
|
+
blockedBy: unmetDeps[0] ?? null,
|
|
232235
|
+
overlapBlockedBy: liveTask.overlapBlockedBy ?? null,
|
|
232236
|
+
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`,
|
|
232237
|
+
outcome: "Executor pre-dispatch dependency gate blocked workflow/authoritative execution.",
|
|
232238
|
+
runContext: this.getRunContextFor(liveTask.id)
|
|
232239
|
+
});
|
|
232178
232240
|
executorLog.log(`${liveTask.id}: executor dispatch blocked by unmet dependencies: ${unmetDeps.join(", ")}`);
|
|
232179
232241
|
return true;
|
|
232180
232242
|
}
|
|
@@ -257802,6 +257864,40 @@ var init_in_process_runtime = __esm({
|
|
|
257802
257864
|
throw err;
|
|
257803
257865
|
}
|
|
257804
257866
|
}
|
|
257867
|
+
/**
|
|
257868
|
+
* Close every process-local admission source without aborting work that is
|
|
257869
|
+
* already running. Development source reload uses this boundary before it
|
|
257870
|
+
* waits for the live-agent count to reach zero.
|
|
257871
|
+
*/
|
|
257872
|
+
beginDrain() {
|
|
257873
|
+
if (this.status !== "active") return;
|
|
257874
|
+
this.setStatus("paused");
|
|
257875
|
+
if (this.workflowContinuationTimer) {
|
|
257876
|
+
clearInterval(this.workflowContinuationTimer);
|
|
257877
|
+
this.workflowContinuationTimer = void 0;
|
|
257878
|
+
}
|
|
257879
|
+
const admissionStops = [
|
|
257880
|
+
["self-healing manager", () => this.selfHealingManager?.stop()],
|
|
257881
|
+
["routine scheduler", () => this.routineScheduler?.stop()],
|
|
257882
|
+
["trigger scheduler", () => this.triggerScheduler?.stop()],
|
|
257883
|
+
["stuck task detector", () => this.stuckTaskDetector?.stop()],
|
|
257884
|
+
["heartbeat monitor", () => this.heartbeatMonitor?.stop()],
|
|
257885
|
+
["triage processor", () => this.triageProcessor?.stop()],
|
|
257886
|
+
["scheduler", () => this.scheduler?.stop()],
|
|
257887
|
+
["mission autopilot", () => this.missionAutopilot?.stop()],
|
|
257888
|
+
["mission execution loop", () => this.missionExecutionLoop?.stop()]
|
|
257889
|
+
];
|
|
257890
|
+
for (const [label, stop] of admissionStops) {
|
|
257891
|
+
try {
|
|
257892
|
+
stop();
|
|
257893
|
+
} catch (error3) {
|
|
257894
|
+
runtimeLog.warn(
|
|
257895
|
+
`Failed to stop ${label} while draining ${this.config.projectId}: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
257896
|
+
);
|
|
257897
|
+
}
|
|
257898
|
+
}
|
|
257899
|
+
runtimeLog.log(`InProcessRuntime draining for ${this.config.projectId}`);
|
|
257900
|
+
}
|
|
257805
257901
|
/**
|
|
257806
257902
|
* Stop the runtime with graceful shutdown.
|
|
257807
257903
|
*
|
|
@@ -261916,6 +262012,11 @@ ${detail}`);
|
|
|
261916
262012
|
this.started = false;
|
|
261917
262013
|
runtimeLog.log(`ProjectEngine stopped for ${this.config.projectId}`);
|
|
261918
262014
|
}
|
|
262015
|
+
/** Stop new lifecycle admission while allowing active work to finish. */
|
|
262016
|
+
beginDrain() {
|
|
262017
|
+
this.shuttingDown = true;
|
|
262018
|
+
this.runtime.beginDrain();
|
|
262019
|
+
}
|
|
261919
262020
|
// ── Public accessors ──
|
|
261920
262021
|
/** Get the underlying InProcessRuntime. */
|
|
261921
262022
|
getRuntime() {
|
|
@@ -265494,14 +265595,30 @@ var init_project_engine_manager = __esm({
|
|
|
265494
265595
|
}
|
|
265495
265596
|
runtimeLog.log(`Engine startup complete: ${started} started, ${failed} failed`);
|
|
265496
265597
|
}
|
|
265497
|
-
/**
|
|
265498
|
-
|
|
265598
|
+
/** Close admission on every engine and stop reconciliation without tearing engines down. */
|
|
265599
|
+
beginDrain() {
|
|
265499
265600
|
this.stopped = true;
|
|
265500
265601
|
this.reconciliationStopped = true;
|
|
265501
265602
|
if (this.reconciliationInterval !== null) {
|
|
265502
265603
|
clearInterval(this.reconciliationInterval);
|
|
265503
265604
|
this.reconciliationInterval = null;
|
|
265504
265605
|
}
|
|
265606
|
+
for (const engine of this.engines.values()) {
|
|
265607
|
+
try {
|
|
265608
|
+
engine.beginDrain?.();
|
|
265609
|
+
} catch (error3) {
|
|
265610
|
+
runtimeLog.warn(
|
|
265611
|
+
`Engine drain error: ${error3 instanceof Error ? error3.message : String(error3)}`
|
|
265612
|
+
);
|
|
265613
|
+
}
|
|
265614
|
+
}
|
|
265615
|
+
for (const starting of this.starting.values()) {
|
|
265616
|
+
void starting.then((engine) => engine.beginDrain?.()).catch(() => void 0);
|
|
265617
|
+
}
|
|
265618
|
+
}
|
|
265619
|
+
/** Gracefully stop all engines and reconciliation. */
|
|
265620
|
+
async stopAll() {
|
|
265621
|
+
this.beginDrain();
|
|
265505
265622
|
try {
|
|
265506
265623
|
this.centralCore.stopDiscovery();
|
|
265507
265624
|
await this.centralCore.markLocalNodeOffline();
|