@adhdev/daemon-standalone 1.0.28-rc.6 → 1.0.28-rc.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33262,10 +33262,10 @@ var require_dist3 = __commonJS({
33262
33262
  }
33263
33263
  function getDaemonBuildInfo() {
33264
33264
  if (cached2) return cached2;
33265
- const commit = readInjected(true ? "dd0a9d78c0de3a18edc594b4ae7b39afac2d6b83" : void 0) ?? "unknown";
33266
- const commitShort = readInjected(true ? "dd0a9d78" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33267
- const version2 = readInjected(true ? "1.0.28-rc.6" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33268
- const builtAt = readInjected(true ? "2026-07-25T07:35:12.497Z" : void 0);
33265
+ const commit = readInjected(true ? "cb5f0a4f64296587a261176e08731f2f3ed78766" : void 0) ?? "unknown";
33266
+ const commitShort = readInjected(true ? "cb5f0a4f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33267
+ const version2 = readInjected(true ? "1.0.28-rc.8" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33268
+ const builtAt = readInjected(true ? "2026-07-25T12:21:31.780Z" : void 0);
33269
33269
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
33270
33270
  return cached2;
33271
33271
  }
@@ -40272,6 +40272,10 @@ Next step: ${nextStep}`;
40272
40272
  node_id TEXT,
40273
40273
  session_id TEXT,
40274
40274
  provider_type TEXT,
40275
+ -- LEDGER-TASK-TRACEABILITY (B): the task a lifecycle entry pertains to,
40276
+ -- promoted from payload.taskId so kind+task_id joins are index-backed
40277
+ -- (legacy DBs get this column via migrateMeshIsolationColumns' ALTER).
40278
+ task_id TEXT,
40275
40279
  payload TEXT NOT NULL DEFAULT '{}'
40276
40280
  );
40277
40281
 
@@ -40443,6 +40447,15 @@ Next step: ${nextStep}`;
40443
40447
  `);
40444
40448
  this.db.exec(`DROP TABLE IF EXISTS mesh_direct_delivered_events`);
40445
40449
  this.db.exec(`DROP TABLE IF EXISTS mesh_completion_conflicts`);
40450
+ const ledgerCols = this.tableColumns("mesh_event_ledger");
40451
+ if (!ledgerCols.has("task_id")) {
40452
+ this.db.exec(`ALTER TABLE mesh_event_ledger ADD COLUMN task_id TEXT`);
40453
+ }
40454
+ this.db.exec(`
40455
+ CREATE INDEX IF NOT EXISTS idx_mesh_event_ledger_task
40456
+ ON mesh_event_ledger(mesh_id, task_id, timestamp)
40457
+ WHERE task_id IS NOT NULL
40458
+ `);
40446
40459
  } catch (err) {
40447
40460
  if (!loggedMigrationFailure) {
40448
40461
  loggedMigrationFailure = true;
@@ -41394,8 +41407,8 @@ Next step: ${nextStep}`;
41394
41407
  }
41395
41408
  this.db.prepare(
41396
41409
  `INSERT OR IGNORE INTO mesh_event_ledger
41397
- (id, mesh_id, timestamp, kind, node_id, session_id, provider_type, payload)
41398
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
41410
+ (id, mesh_id, timestamp, kind, node_id, session_id, provider_type, task_id, payload)
41411
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
41399
41412
  ).run(
41400
41413
  entry.id,
41401
41414
  entry.meshId,
@@ -41404,6 +41417,7 @@ Next step: ${nextStep}`;
41404
41417
  entry.nodeId ?? null,
41405
41418
  entry.sessionId ?? null,
41406
41419
  entry.providerType ?? null,
41420
+ entry.taskId ?? null,
41407
41421
  JSON.stringify(entry.payload ?? {})
41408
41422
  );
41409
41423
  this.maybeCheckpointWal();
@@ -41434,6 +41448,7 @@ Next step: ${nextStep}`;
41434
41448
  nodeId: r.node_id,
41435
41449
  sessionId: r.session_id,
41436
41450
  providerType: r.provider_type,
41451
+ taskId: r.task_id ?? null,
41437
41452
  payload: (() => {
41438
41453
  try {
41439
41454
  return JSON.parse(r.payload);
@@ -41480,6 +41495,7 @@ Next step: ${nextStep}`;
41480
41495
  nodeId: r.node_id,
41481
41496
  sessionId: r.session_id,
41482
41497
  providerType: r.provider_type,
41498
+ taskId: r.task_id ?? null,
41483
41499
  payload: (() => {
41484
41500
  try {
41485
41501
  return JSON.parse(r.payload);
@@ -41521,8 +41537,8 @@ Next step: ${nextStep}`;
41521
41537
  let imported = 0;
41522
41538
  const stmt = this.db.prepare(
41523
41539
  `INSERT OR IGNORE INTO mesh_event_ledger
41524
- (id, mesh_id, timestamp, kind, node_id, session_id, provider_type, payload)
41525
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
41540
+ (id, mesh_id, timestamp, kind, node_id, session_id, provider_type, task_id, payload)
41541
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
41526
41542
  );
41527
41543
  this.db.transaction(() => {
41528
41544
  for (const e of entries) {
@@ -41535,6 +41551,7 @@ Next step: ${nextStep}`;
41535
41551
  e.nodeId ?? null,
41536
41552
  e.sessionId ?? null,
41537
41553
  e.providerType ?? null,
41554
+ e.taskId ?? null,
41538
41555
  JSON.stringify(e.payload ?? {})
41539
41556
  );
41540
41557
  if (result.changes > 0) imported++;
@@ -41912,6 +41929,7 @@ Next step: ${nextStep}`;
41912
41929
  isIntentionalCleanupStopEntry: () => isIntentionalCleanupStopEntry,
41913
41930
  isNoteExpired: () => isNoteExpired,
41914
41931
  isOperatingNoteTombstoned: () => isOperatingNoteTombstoned,
41932
+ ledgerEntryTaskId: () => ledgerEntryTaskId,
41915
41933
  meshLedgerEvents: () => meshLedgerEvents,
41916
41934
  normalizeMeshWorkerResult: () => normalizeMeshWorkerResult,
41917
41935
  pruneOperatingNotes: () => pruneOperatingNotes,
@@ -41921,6 +41939,11 @@ Next step: ${nextStep}`;
41921
41939
  readOperatingNotes: () => readOperatingNotes,
41922
41940
  tombstoneOperatingNote: () => tombstoneOperatingNote
41923
41941
  });
41942
+ function ledgerEntryTaskId(entry) {
41943
+ if (typeof entry.taskId === "string" && entry.taskId.trim()) return entry.taskId.trim();
41944
+ const fromPayload = entry.payload && typeof entry.payload === "object" ? entry.payload.taskId : void 0;
41945
+ return typeof fromPayload === "string" && fromPayload.trim() ? fromPayload.trim() : void 0;
41946
+ }
41924
41947
  function isIntentionalCleanupStopEntry(entry) {
41925
41948
  if (entry.kind !== "session_stopped" && entry.kind !== "task_failed" && entry.kind !== "task_stalled") return false;
41926
41949
  const payload = entry.payload && typeof entry.payload === "object" && !Array.isArray(entry.payload) ? entry.payload : {};
@@ -42229,6 +42252,10 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42229
42252
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
42230
42253
  ...partial2
42231
42254
  };
42255
+ if (!entry.taskId && TASK_LIFECYCLE_LEDGER_KINDS.has(entry.kind)) {
42256
+ const derived = ledgerEntryTaskId(entry);
42257
+ if (derived) entry.taskId = derived;
42258
+ }
42232
42259
  const filePath = getLedgerPath(meshId);
42233
42260
  if ((0, import_fs7.existsSync)(filePath)) {
42234
42261
  try {
@@ -42250,6 +42277,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42250
42277
  nodeId: entry.nodeId ?? null,
42251
42278
  sessionId: entry.sessionId ?? null,
42252
42279
  providerType: entry.providerType ?? null,
42280
+ taskId: entry.taskId ?? null,
42253
42281
  payload: entry.payload
42254
42282
  });
42255
42283
  } catch {
@@ -42430,7 +42458,13 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42430
42458
  if (!line.trim()) continue;
42431
42459
  try {
42432
42460
  const entry = JSON.parse(line);
42433
- if (entry.id && entry.kind) entries.push(entry);
42461
+ if (entry.id && entry.kind) {
42462
+ if (!entry.taskId) {
42463
+ const derived = ledgerEntryTaskId(entry);
42464
+ if (derived) entry.taskId = derived;
42465
+ }
42466
+ entries.push(entry);
42467
+ }
42434
42468
  } catch {
42435
42469
  }
42436
42470
  }
@@ -42454,6 +42488,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42454
42488
  nodeId: e.nodeId ?? null,
42455
42489
  sessionId: e.sessionId ?? null,
42456
42490
  providerType: e.providerType ?? null,
42491
+ taskId: ledgerEntryTaskId(e) ?? null,
42457
42492
  payload: e.payload ?? {}
42458
42493
  })));
42459
42494
  } catch {
@@ -42462,16 +42497,21 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42462
42497
  function readLedgerFromStore(meshId) {
42463
42498
  const store = MeshRuntimeStore.getInstance();
42464
42499
  ensureLedgerImported(store, meshId);
42465
- return store.readLedgerEntriesOrdered(meshId).map((r) => ({
42466
- id: r.id,
42467
- meshId: r.meshId,
42468
- timestamp: r.timestamp,
42469
- kind: r.kind,
42470
- ...r.nodeId ? { nodeId: r.nodeId } : {},
42471
- ...r.sessionId ? { sessionId: r.sessionId } : {},
42472
- ...r.providerType ? { providerType: r.providerType } : {},
42473
- payload: r.payload && typeof r.payload === "object" ? r.payload : {}
42474
- }));
42500
+ return store.readLedgerEntriesOrdered(meshId).map((r) => {
42501
+ const payload = r.payload && typeof r.payload === "object" ? r.payload : {};
42502
+ const taskId = ledgerEntryTaskId({ taskId: r.taskId ?? void 0, payload });
42503
+ return {
42504
+ id: r.id,
42505
+ meshId: r.meshId,
42506
+ timestamp: r.timestamp,
42507
+ kind: r.kind,
42508
+ ...r.nodeId ? { nodeId: r.nodeId } : {},
42509
+ ...r.sessionId ? { sessionId: r.sessionId } : {},
42510
+ ...r.providerType ? { providerType: r.providerType } : {},
42511
+ ...taskId ? { taskId } : {},
42512
+ payload
42513
+ };
42514
+ });
42475
42515
  }
42476
42516
  function getCachedRawEntries(meshId) {
42477
42517
  const now = Date.now();
@@ -42702,6 +42742,7 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42702
42742
  var import_path7;
42703
42743
  var import_crypto8;
42704
42744
  var import_events;
42745
+ var TASK_LIFECYCLE_LEDGER_KINDS;
42705
42746
  var LEDGER_DIR_NAME;
42706
42747
  var MAX_FILE_SIZE_BYTES;
42707
42748
  var COMPACT_THRESHOLD_BYTES;
@@ -42732,6 +42773,17 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
42732
42773
  import_events = require("events");
42733
42774
  init_mesh_runtime_store();
42734
42775
  init_contracts();
42776
+ TASK_LIFECYCLE_LEDGER_KINDS = /* @__PURE__ */ new Set([
42777
+ "task_dispatched",
42778
+ "task_claimed",
42779
+ "task_completed",
42780
+ "task_failed",
42781
+ "task_stalled",
42782
+ "task_reclaimed",
42783
+ "task_approval_needed",
42784
+ "task_question_pending",
42785
+ "p2p_dispatch_failed"
42786
+ ]);
42735
42787
  LEDGER_DIR_NAME = "mesh-ledger";
42736
42788
  MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
42737
42789
  COMPACT_THRESHOLD_BYTES = 2 * 1024 * 1024;
@@ -51790,6 +51842,43 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
51790
51842
  }
51791
51843
  LOG2.warn("MeshQueue", `Auto-launched session ${sessionId} not interactive after ${LOCAL_LAUNCH_READY_TIMEOUT_MS}ms; dispatching anyway (adapter queue-until-ready will buffer)`);
51792
51844
  }
51845
+ function recordTaskDispatchedLedger(ctx, deliveryId) {
51846
+ const task = ctx.task;
51847
+ const routing = ctx.routingDecision;
51848
+ const routingDecision = {
51849
+ source: routing?.source ?? "queue",
51850
+ selectedNodeId: ctx.nodeId,
51851
+ ...localCoordinatorDaemonId() ? { daemonId: localCoordinatorDaemonId() } : {},
51852
+ transport: ctx.transport,
51853
+ // D: resolved execution profile — prefer the caller's resolved values, fall back
51854
+ // to what the claimed task row carries (queue/idle drains carry it on the task).
51855
+ resolvedProviderType: routing?.resolvedProviderType ?? ctx.providerType,
51856
+ ...routing?.resolvedModel ?? task.model ? { resolvedModel: routing?.resolvedModel ?? task.model } : {},
51857
+ ...routing?.resolvedThinkingLevel ?? task.thinkingLevel ? { resolvedThinkingLevel: routing?.resolvedThinkingLevel ?? task.thinkingLevel } : {},
51858
+ ...routing?.resolvedDifficulty ?? task.difficulty ? { resolvedDifficulty: routing?.resolvedDifficulty ?? task.difficulty } : {},
51859
+ ...typeof routing?.fitnessScore === "number" ? { fitnessScore: routing.fitnessScore } : {},
51860
+ ...routing?.skippedCandidates?.length ? { skippedCandidates: routing.skippedCandidates } : {},
51861
+ ...routing?.requiredTagsResult ? { requiredTagsResult: routing.requiredTagsResult } : {},
51862
+ ...routing?.reason ? { reason: routing.reason } : {}
51863
+ };
51864
+ appendLedgerEntry(ctx.meshId, {
51865
+ kind: "task_dispatched",
51866
+ nodeId: ctx.nodeId,
51867
+ sessionId: ctx.sessionId,
51868
+ providerType: ctx.providerType,
51869
+ taskId: task.id,
51870
+ payload: {
51871
+ taskId: task.id,
51872
+ ...task.missionId ? { missionId: task.missionId } : {},
51873
+ deliveryId,
51874
+ transport: ctx.transport,
51875
+ ...ctx.sourceCoordinatorSessionId ? { coordinatorSessionId: ctx.sourceCoordinatorSessionId } : {},
51876
+ ...ctx.sourceCoordinatorDaemonId ? { coordinatorDaemonId: ctx.sourceCoordinatorDaemonId } : {},
51877
+ ...Array.isArray(task.requiredTags) && task.requiredTags.length ? { requiredTags: task.requiredTags } : {},
51878
+ routingDecision
51879
+ }
51880
+ });
51881
+ }
51793
51882
  function deliverTaskToSession(dispatchThunk, ctx, warmup) {
51794
51883
  const delivery = createSessionDelivery({
51795
51884
  meshId: ctx.meshId,
@@ -51803,6 +51892,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
51803
51892
  ...ctx.sourceCoordinatorSessionId ? { sourceCoordinatorSessionId: ctx.sourceCoordinatorSessionId } : {},
51804
51893
  ...ctx.sourceCoordinatorDaemonId ? { sourceCoordinatorDaemonId: ctx.sourceCoordinatorDaemonId } : {}
51805
51894
  });
51895
+ try {
51896
+ recordTaskDispatchedLedger(ctx, delivery.id);
51897
+ } catch {
51898
+ }
51806
51899
  let dispatchPromise;
51807
51900
  try {
51808
51901
  dispatchPromise = Promise.resolve(dispatchThunk());
@@ -51866,7 +51959,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
51866
51959
  return void 0;
51867
51960
  }
51868
51961
  }
51869
- function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
51962
+ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType, routingDecision) {
51870
51963
  const mesh = getMeshWithCache(components, meshId);
51871
51964
  const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
51872
51965
  if (isWorkspaceAutoFastForwardInFlight(readNonEmptyString(node?.workspace))) {
@@ -51943,6 +52036,24 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
51943
52036
  return false;
51944
52037
  }
51945
52038
  LOG2.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
52039
+ try {
52040
+ appendLedgerEntry(meshId, {
52041
+ kind: "task_claimed",
52042
+ nodeId,
52043
+ sessionId,
52044
+ providerType,
52045
+ taskId: task.id,
52046
+ payload: {
52047
+ taskId: task.id,
52048
+ ...task.missionId ? { missionId: task.missionId } : {},
52049
+ nodeId,
52050
+ sessionId,
52051
+ providerType,
52052
+ claimedAt: (/* @__PURE__ */ new Date()).toISOString()
52053
+ }
52054
+ });
52055
+ } catch {
52056
+ }
51946
52057
  retractActionableSkipIfPreviouslyNotified(meshId, task.id);
51947
52058
  beginTaskDispatchInFlight(meshId, task.id);
51948
52059
  const silentIdlePushOnDispatch = resolveCoordinatorIdlePushPolicy(mesh?.policy) === "auto_silent_on_dispatch";
@@ -51980,7 +52091,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
51980
52091
  task,
51981
52092
  transport: "remote",
51982
52093
  ...sourceCoordinatorSessionId ? { sourceCoordinatorSessionId } : {},
51983
- ...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {}
52094
+ ...localDaemonIdForDispatch ? { sourceCoordinatorDaemonId: localDaemonIdForDispatch } : {},
52095
+ ...routingDecision ? { routingDecision } : {}
51984
52096
  },
51985
52097
  // Warmup-aware deadline: this dispatch can be the FIRST command to a
51986
52098
  // peer whose mesh DataChannel is still opening — charge the cold-open
@@ -52047,7 +52159,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52047
52159
  task,
52048
52160
  transport: "local",
52049
52161
  ...readNonEmptyString(task.sourceCoordinatorSessionId) ? { sourceCoordinatorSessionId: readNonEmptyString(task.sourceCoordinatorSessionId) } : {},
52050
- ...localCoordinatorDaemonId() ? { sourceCoordinatorDaemonId: localCoordinatorDaemonId() } : {}
52162
+ ...localCoordinatorDaemonId() ? { sourceCoordinatorDaemonId: localCoordinatorDaemonId() } : {},
52163
+ ...routingDecision ? { routingDecision } : {}
52051
52164
  }
52052
52165
  );
52053
52166
  return true;
@@ -52485,11 +52598,16 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52485
52598
  nodeId: args.nodeId,
52486
52599
  sessionId: args.sessionId,
52487
52600
  providerType: args.providerType,
52601
+ // (B) promote taskId so this entry joins the task lifecycle timeline.
52602
+ ...args.taskId ? { taskId: args.taskId } : {},
52488
52603
  payload: {
52489
52604
  phase: args.phase,
52490
52605
  taskId: args.taskId,
52491
52606
  reason: args.reason,
52492
- error: args.error
52607
+ error: args.error,
52608
+ // (D) resolved execution profile for the spawned worker.
52609
+ ...args.model ? { resolvedModel: args.model } : {},
52610
+ ...args.thinkingLevel ? { resolvedThinkingLevel: args.thinkingLevel } : {}
52493
52611
  }
52494
52612
  });
52495
52613
  } catch (e) {
@@ -52511,7 +52629,9 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52511
52629
  providerType: args.providerType,
52512
52630
  sessionId: args.sessionId,
52513
52631
  reason: args.reason,
52514
- error: args.error
52632
+ error: args.error,
52633
+ ...args.model ? { model: args.model } : {},
52634
+ ...args.thinkingLevel ? { thinkingLevel: args.thinkingLevel } : {}
52515
52635
  });
52516
52636
  if (args.status === "skipped") {
52517
52637
  if (isActionableSkipReason(args.reason)) {
@@ -52711,6 +52831,14 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52711
52831
  // pass it through for the 'fitness' strategy's task→slot ranking.
52712
52832
  { bumpCursor: true, task: { difficulty: task.difficulty, requiredTags: task.requiredTags } }
52713
52833
  ).map((c) => c.node);
52834
+ const skippedCandidates = [];
52835
+ const SKIPPED_CANDIDATES_MAX = 12;
52836
+ const markSkip = (nodeIdForSkip, reason, extra) => {
52837
+ markAutoLaunch(meshId, task.id, { status: "skipped", reason, nodeId: nodeIdForSkip, ...extra || {} });
52838
+ if (nodeIdForSkip && skippedCandidates.length < SKIPPED_CANDIDATES_MAX) {
52839
+ skippedCandidates.push({ nodeId: nodeIdForSkip, reason });
52840
+ }
52841
+ };
52714
52842
  for (const node of orderedCandidateNodes) {
52715
52843
  const nodeId = readMeshNodeId(node);
52716
52844
  if (!nodeId) continue;
@@ -52719,50 +52847,50 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52719
52847
  const cooldownUntil = autoLaunchCooldownUntil.get(launchKey) || 0;
52720
52848
  if (cooldownUntil > 0 && now >= cooldownUntil) autoLaunchCooldownUntil.delete(launchKey);
52721
52849
  if (autoLaunchInProgress.has(launchKey)) {
52722
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_in_progress", nodeId });
52850
+ markSkip(nodeId, "auto_launch_in_progress");
52723
52851
  continue;
52724
52852
  }
52725
52853
  if (now < cooldownUntil) {
52726
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "auto_launch_cooldown", nodeId });
52854
+ markSkip(nodeId, "auto_launch_cooldown");
52727
52855
  continue;
52728
52856
  }
52729
52857
  if (isDirtyNode(node)) {
52730
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "dirty_workspace", nodeId });
52858
+ markSkip(nodeId, "dirty_workspace");
52731
52859
  continue;
52732
52860
  }
52733
52861
  if (!isLaunchableNode(node)) {
52734
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_not_launch_ready", nodeId });
52862
+ markSkip(nodeId, "node_not_launch_ready");
52735
52863
  continue;
52736
52864
  }
52737
52865
  if (!isMeshNodeFreshEnoughToLaunch(node, freshnessGate)) {
52738
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_stale_behind_upstream", nodeId });
52866
+ markSkip(nodeId, "node_stale_behind_upstream");
52739
52867
  continue;
52740
52868
  }
52741
52869
  const launchTarget = resolveAutoLaunchTarget(components, node);
52742
52870
  if (launchTarget.mode === "skip") {
52743
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: launchTarget.reason || "auto_launch_unavailable", nodeId });
52871
+ markSkip(nodeId, launchTarget.reason || "auto_launch_unavailable");
52744
52872
  autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
52745
52873
  sweepExpiredCooldowns();
52746
52874
  continue;
52747
52875
  }
52748
52876
  if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId, task, node)) {
52749
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
52877
+ markSkip(nodeId, "node_has_live_session_pending_claim");
52750
52878
  continue;
52751
52879
  }
52752
52880
  if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
52753
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
52881
+ markSkip(nodeId, "node_has_active_assignment");
52754
52882
  continue;
52755
52883
  }
52756
52884
  const maxConcurrentSessions = Number(node?.policy?.maxConcurrentSessions);
52757
52885
  if (Number.isFinite(maxConcurrentSessions) && maxConcurrentSessions >= 0 && liveSessionCountForNode(components, meshId, nodeId) >= maxConcurrentSessions) {
52758
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_concurrent_sessions_reached", nodeId });
52886
+ markSkip(nodeId, "max_concurrent_sessions_reached");
52759
52887
  continue;
52760
52888
  }
52761
52889
  autoLaunchInProgress.add(launchKey);
52762
52890
  try {
52763
52891
  const resolved = await resolveUsableProvider(components, nodeId, node, task.requiredTags, { difficulty: task.difficulty, requiredTags: task.requiredTags });
52764
52892
  if (!resolved.providerType) {
52765
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: resolved.reason || "provider_unusable", nodeId });
52893
+ markSkip(nodeId, resolved.reason || "provider_unusable");
52766
52894
  continue;
52767
52895
  }
52768
52896
  const rawEffectiveModel = typeof task.model === "string" && task.model.trim() ? task.model.trim() : resolved.model;
@@ -52773,7 +52901,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52773
52901
  }
52774
52902
  const providerCap = resolveProviderMaxParallel(resolveNodeCapabilitySlots(node), resolved.providerType);
52775
52903
  if (providerCap !== void 0 && activeProviderAssignedCount(meshId, nodeId, resolved.providerType) >= providerCap) {
52776
- markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_provider_parallel_reached", nodeId, providerType: resolved.providerType });
52904
+ markSkip(nodeId, "max_provider_parallel_reached", { providerType: resolved.providerType });
52777
52905
  continue;
52778
52906
  }
52779
52907
  const launchSettings = {
@@ -52801,7 +52929,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52801
52929
  meshCoordinatorDaemonId: launchTarget.coordinatorDaemonId,
52802
52930
  meshCoordinatorNodeId: nodeId
52803
52931
  };
52804
- markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType });
52932
+ markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType, ...effectiveModel ? { model: effectiveModel } : {}, ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {} });
52805
52933
  let launchResult2;
52806
52934
  try {
52807
52935
  launchResult2 = await components.dispatchMeshCommand(launchTarget.daemonId, "launch_cli", withStatusProbeMarker({
@@ -52830,12 +52958,12 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52830
52958
  return false;
52831
52959
  }
52832
52960
  const remoteSessionId = readNonEmptyString(payload.sessionId) || readNonEmptyString(payload.id) || readNonEmptyString(payload.runtimeSessionId);
52833
- markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId: remoteSessionId || void 0 });
52961
+ markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId: remoteSessionId || void 0, ...effectiveModel ? { model: effectiveModel } : {}, ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {} });
52834
52962
  autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS);
52835
52963
  sweepExpiredCooldowns();
52836
52964
  return true;
52837
52965
  }
52838
- markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType });
52966
+ markAutoLaunch(meshId, task.id, { status: "started", nodeId, providerType: resolved.providerType, ...effectiveModel ? { model: effectiveModel } : {}, ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {} });
52839
52967
  const launchResult = await components.cliManager.handleCliCommand("launch_cli", {
52840
52968
  cliType: resolved.providerType,
52841
52969
  dir: node.workspace,
@@ -52860,9 +52988,25 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
52860
52988
  sweepExpiredCooldowns();
52861
52989
  return false;
52862
52990
  }
52863
- markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId });
52991
+ markAutoLaunch(meshId, task.id, { status: "completed", nodeId, providerType: resolved.providerType, sessionId, ...effectiveModel ? { model: effectiveModel } : {}, ...effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {} });
52864
52992
  await waitForLocalSessionReady(components, sessionId);
52865
- tryAssignQueueTask(components, meshId, nodeId, sessionId, resolved.providerType);
52993
+ const requiredTags = Array.isArray(task.requiredTags) ? task.requiredTags.filter((t) => !!t) : [];
52994
+ const routingDecision = {
52995
+ source: "autoLaunch",
52996
+ fitnessScore: nodeFitnessForTask(node, { difficulty: task.difficulty, requiredTags: task.requiredTags }),
52997
+ ...skippedCandidates.length ? { skippedCandidates } : {},
52998
+ requiredTagsResult: {
52999
+ required: requiredTags,
53000
+ satisfied: !requiredTags.length || nodeSatisfiesRequiredTags(requiredTags, buildMeshNodeCapabilityTags(node, resolved.providerType)),
53001
+ missing: requiredTags.filter((t) => !buildMeshNodeCapabilityTags(node, resolved.providerType).includes(t))
53002
+ },
53003
+ resolvedProviderType: resolved.providerType,
53004
+ ...effectiveModel ? { resolvedModel: effectiveModel } : {},
53005
+ ...effectiveThinkingLevel ? { resolvedThinkingLevel: effectiveThinkingLevel } : {},
53006
+ ...task.difficulty ? { resolvedDifficulty: String(task.difficulty) } : {},
53007
+ ...resolved.reason ? { reason: resolved.reason } : {}
53008
+ };
53009
+ tryAssignQueueTask(components, meshId, nodeId, sessionId, resolved.providerType, routingDecision);
52866
53010
  return true;
52867
53011
  } catch (e) {
52868
53012
  markAutoLaunch(meshId, task.id, { status: "failed", error: e?.message || String(e), nodeId });
@@ -62422,7 +62566,7 @@ ${cont}` : cont;
62422
62566
  return true;
62423
62567
  }
62424
62568
  shouldDeferFinishForTranscript(parsed) {
62425
- const requiresFinalAssistant = !!this.provider.requiresFinalAssistantBeforeIdle;
62569
+ const requiresFinalAssistant = resolveTranscriptAuthorityProfile(this.provider).timing === "floor";
62426
62570
  if (!requiresFinalAssistant) return false;
62427
62571
  if (!this.isWaitingForResponse || !this.currentTurnScope || this.hasActionableApproval()) return false;
62428
62572
  const parsedStatus = typeof parsed?.status === "string" ? parsed.status.trim() : "";
@@ -62834,6 +62978,9 @@ ${cont}` : cont;
62834
62978
  pendingOutboundQueue = [];
62835
62979
  pendingOutboundFlushTimer = null;
62836
62980
  pendingOutboundFlushInFlight = false;
62981
+ // Stale-queue watchdog: fires STALE_QUEUE_WARN_MS after the oldest queued
62982
+ // message was enqueued if nothing has been flushed yet.
62983
+ pendingOutboundStaleTimer = null;
62837
62984
  // Submit retry timer — PTY-level, not state machine
62838
62985
  submitRetryTimer = null;
62839
62986
  // PTY-WRITE-SERIALIZE: a single per-session tail promise that serializes every
@@ -63867,6 +64014,9 @@ ${lastSnapshot}`;
63867
64014
  async waitForForceSubmitSettle() {
63868
64015
  await new Promise((resolve28) => setTimeout(resolve28, FORCE_SUBMIT_SETTLE_MS));
63869
64016
  }
64017
+ // Stale-queue threshold: warn if a queued message has not been flushed
64018
+ // within this many milliseconds (instrumentation only, no behavior change).
64019
+ static STALE_QUEUE_WARN_MS = 15e3;
63870
64020
  enqueuePendingOutboundMessage(text, reason, meshTaskId) {
63871
64021
  const content = String(text || "");
63872
64022
  const duplicate = this.pendingOutboundQueue.some((message2) => message2.content === content);
@@ -63874,6 +64024,16 @@ ${lastSnapshot}`;
63874
64024
  return;
63875
64025
  }
63876
64026
  const queuedAt = Date.now();
64027
+ const stableMs = this.lastScreenChangeAt ? queuedAt - this.lastScreenChangeAt : -1;
64028
+ const gateContext = {
64029
+ reason,
64030
+ startupParseGate: this.startupParseGate,
64031
+ ready: this.ready,
64032
+ engineStatus: this.engine.currentStatus,
64033
+ isWaitingForResponse: this.engine.isWaitingForResponse,
64034
+ stableMs,
64035
+ sessionId: this.engine.getTraceSessionId()
64036
+ };
63877
64037
  const message = {
63878
64038
  id: `${queuedAt}:${this.pendingOutboundQueue.length}:${Math.random().toString(36).slice(2, 10)}`,
63879
64039
  role: "user",
@@ -63883,8 +64043,18 @@ ${lastSnapshot}`;
63883
64043
  ...typeof meshTaskId === "string" && meshTaskId.trim() ? { meshTaskId } : {}
63884
64044
  };
63885
64045
  this.pendingOutboundQueue.push(message);
63886
- LOG2.info("CLI", `[${this.cliType}] queued outbound message while busy (${reason}); queue=${this.pendingOutboundQueue.length}`);
64046
+ LOG2.info("CLI", `[${this.cliType}] queued outbound message; gate=${JSON.stringify(gateContext)}; queue=${this.pendingOutboundQueue.length}`);
63887
64047
  this.onStatusChange?.();
64048
+ if (!this.pendingOutboundStaleTimer) {
64049
+ this.pendingOutboundStaleTimer = setTimeout(() => {
64050
+ this.pendingOutboundStaleTimer = null;
64051
+ if (this.pendingOutboundQueue.length === 0) return;
64052
+ const oldest = this.pendingOutboundQueue[0];
64053
+ const staleSec = ((Date.now() - oldest.queuedAt) / 1e3).toFixed(1);
64054
+ const nowStableMs = this.lastScreenChangeAt ? Date.now() - this.lastScreenChangeAt : -1;
64055
+ LOG2.warn("CLI", `[${this.cliType}] STALE QUEUE: ${this.pendingOutboundQueue.length} message(s) undelivered for ${staleSec}s; gate=startupParseGate:${this.startupParseGate} ready:${this.ready} engineStatus:${this.engine.currentStatus} isWaitingForResponse:${this.engine.isWaitingForResponse} stableMs:${nowStableMs} sessionId:${this.engine.getTraceSessionId()} enqueueReason:${oldest.id}`);
64056
+ }, _ProviderCliAdapter.STALE_QUEUE_WARN_MS);
64057
+ }
63888
64058
  }
63889
64059
  shouldQueuePendingOutboundMessage(parsedStatusBeforeSend = null) {
63890
64060
  if (this.provider.allowInputDuringGeneration === true) return null;
@@ -63925,6 +64095,10 @@ ${lastSnapshot}`;
63925
64095
  try {
63926
64096
  await this.sendMessageNow(next.content, false, next.meshTaskId);
63927
64097
  this.pendingOutboundQueue.shift();
64098
+ if (this.pendingOutboundQueue.length === 0 && this.pendingOutboundStaleTimer) {
64099
+ clearTimeout(this.pendingOutboundStaleTimer);
64100
+ this.pendingOutboundStaleTimer = null;
64101
+ }
63928
64102
  this.onStatusChange?.();
63929
64103
  } catch (error48) {
63930
64104
  LOG2.warn("CLI", `[${this.cliType}] queued outbound flush failed: ${error48?.message || error48}`);
@@ -64256,6 +64430,10 @@ ${lastSnapshot}`;
64256
64430
  clearTimeout(this.pendingOutboundFlushTimer);
64257
64431
  this.pendingOutboundFlushTimer = null;
64258
64432
  }
64433
+ if (this.pendingOutboundStaleTimer) {
64434
+ clearTimeout(this.pendingOutboundStaleTimer);
64435
+ this.pendingOutboundStaleTimer = null;
64436
+ }
64259
64437
  this.pendingOutboundQueue = [];
64260
64438
  this.pendingOutboundFlushInFlight = false;
64261
64439
  if (this.ptyProcess) {
@@ -64284,6 +64462,10 @@ ${lastSnapshot}`;
64284
64462
  clearTimeout(this.pendingOutboundFlushTimer);
64285
64463
  this.pendingOutboundFlushTimer = null;
64286
64464
  }
64465
+ if (this.pendingOutboundStaleTimer) {
64466
+ clearTimeout(this.pendingOutboundStaleTimer);
64467
+ this.pendingOutboundStaleTimer = null;
64468
+ }
64287
64469
  this.pendingOutboundQueue = [];
64288
64470
  this.pendingOutboundFlushInFlight = false;
64289
64471
  if (this.ptyProcess) {
@@ -65341,6 +65523,7 @@ ${lastSnapshot}`;
65341
65523
  killIdeProcess: () => killIdeProcess,
65342
65524
  launchIDE: () => launchIDE,
65343
65525
  launchWithCdp: () => launchWithCdp,
65526
+ ledgerEntryTaskId: () => ledgerEntryTaskId,
65344
65527
  listCoordinatorsForWorkspace: () => listCoordinatorsForWorkspace,
65345
65528
  listHostedCliRuntimes: () => listHostedCliRuntimes2,
65346
65529
  listMagiKindPanels: () => listMagiKindPanels,
@@ -85222,7 +85405,12 @@ ${buttons.join("\n")}`;
85222
85405
  fcFinalSummary = extractFinalSummaryFromMessages(evidence.messages);
85223
85406
  } catch {
85224
85407
  }
85225
- const missingEvidence = (resolveTranscriptAuthorityProfile(this.provider).timing === "floor" || fcEvidenceSource === "external-native") && !fcFinalSummary;
85408
+ const synthTiming = resolveTranscriptAuthorityProfile(this.provider).timing;
85409
+ const missingEvidence = (synthTiming === "floor" || synthTiming === "hold" || fcEvidenceSource === "external-native") && !fcFinalSummary;
85410
+ if (missingEvidence && synthTiming === "hold") {
85411
+ LOG2.info("CLI", `[${this.type}] ${reason} held: hold-class transcript not yet landed (source=${fcEvidenceSource})`);
85412
+ return false;
85413
+ }
85226
85414
  const hasMeshContext = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
85227
85415
  if (missingEvidence && !hasMeshContext) {
85228
85416
  LOG2.info("CLI", `[${this.type}] ${reason} suppressed: missing final assistant evidence, no mesh context (source=${fcEvidenceSource})`);