@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
|
@@ -11923,6 +11923,11 @@ APPROVE when the plan is executable and verifiable, not when it is cosmetically
|
|
|
11923
11923
|
});
|
|
11924
11924
|
|
|
11925
11925
|
// ../core/src/agents/agent-prompts.ts
|
|
11926
|
+
function buildPlanningDuplicatePolicyInstruction() {
|
|
11927
|
+
return `## Duplicate policy for this task
|
|
11928
|
+
|
|
11929
|
+
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.`;
|
|
11930
|
+
}
|
|
11926
11931
|
function buildTriageHeartbeatGuidance(options = {}) {
|
|
11927
11932
|
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.";
|
|
11928
11933
|
const patrolSafetyLines = options.plannerHeartbeatPatrolEnabled === false ? "" : `
|
|
@@ -12214,7 +12219,7 @@ Write a lean, executable PROMPT.md quickly. Preserve safety gates, but skip heav
|
|
|
12214
12219
|
- Preserve required safety sections for bugs, workflow routing, forensic tasks, and decision-only work.
|
|
12215
12220
|
|
|
12216
12221
|
## Duplicate check
|
|
12217
|
-
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.
|
|
12222
|
+
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.
|
|
12218
12223
|
|
|
12219
12224
|
## Required PROMPT.md shape
|
|
12220
12225
|
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.
|
|
@@ -12482,9 +12487,9 @@ Verified facts about this codebase's storage \u2014 cite these correctly so Plan
|
|
|
12482
12487
|
- 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.
|
|
12483
12488
|
|
|
12484
12489
|
## Duplicate check
|
|
12485
|
-
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).
|
|
12486
|
-
|
|
12487
|
-
If
|
|
12490
|
+
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).
|
|
12491
|
+
Do not search completed or archived work for duplicate candidates.
|
|
12492
|
+
If an actionable task already covers the same work (even if worded differently), do not write a spec.
|
|
12488
12493
|
Instead you MUST still write PROMPT.md, with its ENTIRE contents being this one line and nothing else:
|
|
12489
12494
|
\`DUPLICATE: {existing-task-id}\`
|
|
12490
12495
|
Writing that file IS how you report the duplicate. Reporting it only in your reply is not recorded:
|
|
@@ -12515,7 +12520,7 @@ Workflow policy can disable proactive oversized-task splitting for operators who
|
|
|
12515
12520
|
## Triage tools
|
|
12516
12521
|
You have these extra tools during triage:
|
|
12517
12522
|
- \`fn_task_list\` \u2014 list existing active tasks
|
|
12518
|
-
- \`fn_task_search\` \u2014 keyword search across tasks
|
|
12523
|
+
- \`fn_task_search\` \u2014 keyword search across active tasks by default; history is opt-in for non-duplicate research
|
|
12519
12524
|
- \`fn_task_show\` \u2014 inspect a task and its PROMPT.md
|
|
12520
12525
|
- \`fn_task_create\` \u2014 create a child/follow-up task while triaging
|
|
12521
12526
|
- \`fn_task_document_write\` \u2014 save a planning document (e.g., key="plan")
|
|
@@ -20255,6 +20260,7 @@ var init_project = __esm({
|
|
|
20255
20260
|
worktree: text("worktree"),
|
|
20256
20261
|
blockedBy: text("blocked_by"),
|
|
20257
20262
|
overlapBlockedBy: text("overlap_blocked_by"),
|
|
20263
|
+
queuedLogEpisodeSignature: text("queued_log_episode_signature"),
|
|
20258
20264
|
paused: integer("paused").default(0),
|
|
20259
20265
|
userPaused: integer("user_paused").default(0),
|
|
20260
20266
|
pausedReason: text("paused_reason"),
|
|
@@ -24405,6 +24411,22 @@ var init_near_duplicate_canonical = __esm({
|
|
|
24405
24411
|
}
|
|
24406
24412
|
});
|
|
24407
24413
|
|
|
24414
|
+
// ../core/src/duplicates/near-duplicate-canonical-flags.ts
|
|
24415
|
+
async function resolveNearDuplicateCanonicalFlags(store, canonical) {
|
|
24416
|
+
if (!canonical?.column) return void 0;
|
|
24417
|
+
const workflow = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
24418
|
+
if (!workflow || workflow.version !== "v2") return void 0;
|
|
24419
|
+
const column = workflow.columns.find((candidate) => candidate.id === canonical.column);
|
|
24420
|
+
return column ? resolveColumnFlags(column) : void 0;
|
|
24421
|
+
}
|
|
24422
|
+
var init_near_duplicate_canonical_flags = __esm({
|
|
24423
|
+
"../core/src/duplicates/near-duplicate-canonical-flags.ts"() {
|
|
24424
|
+
"use strict";
|
|
24425
|
+
init_trait_registry();
|
|
24426
|
+
init_workflow_ir_resolver();
|
|
24427
|
+
}
|
|
24428
|
+
});
|
|
24429
|
+
|
|
24408
24430
|
// ../core/src/git/gitlab-tracking.ts
|
|
24409
24431
|
function formatGitLabTrackedItemRef(item) {
|
|
24410
24432
|
const marker = item.kind === "merge_request" ? "!" : "#";
|
|
@@ -38166,6 +38188,7 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
38166
38188
|
const taskLifecycleConsumersAlreadyApplied = applied.includes(TASK_LIFECYCLE_CONSUMERS_VERSION);
|
|
38167
38189
|
const validatorInputFingerprintAlreadyApplied = applied.includes(VALIDATOR_INPUT_FINGERPRINT_VERSION);
|
|
38168
38190
|
const unplannedExecutionBlockDedupeAlreadyApplied = applied.includes(UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION);
|
|
38191
|
+
const queuedEpisodeSignatureAlreadyApplied = applied.includes(QUEUED_EPISODE_SIGNATURE_VERSION);
|
|
38169
38192
|
assertBinaryNotOlderThanDatabase(applied);
|
|
38170
38193
|
let schemaChanged = false;
|
|
38171
38194
|
if (!baselineAlreadyApplied) {
|
|
@@ -38559,17 +38582,23 @@ async function applySchemaBaseline(db, options = {}) {
|
|
|
38559
38582
|
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
38560
38583
|
schemaChanged = true;
|
|
38561
38584
|
}
|
|
38585
|
+
if (!queuedEpisodeSignatureAlreadyApplied) {
|
|
38586
|
+
const migrationSql = await readFile4(QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH, "utf8");
|
|
38587
|
+
await tx.execute(sql.raw(migrationSql));
|
|
38588
|
+
await tx.execute(sql`INSERT INTO public.${sql.identifier(MIGRATION_BOOKKEEPING_TABLE)} (version) VALUES (${QUEUED_EPISODE_SIGNATURE_VERSION}) ON CONFLICT (version) DO NOTHING`);
|
|
38589
|
+
schemaChanged = true;
|
|
38590
|
+
}
|
|
38562
38591
|
return { applied: schemaChanged, pluginHooksRun: pluginHooks.length };
|
|
38563
38592
|
});
|
|
38564
38593
|
}
|
|
38565
|
-
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;
|
|
38594
|
+
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;
|
|
38566
38595
|
var init_schema_applier = __esm({
|
|
38567
38596
|
"../core/src/postgres/schema-applier.ts"() {
|
|
38568
38597
|
"use strict";
|
|
38569
38598
|
init_drizzle_orm();
|
|
38570
38599
|
init_plugin_schema_hook();
|
|
38571
38600
|
init_advisory_locks();
|
|
38572
|
-
SCHEMA_BASELINE_VERSION = "
|
|
38601
|
+
SCHEMA_BASELINE_VERSION = "0044";
|
|
38573
38602
|
TASK_DECLARED_SYMBOLS_VERSION = "0028";
|
|
38574
38603
|
INITIAL_SCHEMA_VERSION = "0000";
|
|
38575
38604
|
AUTOMATION_ISOLATION_SCHEMA_VERSION = "0001";
|
|
@@ -38613,6 +38642,7 @@ var init_schema_applier = __esm({
|
|
|
38613
38642
|
TASK_LIFECYCLE_CONSUMERS_VERSION = "0041";
|
|
38614
38643
|
VALIDATOR_INPUT_FINGERPRINT_VERSION = "0042";
|
|
38615
38644
|
UNPLANNED_EXECUTION_BLOCK_DEDUPE_VERSION = "0043";
|
|
38645
|
+
QUEUED_EPISODE_SIGNATURE_VERSION = "0044";
|
|
38616
38646
|
LEGACY_ADOPTION_DRAINED_MARKER_FUNCTION = "fusion_mark_legacy_adoption_drained";
|
|
38617
38647
|
StaleBinarySchemaError = class extends Error {
|
|
38618
38648
|
constructor(databaseVersion, binaryVersion) {
|
|
@@ -38736,6 +38766,7 @@ var init_schema_applier = __esm({
|
|
|
38736
38766
|
TASK_LIFECYCLE_CONSUMERS_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0041_fn_8685_task_lifecycle_consumers.sql");
|
|
38737
38767
|
VALIDATOR_INPUT_FINGERPRINT_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0042_fn_8694_validator_input_fingerprint.sql");
|
|
38738
38768
|
UNPLANNED_EXECUTION_BLOCK_DEDUPE_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0043_fn8768_dispatch_dedupe.sql");
|
|
38769
|
+
QUEUED_EPISODE_SIGNATURE_MIGRATION_PATH = join8(MIGRATIONS_DIR, "0044_fn_8785_queued_episode_signature.sql");
|
|
38739
38770
|
}
|
|
38740
38771
|
});
|
|
38741
38772
|
|
|
@@ -61675,9 +61706,14 @@ var init_central_core = __esm({
|
|
|
61675
61706
|
incremented by real work and the durable counter it maintained was fiction.
|
|
61676
61707
|
|
|
61677
61708
|
`getLiveRunningAgentCounts` SURVIVES and is now the only global readout. It is
|
|
61678
|
-
TELEMETRY, not a limiter: it derives live per-project agent counts
|
|
61679
|
-
registered side-effect-safe source so the dashboard can show "N
|
|
61680
|
-
projects)".
|
|
61709
|
+
TELEMETRY, not a capacity limiter: it derives live per-project agent counts
|
|
61710
|
+
from the registered side-effect-safe source so the dashboard can show "N
|
|
61711
|
+
running (all projects)". Task admission does not gate on it.
|
|
61712
|
+
|
|
61713
|
+
FNXC:DevEngineWatch 2026-08-04-01:25:
|
|
61714
|
+
The opt-in source-development restart also reads this conservative telemetry
|
|
61715
|
+
to wait for active work to drain. That is shutdown safety, not capacity
|
|
61716
|
+
arbitration; it never reserves slots or changes task admission.
|
|
61681
61717
|
*/
|
|
61682
61718
|
async getLiveRunningAgentCounts(options) {
|
|
61683
61719
|
this.ensureInitialized();
|
|
@@ -62939,6 +62975,7 @@ var init_persistence = __esm({
|
|
|
62939
62975
|
defineTaskColumn("worktree", (task) => task.worktree ?? null),
|
|
62940
62976
|
defineTaskColumn("blockedBy", (task) => task.blockedBy ?? null),
|
|
62941
62977
|
defineTaskColumn("overlapBlockedBy", (task) => task.overlapBlockedBy ?? null),
|
|
62978
|
+
defineTaskColumn("queuedLogEpisodeSignature", (task) => task.queuedLogEpisodeSignature ?? null),
|
|
62942
62979
|
defineTaskColumn("paused", (task) => task.paused ? 1 : 0),
|
|
62943
62980
|
defineTaskColumn("pausedReason", (task) => task.pausedReason ?? null),
|
|
62944
62981
|
defineTaskColumn("wedgeNotification", (task) => toJsonNullable(task.wedgeNotification)),
|
|
@@ -63353,6 +63390,7 @@ function rowToTask(row) {
|
|
|
63353
63390
|
worktree: row.worktree || void 0,
|
|
63354
63391
|
blockedBy: row.blockedBy || void 0,
|
|
63355
63392
|
overlapBlockedBy: row.overlapBlockedBy || void 0,
|
|
63393
|
+
queuedLogEpisodeSignature: row.queuedLogEpisodeSignature || void 0,
|
|
63356
63394
|
paused: row.paused ? true : void 0,
|
|
63357
63395
|
pausedReason: row.pausedReason || void 0,
|
|
63358
63396
|
wedgeNotification: fromJson(row.wedgeNotification) ?? void 0,
|
|
@@ -69472,6 +69510,14 @@ function noop3() {
|
|
|
69472
69510
|
function matchesParentScope(task, sourceParentTaskId) {
|
|
69473
69511
|
return !sourceParentTaskId || task.sourceParentTaskId === sourceParentTaskId;
|
|
69474
69512
|
}
|
|
69513
|
+
async function findActiveDuplicate(store, candidates, predicate) {
|
|
69514
|
+
for (const candidate of candidates) {
|
|
69515
|
+
if (!predicate(candidate)) continue;
|
|
69516
|
+
const flags = await resolveNearDuplicateCanonicalFlags(store, candidate);
|
|
69517
|
+
if (!isNearDuplicateCanonicalInactive(candidate, flags)) return candidate;
|
|
69518
|
+
}
|
|
69519
|
+
return void 0;
|
|
69520
|
+
}
|
|
69475
69521
|
async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
69476
69522
|
const fingerprint = computeContentFingerprint(input);
|
|
69477
69523
|
if (opts?.bypass === true || !fingerprint) {
|
|
@@ -69485,7 +69531,9 @@ async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
|
69485
69531
|
windowMs,
|
|
69486
69532
|
includeArchived: false
|
|
69487
69533
|
});
|
|
69488
|
-
const deterministicConflict =
|
|
69534
|
+
const deterministicConflict = await findActiveDuplicate(
|
|
69535
|
+
store,
|
|
69536
|
+
deterministicMatches,
|
|
69489
69537
|
(match) => matchesParentScope(match, opts?.sourceParentTaskId) && !acknowledged.has(match.id)
|
|
69490
69538
|
);
|
|
69491
69539
|
if (deterministicConflict) {
|
|
@@ -69532,7 +69580,9 @@ async function runDeterministicDuplicateGuard(store, input, opts) {
|
|
|
69532
69580
|
windowMs,
|
|
69533
69581
|
includeArchived: false
|
|
69534
69582
|
});
|
|
69535
|
-
const deterministicConflict =
|
|
69583
|
+
const deterministicConflict = await findActiveDuplicate(
|
|
69584
|
+
store,
|
|
69585
|
+
deterministicMatches,
|
|
69536
69586
|
(match) => matchesParentScope(match, opts.sourceParentTaskId) && !acknowledged.has(match.id)
|
|
69537
69587
|
);
|
|
69538
69588
|
if (deterministicConflict) {
|
|
@@ -69556,7 +69606,9 @@ async function reconcileDeterministicDuplicate(store, args) {
|
|
|
69556
69606
|
windowMs: clampWindowMs(args.windowMs),
|
|
69557
69607
|
includeArchived: false
|
|
69558
69608
|
});
|
|
69559
|
-
const olderSibling =
|
|
69609
|
+
const olderSibling = await findActiveDuplicate(
|
|
69610
|
+
store,
|
|
69611
|
+
siblings,
|
|
69560
69612
|
(sibling) => sibling.id !== args.createdTask.id && sibling.createdAt < args.createdTask.createdAt && matchesParentScope(sibling, args.sourceParentTaskId)
|
|
69561
69613
|
);
|
|
69562
69614
|
if (!olderSibling) {
|
|
@@ -69615,6 +69667,8 @@ var init_duplicate_guard = __esm({
|
|
|
69615
69667
|
"../core/src/duplicates/duplicate-guard.ts"() {
|
|
69616
69668
|
"use strict";
|
|
69617
69669
|
init_duplicate_detection();
|
|
69670
|
+
init_near_duplicate_canonical();
|
|
69671
|
+
init_near_duplicate_canonical_flags();
|
|
69618
69672
|
init_workflow_lifecycle_traits();
|
|
69619
69673
|
FINGERPRINT_WINDOW_DEFAULT_MS = 6e5;
|
|
69620
69674
|
FINGERPRINT_WINDOW_MAX_MS = 36e5;
|
|
@@ -93226,6 +93280,50 @@ async function runPluginColumnTransitionHooksImpl(store, taskId, workflowIr, fro
|
|
|
93226
93280
|
await writeMarker2(remaining);
|
|
93227
93281
|
}
|
|
93228
93282
|
}
|
|
93283
|
+
async function transitionQueuedEpisodeImpl(store, id, transition) {
|
|
93284
|
+
const layer = store.asyncLayer;
|
|
93285
|
+
const projectId = layer.projectId?.trim() || "__legacy_unscoped__";
|
|
93286
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
93287
|
+
const result = await layer.transactionImmediate(async (tx) => {
|
|
93288
|
+
await acquireTaskAdvisoryXactLock(tx, projectId, id);
|
|
93289
|
+
const rows = await tx.select().from(project_exports.tasks).where(and(
|
|
93290
|
+
eq(project_exports.tasks.projectId, projectId),
|
|
93291
|
+
eq(project_exports.tasks.id, id),
|
|
93292
|
+
isNull(project_exports.tasks.deletedAt)
|
|
93293
|
+
));
|
|
93294
|
+
const current = rows[0];
|
|
93295
|
+
if (!current) throw new Error(`Task ${id} not found or archived while queuing`);
|
|
93296
|
+
const appended = !(current.status === "queued" && (current.blockedBy ?? null) === transition.blockedBy && (current.overlapBlockedBy ?? null) === transition.overlapBlockedBy && (current.queuedLogEpisodeSignature ?? null) === transition.signature);
|
|
93297
|
+
const log41 = Array.isArray(current.log) ? [...current.log] : [];
|
|
93298
|
+
if (appended) {
|
|
93299
|
+
log41.push({
|
|
93300
|
+
timestamp: now,
|
|
93301
|
+
action: transition.action,
|
|
93302
|
+
outcome: truncateTaskLogOutcome(transition.outcome),
|
|
93303
|
+
...transition.runContext ? { runContext: transition.runContext } : {}
|
|
93304
|
+
});
|
|
93305
|
+
const limit = getTaskActivityLogEntryLimit();
|
|
93306
|
+
if (log41.length > limit) log41.splice(0, log41.length - limit);
|
|
93307
|
+
}
|
|
93308
|
+
const updated = await tx.update(project_exports.tasks).set({
|
|
93309
|
+
status: "queued",
|
|
93310
|
+
blockedBy: transition.blockedBy,
|
|
93311
|
+
overlapBlockedBy: transition.overlapBlockedBy,
|
|
93312
|
+
queuedLogEpisodeSignature: transition.signature,
|
|
93313
|
+
...appended ? { log: log41 } : {},
|
|
93314
|
+
updatedAt: now
|
|
93315
|
+
}).where(and(
|
|
93316
|
+
eq(project_exports.tasks.projectId, projectId),
|
|
93317
|
+
eq(project_exports.tasks.id, id)
|
|
93318
|
+
)).returning();
|
|
93319
|
+
return { appended, task: updated[0] };
|
|
93320
|
+
});
|
|
93321
|
+
const task = store.rowToTask(store.pgRowToTaskRow(result.task));
|
|
93322
|
+
await store.writeTaskJsonFile(store.taskDir(id), task);
|
|
93323
|
+
if (store.isWatching) store.taskCache.set(id, { ...task });
|
|
93324
|
+
store.emitTaskLifecycleEventSafely("task:updated", [task]);
|
|
93325
|
+
return { appended: result.appended, task };
|
|
93326
|
+
}
|
|
93229
93327
|
async function checkAndRecordUnplannedExecutionBlockImpl(store, id, episode) {
|
|
93230
93328
|
const layer = store.asyncLayer;
|
|
93231
93329
|
const projectId = layer.projectId ?? "__legacy_unscoped__";
|
|
@@ -93337,6 +93435,7 @@ var init_audit_ops = __esm({
|
|
|
93337
93435
|
init_comments();
|
|
93338
93436
|
init_async_persistence();
|
|
93339
93437
|
init_async_comments_attachments();
|
|
93438
|
+
init_task_advisory_lock();
|
|
93340
93439
|
init_project_lane_vocabulary();
|
|
93341
93440
|
init_schema2();
|
|
93342
93441
|
}
|
|
@@ -99119,6 +99218,9 @@ var init_store = __esm({
|
|
|
99119
99218
|
async checkAndRecordUnplannedExecutionBlock(id, episode) {
|
|
99120
99219
|
return checkAndRecordUnplannedExecutionBlockImpl(this, id, episode);
|
|
99121
99220
|
}
|
|
99221
|
+
async transitionQueuedEpisode(id, transition) {
|
|
99222
|
+
return transitionQueuedEpisodeImpl(this, id, transition);
|
|
99223
|
+
}
|
|
99122
99224
|
async logEntry(id, action, outcome, runContext) {
|
|
99123
99225
|
return logEntryImpl(this, id, action, outcome, runContext);
|
|
99124
99226
|
}
|
|
@@ -127885,6 +127987,7 @@ __export(src_exports, {
|
|
|
127885
127987
|
buildInsightExtractionPrompt: () => buildInsightExtractionPrompt,
|
|
127886
127988
|
buildManualRetryResetPatch: () => buildManualRetryResetPatch,
|
|
127887
127989
|
buildOriginalDescriptionSection: () => buildOriginalDescriptionSection,
|
|
127990
|
+
buildPlanningDuplicatePolicyInstruction: () => buildPlanningDuplicatePolicyInstruction,
|
|
127888
127991
|
buildQmdCollectionAddArgs: () => buildQmdCollectionAddArgs,
|
|
127889
127992
|
buildQmdRefreshCommands: () => buildQmdRefreshCommands,
|
|
127890
127993
|
buildQmdSearchArgs: () => buildQmdSearchArgs,
|
|
@@ -128579,6 +128682,7 @@ __export(src_exports, {
|
|
|
128579
128682
|
resolveMergerFallbackModel: () => resolveMergerFallbackModel,
|
|
128580
128683
|
resolveMergerSettingsModel: () => resolveMergerSettingsModel,
|
|
128581
128684
|
resolveMobileNavPrimaryItems: () => resolveMobileNavPrimaryItems,
|
|
128685
|
+
resolveNearDuplicateCanonicalFlags: () => resolveNearDuplicateCanonicalFlags,
|
|
128582
128686
|
resolveNodeOverrideLanes: () => resolveNodeOverrideLanes,
|
|
128583
128687
|
resolveOptionalReviewRevisionBudget: () => resolveOptionalReviewRevisionBudget,
|
|
128584
128688
|
resolveOptionalStepRevisionBudget: () => resolveOptionalStepRevisionBudget,
|
|
@@ -128811,6 +128915,7 @@ var init_src2 = __esm({
|
|
|
128811
128915
|
init_plugin_prompt_condition();
|
|
128812
128916
|
init_plan_approval();
|
|
128813
128917
|
init_near_duplicate_canonical();
|
|
128918
|
+
init_near_duplicate_canonical_flags();
|
|
128814
128919
|
init_gitlab_tracking();
|
|
128815
128920
|
init_planner_intervention2();
|
|
128816
128921
|
init_planner_overseer_events();
|
|
@@ -169919,14 +170024,14 @@ async function findDefinedFeatureBootstrapDuplicate(store, input, sourceAgentId,
|
|
|
169919
170024
|
if (!sourceAgentId && !sourceParentTaskId) return void 0;
|
|
169920
170025
|
const candidates = await store.listTasks({ slim: true, includeArchived: true, includeDeleted: true });
|
|
169921
170026
|
const byId = new Map(candidates.map((task) => [task.id, task]));
|
|
169922
|
-
const
|
|
170027
|
+
const isTerminalCandidate = await resolveTerminalColumnsForTasks(store, candidates);
|
|
169923
170028
|
const matches = findSameAgentDuplicates({
|
|
169924
170029
|
title: input.title,
|
|
169925
170030
|
description: input.description,
|
|
169926
170031
|
sourceParentTaskId
|
|
169927
170032
|
}, candidates.flatMap((task) => {
|
|
169928
170033
|
const createdAt = Date.parse(task.createdAt);
|
|
169929
|
-
if (Number.isNaN(createdAt) || task.deletedAt ||
|
|
170034
|
+
if (Number.isNaN(createdAt) || task.deletedAt || isTerminalCandidate(task)) return [];
|
|
169930
170035
|
return [{
|
|
169931
170036
|
id: task.id,
|
|
169932
170037
|
title: task.title ?? "",
|
|
@@ -169977,21 +170082,6 @@ async function resolveTerminalColumnsForTasks(store, tasks2) {
|
|
|
169977
170082
|
}
|
|
169978
170083
|
return (task) => terminalByTaskId.get(task.id)?.has(task.column) === true;
|
|
169979
170084
|
}
|
|
169980
|
-
async function resolveArchivedColumnsForTasks(store, tasks2) {
|
|
169981
|
-
const cache = /* @__PURE__ */ new Map();
|
|
169982
|
-
const archivedByTaskId = /* @__PURE__ */ new Map();
|
|
169983
|
-
for (const task of tasks2) {
|
|
169984
|
-
if (archivedByTaskId.has(task.id)) continue;
|
|
169985
|
-
const columns = /* @__PURE__ */ new Set(["archived"]);
|
|
169986
|
-
try {
|
|
169987
|
-
const ir2 = await resolveWorkflowIrForTask(store, task.id, cache);
|
|
169988
|
-
if (ir2) for (const id of columnsWithFlag(ir2, "archived")) columns.add(id);
|
|
169989
|
-
} catch {
|
|
169990
|
-
}
|
|
169991
|
-
archivedByTaskId.set(task.id, columns);
|
|
169992
|
-
}
|
|
169993
|
-
return (task) => archivedByTaskId.get(task.id)?.has(task.column) === true;
|
|
169994
|
-
}
|
|
169995
170085
|
async function createAgentTask(store, input, options) {
|
|
169996
170086
|
const validateDuplicateCanonical = input.validateDuplicateCanonical;
|
|
169997
170087
|
const settings = typeof store.getSettings === "function" ? await store.getSettings() : {};
|
|
@@ -170056,11 +170146,12 @@ async function createAgentTask(store, input, options) {
|
|
|
170056
170146
|
try {
|
|
170057
170147
|
const acknowledged = new Set(options?.acknowledgedDuplicates ?? []);
|
|
170058
170148
|
const candidates = await store.findRecentTasksBySourceParentTaskId(sourceParentTaskId);
|
|
170149
|
+
const isTerminalCandidate = await resolveTerminalColumnsForTasks(store, candidates);
|
|
170059
170150
|
const matches = findSameAgentDuplicates({
|
|
170060
170151
|
title: input.title,
|
|
170061
170152
|
description: input.description,
|
|
170062
170153
|
sourceParentTaskId
|
|
170063
|
-
}, candidates.map((candidate) => ({
|
|
170154
|
+
}, candidates.filter((candidate) => !isTerminalCandidate(candidate)).map((candidate) => ({
|
|
170064
170155
|
id: candidate.id,
|
|
170065
170156
|
title: candidate.title ?? "",
|
|
170066
170157
|
description: candidate.description,
|
|
@@ -170288,7 +170379,7 @@ function createTaskSearchTool(store) {
|
|
|
170288
170379
|
return {
|
|
170289
170380
|
name: "fn_task_search",
|
|
170290
170381
|
label: "Search Tasks",
|
|
170291
|
-
description: "Keyword search across
|
|
170382
|
+
description: "Keyword search across active tasks by default. Done and archived history is opt-in and must not be used for duplicate detection.",
|
|
170292
170383
|
parameters: taskSearchParams,
|
|
170293
170384
|
execute: async (_id, params) => {
|
|
170294
170385
|
const query = params.query.trim();
|
|
@@ -170301,10 +170392,10 @@ function createTaskSearchTool(store) {
|
|
|
170301
170392
|
const limit = Math.min(50, Math.max(1, Math.floor(params.limit ?? 20)));
|
|
170302
170393
|
const results = await store.searchTasks(query, {
|
|
170303
170394
|
slim: true,
|
|
170304
|
-
includeArchived: params.includeArchived ??
|
|
170395
|
+
includeArchived: params.includeArchived ?? false,
|
|
170305
170396
|
limit
|
|
170306
170397
|
});
|
|
170307
|
-
const includeDone = params.includeDone ??
|
|
170398
|
+
const includeDone = params.includeDone ?? false;
|
|
170308
170399
|
const isTerminalResult = includeDone ? void 0 : await resolveTerminalColumnsForTasks(store, results);
|
|
170309
170400
|
const filtered = includeDone ? results : results.filter((task) => !isTerminalResult(task));
|
|
170310
170401
|
const lines = filtered.map(formatTaskSummaryLine);
|
|
@@ -191422,6 +191513,9 @@ var Scheduler = class {
|
|
|
191422
191513
|
}
|
|
191423
191514
|
}
|
|
191424
191515
|
}
|
|
191516
|
+
async transitionQueuedEpisode(task, input) {
|
|
191517
|
+
return (await this.store.transitionQueuedEpisode(task.id, input)).appended;
|
|
191518
|
+
}
|
|
191425
191519
|
async logDispatchQueuedReason(taskId, reason, memoKey) {
|
|
191426
191520
|
const key = `${taskId}:${memoKey ?? reason}`;
|
|
191427
191521
|
if (this.wasDispatchQueuedReasonLogged.has(key)) {
|
|
@@ -191934,11 +192028,13 @@ var Scheduler = class {
|
|
|
191934
192028
|
}
|
|
191935
192029
|
const unmetDeps = getUnmetSchedulingDependencies(task, tasks2, schedulingDependencyOptions);
|
|
191936
192030
|
if (unmetDeps.length > 0) {
|
|
191937
|
-
|
|
191938
|
-
|
|
191939
|
-
|
|
192031
|
+
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
192032
|
+
await this.transitionQueuedEpisode(task, {
|
|
192033
|
+
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
192034
|
+
blockedBy: unmetDeps[0] ?? null,
|
|
192035
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
192036
|
+
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`
|
|
191940
192037
|
});
|
|
191941
|
-
await this.logDispatchQueuedReason(task.id, `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`);
|
|
191942
192038
|
this.options.onBlocked?.(task, unmetDeps);
|
|
191943
192039
|
return null;
|
|
191944
192040
|
}
|
|
@@ -192299,16 +192395,13 @@ var Scheduler = class {
|
|
|
192299
192395
|
const overlappingTaskId = Array.from(activeScopes.entries()).sort(([aId], [bId]) => aId.localeCompare(bId)).find(([, activeScope]) => this.pathsOverlap(taskScope, activeScope))?.[0] ?? null;
|
|
192300
192396
|
if (overlappingTaskId) {
|
|
192301
192397
|
const activeLeaseColumn = activeScopeColumns.get(overlappingTaskId) ?? "in-progress";
|
|
192302
|
-
await this.
|
|
192303
|
-
|
|
192398
|
+
await this.transitionQueuedEpisode(task, {
|
|
192399
|
+
signature: `file-scope:${overlappingTaskId}`,
|
|
192304
192400
|
blockedBy: null,
|
|
192305
|
-
overlapBlockedBy: overlappingTaskId
|
|
192401
|
+
overlapBlockedBy: overlappingTaskId,
|
|
192402
|
+
action: `queued \u2014 blocked by active file-scope lease ${overlappingTaskId} (column=${activeLeaseColumn})`
|
|
192306
192403
|
});
|
|
192307
192404
|
await this.rollbackRunningAgentsForQueuedTodoTask(task.id);
|
|
192308
|
-
await this.logDispatchQueuedReason(
|
|
192309
|
-
task.id,
|
|
192310
|
-
`queued \u2014 blocked by active file-scope lease ${overlappingTaskId} (column=${activeLeaseColumn})`
|
|
192311
|
-
);
|
|
192312
192405
|
return null;
|
|
192313
192406
|
}
|
|
192314
192407
|
if (task.overlapBlockedBy) {
|
|
@@ -207098,13 +207191,6 @@ function hasTerminalInvalidDoneTransition(task) {
|
|
|
207098
207191
|
return error2.includes("Invalid transition:") && error2.includes("\u2192 'done'");
|
|
207099
207192
|
}
|
|
207100
207193
|
var UNREADABLE_WORKFLOW_SELECTION = "\0unreadable-workflow-selection";
|
|
207101
|
-
async function resolveNearDuplicateCanonicalFlags(store, canonical) {
|
|
207102
|
-
if (!canonical?.column) return void 0;
|
|
207103
|
-
const ir2 = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
207104
|
-
if (!ir2 || ir2.version !== "v2") return void 0;
|
|
207105
|
-
const column = ir2.columns.find((candidate) => candidate.id === canonical.column);
|
|
207106
|
-
return column ? resolveColumnFlags(column) : void 0;
|
|
207107
|
-
}
|
|
207108
207194
|
var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidence {
|
|
207109
207195
|
constructor(store, options) {
|
|
207110
207196
|
super();
|
|
@@ -207156,7 +207242,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
207156
207242
|
strandedHoldContinuationNoActionAudited = /* @__PURE__ */ new Set();
|
|
207157
207243
|
/* FNXC:SymbolLock 2026-07-30-14:20: idle symbol-lock sweeps emit one no-action audit until a stale lock re-arms the diagnostic. */
|
|
207158
207244
|
symbolLockNoActionAudited = false;
|
|
207159
|
-
preservedQueuedOverlapLogged = /* @__PURE__ */ new Map();
|
|
207160
207245
|
maintenanceTickCounter = 0;
|
|
207161
207246
|
taskLifecycleRetentionLastPrunedAt = /* @__PURE__ */ new Map();
|
|
207162
207247
|
processBootStartedAt = Date.now();
|
|
@@ -207816,7 +207901,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
207816
207901
|
}
|
|
207817
207902
|
this.finalizeUnprovenWarned.clear();
|
|
207818
207903
|
this.strandedCompletedFailureProvenanceWarned.clear();
|
|
207819
|
-
this.preservedQueuedOverlapLogged.clear();
|
|
207820
207904
|
log34.debug("Stopped");
|
|
207821
207905
|
}
|
|
207822
207906
|
// ── Auto-unpause ───────────────────────────────────────────────────
|
|
@@ -210385,17 +210469,20 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
210385
210469
|
if (todoTaskIds.has(dependent.id)) {
|
|
210386
210470
|
if (unresolvedDeps.length > 0) {
|
|
210387
210471
|
const nextBlocker = unresolvedDeps[0];
|
|
210388
|
-
|
|
210389
|
-
await this.store.
|
|
210390
|
-
|
|
210391
|
-
|
|
210392
|
-
|
|
210472
|
+
const normalizedUnresolvedDeps = [...new Set(unresolvedDeps)].sort();
|
|
210473
|
+
await this.store.transitionQueuedEpisode(dependent.id, {
|
|
210474
|
+
signature: `dependency:${normalizedUnresolvedDeps.join(",")}`,
|
|
210475
|
+
blockedBy: nextBlocker,
|
|
210476
|
+
overlapBlockedBy,
|
|
210477
|
+
action: `Auto-recovered (FN-4523): cleared stale blockedBy \u2014 blocker ${taskId} is done; now blocked by ${nextBlocker}`
|
|
210478
|
+
});
|
|
210393
210479
|
} else if (hasActiveOverlapBlocker) {
|
|
210394
|
-
await this.store.
|
|
210395
|
-
|
|
210396
|
-
|
|
210397
|
-
|
|
210398
|
-
|
|
210480
|
+
await this.store.transitionQueuedEpisode(dependent.id, {
|
|
210481
|
+
signature: `file-scope:${overlapBlockedBy}`,
|
|
210482
|
+
blockedBy: null,
|
|
210483
|
+
overlapBlockedBy,
|
|
210484
|
+
action: `Auto-recovered (FN-4523): preserved queued status \u2014 still blocked by file scope overlap with ${overlapBlockedBy}`
|
|
210485
|
+
});
|
|
210399
210486
|
} else {
|
|
210400
210487
|
await this.store.updateTask(dependent.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
210401
210488
|
await this.store.logEntry(
|
|
@@ -210908,16 +210995,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
210908
210995
|
countBlockedDepth(tasks2) {
|
|
210909
210996
|
return tasks2.filter((task) => typeof task.blockedBy === "string" && task.blockedBy.trim().length > 0).length;
|
|
210910
210997
|
}
|
|
210911
|
-
shouldLogPreservedQueuedOverlap(taskId, overlapBlockedBy) {
|
|
210912
|
-
if (!overlapBlockedBy) return false;
|
|
210913
|
-
const previous = this.preservedQueuedOverlapLogged.get(taskId);
|
|
210914
|
-
if (previous === overlapBlockedBy) return false;
|
|
210915
|
-
this.preservedQueuedOverlapLogged.set(taskId, overlapBlockedBy);
|
|
210916
|
-
return true;
|
|
210917
|
-
}
|
|
210918
|
-
clearPreservedQueuedOverlapMemo(taskId) {
|
|
210919
|
-
this.preservedQueuedOverlapLogged.delete(taskId);
|
|
210920
|
-
}
|
|
210921
210998
|
/**
|
|
210922
210999
|
* #1401: periodic transitionPending recovery sweep. Delegates to the store's
|
|
210923
211000
|
* idempotent recovery method (a no-op when no stale markers exist), keeping
|
|
@@ -211150,7 +211227,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211150
211227
|
(task) => task.status === "queued" && (task.dependencies.length > 0 || Boolean(task.overlapBlockedBy))
|
|
211151
211228
|
);
|
|
211152
211229
|
if (blockedTasks.length === 0 && queuedDependencyTasks.length === 0) {
|
|
211153
|
-
this.preservedQueuedOverlapLogged.clear();
|
|
211154
211230
|
return 0;
|
|
211155
211231
|
}
|
|
211156
211232
|
const allTasks = await this.store.listTasks({ includeArchived: true });
|
|
@@ -211222,13 +211298,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211222
211298
|
hold: /* @__PURE__ */ new Set(["todo"]),
|
|
211223
211299
|
review: /* @__PURE__ */ new Set(["in-review"])
|
|
211224
211300
|
};
|
|
211225
|
-
for (const [taskId, lastLoggedBlockerId] of this.preservedQueuedOverlapLogged) {
|
|
211226
|
-
const memoTask = taskById.get(taskId);
|
|
211227
|
-
const memoHasActiveOverlapBlocker = memoTask ? await hasActiveFileScopeOverlapBlocker(memoTask, memoTask.overlapBlockedBy) : false;
|
|
211228
|
-
if (!candidates.has(taskId) || !memoTask || !lanesOf(taskId).hold.has(memoTask.column) || memoTask.status !== "queued" || memoTask.overlapBlockedBy !== lastLoggedBlockerId || !memoHasActiveOverlapBlocker) {
|
|
211229
|
-
this.clearPreservedQueuedOverlapMemo(taskId);
|
|
211230
|
-
}
|
|
211231
|
-
}
|
|
211232
211301
|
for (const task of candidates.values()) {
|
|
211233
211302
|
const blockerId = task.blockedBy;
|
|
211234
211303
|
const unresolvedDeps = task.dependencies.filter((depId) => {
|
|
@@ -211301,7 +211370,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211301
211370
|
let didRecover = false;
|
|
211302
211371
|
if (todoTaskIds.has(task.id)) {
|
|
211303
211372
|
if (unresolvedDeps.length > 0) {
|
|
211304
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
211305
211373
|
const nextBlocker2 = unresolvedDeps[0];
|
|
211306
211374
|
if (nextBlocker2 === blockerId) {
|
|
211307
211375
|
continue;
|
|
@@ -211310,19 +211378,19 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211310
211378
|
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}`);
|
|
211311
211379
|
didRecover = true;
|
|
211312
211380
|
} else if (hasActiveOverlapBlocker) {
|
|
211313
|
-
await this.store.
|
|
211314
|
-
|
|
211315
|
-
|
|
211316
|
-
|
|
211317
|
-
|
|
211381
|
+
const transition = await this.store.transitionQueuedEpisode(task.id, {
|
|
211382
|
+
signature: `file-scope:${task.overlapBlockedBy}`,
|
|
211383
|
+
blockedBy: null,
|
|
211384
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
211385
|
+
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}`
|
|
211386
|
+
});
|
|
211387
|
+
didRecover = transition.appended;
|
|
211318
211388
|
} else {
|
|
211319
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
211320
211389
|
await this.store.updateTask(task.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
211321
211390
|
await this.store.logEntry(task.id, `Auto-recovered (FN-5488): cleared stale blockedBy \u2014 blocker=${blockerId} blockerStatus=${blocker?.status ?? "none"} reason=${reasonCode ?? "unspecified"}; ${reason}`);
|
|
211322
211391
|
didRecover = true;
|
|
211323
211392
|
}
|
|
211324
211393
|
} else {
|
|
211325
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
211326
211394
|
await this.store.updateTask(task.id, { blockedBy: null });
|
|
211327
211395
|
await this.store.logEntry(task.id, `Auto-recovered (FN-4091): cleared stale blockedBy \u2014 ${reason}`);
|
|
211328
211396
|
didRecover = true;
|
|
@@ -211342,13 +211410,14 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211342
211410
|
if (queuedDependencyTaskIds.has(task.id)) {
|
|
211343
211411
|
try {
|
|
211344
211412
|
if (hasActiveOverlapBlocker) {
|
|
211345
|
-
await this.store.
|
|
211346
|
-
|
|
211347
|
-
|
|
211348
|
-
|
|
211349
|
-
|
|
211413
|
+
const transition = await this.store.transitionQueuedEpisode(task.id, {
|
|
211414
|
+
signature: `file-scope:${task.overlapBlockedBy}`,
|
|
211415
|
+
blockedBy: null,
|
|
211416
|
+
overlapBlockedBy: task.overlapBlockedBy ?? null,
|
|
211417
|
+
action: `Auto-recovered: preserved queued status \u2014 still blocked by file scope overlap with ${task.overlapBlockedBy}`
|
|
211418
|
+
});
|
|
211419
|
+
if (transition.appended) recovered++;
|
|
211350
211420
|
} else {
|
|
211351
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
211352
211421
|
await this.store.updateTask(task.id, { blockedBy: null, overlapBlockedBy: null, status: null });
|
|
211353
211422
|
}
|
|
211354
211423
|
} catch (err) {
|
|
@@ -211358,7 +211427,6 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
211358
211427
|
}
|
|
211359
211428
|
continue;
|
|
211360
211429
|
}
|
|
211361
|
-
this.clearPreservedQueuedOverlapMemo(task.id);
|
|
211362
211430
|
const nextBlocker = unresolvedDeps[0] ?? null;
|
|
211363
211431
|
if (nextBlocker && task.blockedBy !== nextBlocker) {
|
|
211364
211432
|
try {
|
|
@@ -217569,14 +217637,12 @@ var SelfHealingManager = class _SelfHealingManager extends SelfHealingGitEvidenc
|
|
|
217569
217637
|
if (canClearInactiveMarker) {
|
|
217570
217638
|
rmSync7(promptPath, { force: true });
|
|
217571
217639
|
const priorClearCount = typeof task.sourceMetadata?.duplicateMarkerClearCount === "number" ? task.sourceMetadata.duplicateMarkerClearCount : 0;
|
|
217572
|
-
const
|
|
217573
|
-
const exhausted = alreadyDismissed || priorClearCount >= 1;
|
|
217574
|
-
const patch = exhausted ? buildMarkerExhaustedFailedTaskPatch(marker.canonicalId, priorClearCount) : buildMarkerClearedReplanTaskPatch(marker.canonicalId, priorClearCount);
|
|
217640
|
+
const patch = buildMarkerClearedReplanTaskPatch(marker.canonicalId, priorClearCount);
|
|
217575
217641
|
await this.store.updateTask(task.id, patch);
|
|
217576
217642
|
if (typeof this.store.logEntry === "function") {
|
|
217577
217643
|
await Promise.resolve(this.store.logEntry(
|
|
217578
217644
|
task.id,
|
|
217579
|
-
|
|
217645
|
+
TRIAGE_MARKER_CLEARED_REPLAN_LOG_ACTION,
|
|
217580
217646
|
buildInactiveDuplicateClearFeedback(marker.canonicalId)
|
|
217581
217647
|
)).catch(() => {
|
|
217582
217648
|
});
|
|
@@ -227611,13 +227677,15 @@ Graph value: ${failureValue}` : ""}`, budget.key),
|
|
|
227611
227677
|
recoveryRehome: true
|
|
227612
227678
|
});
|
|
227613
227679
|
}
|
|
227614
|
-
|
|
227615
|
-
await this.store.
|
|
227616
|
-
|
|
227617
|
-
|
|
227618
|
-
|
|
227619
|
-
|
|
227620
|
-
|
|
227680
|
+
const normalizedUnmetDeps = [...new Set(unmetDeps)].sort();
|
|
227681
|
+
await this.store.transitionQueuedEpisode(liveTask.id, {
|
|
227682
|
+
signature: `dependency:${normalizedUnmetDeps.join(",")}`,
|
|
227683
|
+
blockedBy: unmetDeps[0] ?? null,
|
|
227684
|
+
overlapBlockedBy: liveTask.overlapBlockedBy ?? null,
|
|
227685
|
+
action: `queued \u2014 unmet dependencies: ${unmetDeps.join(", ")}`,
|
|
227686
|
+
outcome: "Executor pre-dispatch dependency gate blocked workflow/authoritative execution.",
|
|
227687
|
+
runContext: this.getRunContextFor(liveTask.id)
|
|
227688
|
+
});
|
|
227621
227689
|
executorLog.log(`${liveTask.id}: executor dispatch blocked by unmet dependencies: ${unmetDeps.join(", ")}`);
|
|
227622
227690
|
return true;
|
|
227623
227691
|
}
|
|
@@ -243563,13 +243631,6 @@ function resolveTaskListFormatter(core) {
|
|
|
243563
243631
|
}
|
|
243564
243632
|
var STALE_PLANNING_STATUS_GRACE_MS = 20 * 6e4;
|
|
243565
243633
|
var LEGACY_PLANNER_COLUMN_IDS = /* @__PURE__ */ new Set(["triage", "todo"]);
|
|
243566
|
-
async function resolveNearDuplicateCanonicalFlags2(store, canonical) {
|
|
243567
|
-
if (!canonical?.column) return void 0;
|
|
243568
|
-
const ir2 = await resolveWorkflowIrForTask(store, canonical.id).catch(() => void 0);
|
|
243569
|
-
if (!ir2 || ir2.version !== "v2") return void 0;
|
|
243570
|
-
const column = ir2.columns.find((candidate) => candidate.id === canonical.column);
|
|
243571
|
-
return column ? resolveColumnFlags(column) : void 0;
|
|
243572
|
-
}
|
|
243573
243634
|
function isOrphanedLegacyTriageRow(column, declaresTriage) {
|
|
243574
243635
|
return column === "triage" && !declaresTriage;
|
|
243575
243636
|
}
|
|
@@ -244961,11 +245022,13 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
244961
245022
|
const defaultTriagePrompt = resolveAgentPrompt("triage", void 0, { plannerHeartbeatPatrolEnabled });
|
|
244962
245023
|
const resolvedBasePrompt = userTriagePrompt || (leanPlanning ? workflowFastPlanningPrompt || builtinSeamPrompt("planning-fast") || defaultTriagePrompt : workflowPlanningPrompt || defaultTriagePrompt);
|
|
244963
245024
|
const renderedBasePrompt = renderTriagePolicyPlaceholders(resolvedBasePrompt, triagePolicySettings);
|
|
245025
|
+
const duplicatePolicyInstruction = buildPlanningDuplicatePolicyInstruction();
|
|
244964
245026
|
const triageLayers = buildPromptLayers({
|
|
244965
245027
|
basePrompt: renderedBasePrompt,
|
|
244966
245028
|
goalContext: triageGoalResolution.goalContext,
|
|
244967
245029
|
agentInstructions: [
|
|
244968
245030
|
triageIdentitySection,
|
|
245031
|
+
duplicatePolicyInstruction,
|
|
244969
245032
|
triageInstructions,
|
|
244970
245033
|
isResearchToolSurfaceEnabled(settings) ? getResearchGuidanceForSurface("triage") : ""
|
|
244971
245034
|
].filter((section) => section.trim()).join("\n\n"),
|
|
@@ -245594,7 +245657,7 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
245594
245657
|
const taskSearch = {
|
|
245595
245658
|
name: "fn_task_search",
|
|
245596
245659
|
label: "Search Tasks",
|
|
245597
|
-
description: "Keyword search across tasks
|
|
245660
|
+
description: "Keyword search across active tasks by default. Done and archived history is opt-in and must not be used for duplicate detection.",
|
|
245598
245661
|
parameters: taskSearchParams2,
|
|
245599
245662
|
execute: async (_callId, params) => {
|
|
245600
245663
|
const query = params.query.trim();
|
|
@@ -245606,10 +245669,10 @@ You are ${assignedAgent.name}${assignedAgent.title?.trim() ? `, ${assignedAgent.
|
|
|
245606
245669
|
}
|
|
245607
245670
|
const results = await store.searchTasks(query, {
|
|
245608
245671
|
slim: true,
|
|
245609
|
-
includeArchived: params.includeArchived ??
|
|
245672
|
+
includeArchived: params.includeArchived ?? false,
|
|
245610
245673
|
limit: params.limit ?? 20
|
|
245611
245674
|
});
|
|
245612
|
-
const includeDone = params.includeDone ??
|
|
245675
|
+
const includeDone = params.includeDone ?? false;
|
|
245613
245676
|
const isTerminalResult = includeDone ? void 0 : await resolveTerminalColumnsForTasks(store, results);
|
|
245614
245677
|
const filtered = includeDone ? results : results.filter((t) => !isTerminalResult(t));
|
|
245615
245678
|
if (filtered.length === 0) {
|
|
@@ -245848,7 +245911,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
245848
245911
|
if (canonicalTask?.id.toLowerCase() === task.id.toLowerCase()) {
|
|
245849
245912
|
return false;
|
|
245850
245913
|
}
|
|
245851
|
-
const canonicalFlags = await
|
|
245914
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
245852
245915
|
if (isNearDuplicateCanonicalInactive(canonicalTask, canonicalFlags)) {
|
|
245853
245916
|
planLog.log(`${task.id} explicit duplicate marker targets inactive ${canonicalId}; clearing marker for replanning`);
|
|
245854
245917
|
} else {
|
|
@@ -245992,17 +246055,16 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
245992
246055
|
const canonicalId = explicitDuplicateMarker.canonicalId;
|
|
245993
246056
|
const canonicalTask = await this.store.getTask(canonicalId).catch(() => null);
|
|
245994
246057
|
const canClearInactiveMarker = task.userPaused !== true && (task.paused !== true || task.pausedReason === "duplicate-decision-required") && (task.pausedReason == null || task.pausedReason === "duplicate-decision-required");
|
|
245995
|
-
const canonicalFlags = await
|
|
246058
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
245996
246059
|
const liveMeta = (await this.store.getTask(task.id).catch(() => null))?.sourceMetadata ?? task.sourceMetadata;
|
|
245997
246060
|
const priorClearCount = typeof liveMeta?.duplicateMarkerClearCount === "number" ? liveMeta.duplicateMarkerClearCount : 0;
|
|
245998
246061
|
if (isNearDuplicateCanonicalInactive(canonicalTask ?? void 0, canonicalFlags)) {
|
|
245999
246062
|
if (canClearInactiveMarker) {
|
|
246000
|
-
const alreadyDismissed = isTriageDuplicateKeepAcknowledged(liveMeta, canonicalId);
|
|
246001
246063
|
await this.clearDuplicateMarkerForReplan(
|
|
246002
246064
|
task,
|
|
246003
246065
|
canonicalId,
|
|
246004
246066
|
buildInactiveDuplicateClearFeedback(canonicalId),
|
|
246005
|
-
{ exhausted:
|
|
246067
|
+
{ exhausted: false, priorClearCount }
|
|
246006
246068
|
);
|
|
246007
246069
|
}
|
|
246008
246070
|
return;
|
|
@@ -246242,7 +246304,7 @@ Remove or replace these ids and call fn_task_create again.`
|
|
|
246242
246304
|
if (!canonicalTask) {
|
|
246243
246305
|
return;
|
|
246244
246306
|
}
|
|
246245
|
-
const canonicalFlags = await
|
|
246307
|
+
const canonicalFlags = await resolveNearDuplicateCanonicalFlags(this.store, canonicalTask);
|
|
246246
246308
|
if (isNearDuplicateCanonicalInactive(canonicalTask, canonicalFlags)) {
|
|
246247
246309
|
planLog.log(`${task.id}: near-duplicate candidate ${canonical.id} is inactive; skipping near-duplicate flag`);
|
|
246248
246310
|
return;
|
|
@@ -248158,6 +248220,40 @@ var InProcessRuntime = class extends EventEmitter27 {
|
|
|
248158
248220
|
throw err;
|
|
248159
248221
|
}
|
|
248160
248222
|
}
|
|
248223
|
+
/**
|
|
248224
|
+
* Close every process-local admission source without aborting work that is
|
|
248225
|
+
* already running. Development source reload uses this boundary before it
|
|
248226
|
+
* waits for the live-agent count to reach zero.
|
|
248227
|
+
*/
|
|
248228
|
+
beginDrain() {
|
|
248229
|
+
if (this.status !== "active") return;
|
|
248230
|
+
this.setStatus("paused");
|
|
248231
|
+
if (this.workflowContinuationTimer) {
|
|
248232
|
+
clearInterval(this.workflowContinuationTimer);
|
|
248233
|
+
this.workflowContinuationTimer = void 0;
|
|
248234
|
+
}
|
|
248235
|
+
const admissionStops = [
|
|
248236
|
+
["self-healing manager", () => this.selfHealingManager?.stop()],
|
|
248237
|
+
["routine scheduler", () => this.routineScheduler?.stop()],
|
|
248238
|
+
["trigger scheduler", () => this.triggerScheduler?.stop()],
|
|
248239
|
+
["stuck task detector", () => this.stuckTaskDetector?.stop()],
|
|
248240
|
+
["heartbeat monitor", () => this.heartbeatMonitor?.stop()],
|
|
248241
|
+
["triage processor", () => this.triageProcessor?.stop()],
|
|
248242
|
+
["scheduler", () => this.scheduler?.stop()],
|
|
248243
|
+
["mission autopilot", () => this.missionAutopilot?.stop()],
|
|
248244
|
+
["mission execution loop", () => this.missionExecutionLoop?.stop()]
|
|
248245
|
+
];
|
|
248246
|
+
for (const [label, stop] of admissionStops) {
|
|
248247
|
+
try {
|
|
248248
|
+
stop();
|
|
248249
|
+
} catch (error2) {
|
|
248250
|
+
runtimeLog.warn(
|
|
248251
|
+
`Failed to stop ${label} while draining ${this.config.projectId}: ${error2 instanceof Error ? error2.message : String(error2)}`
|
|
248252
|
+
);
|
|
248253
|
+
}
|
|
248254
|
+
}
|
|
248255
|
+
runtimeLog.log(`InProcessRuntime draining for ${this.config.projectId}`);
|
|
248256
|
+
}
|
|
248161
248257
|
/**
|
|
248162
248258
|
* Stop the runtime with graceful shutdown.
|
|
248163
248259
|
*
|
|
@@ -255450,6 +255546,11 @@ ${detail}`);
|
|
|
255450
255546
|
this.started = false;
|
|
255451
255547
|
runtimeLog.log(`ProjectEngine stopped for ${this.config.projectId}`);
|
|
255452
255548
|
}
|
|
255549
|
+
/** Stop new lifecycle admission while allowing active work to finish. */
|
|
255550
|
+
beginDrain() {
|
|
255551
|
+
this.shuttingDown = true;
|
|
255552
|
+
this.runtime.beginDrain();
|
|
255553
|
+
}
|
|
255453
255554
|
// ── Public accessors ──
|
|
255454
255555
|
/** Get the underlying InProcessRuntime. */
|
|
255455
255556
|
getRuntime() {
|