@adhdev/daemon-standalone 1.0.37-rc.2 → 1.0.37-rc.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-standalone",
3
- "version": "1.0.37-rc.2",
3
+ "version": "1.0.37-rc.4",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "license": "AGPL-3.0-or-later",
38
38
  "dependencies": {
39
39
  "@adhdev/ghostty-vt-node": "*",
40
- "@adhdev/session-host-core": "1.0.37-rc.2",
40
+ "@adhdev/session-host-core": "1.0.37-rc.4",
41
41
  "@xterm/addon-serialize": "^0.14.0",
42
42
  "@xterm/xterm": "^6.0.0",
43
43
  "chalk": "^5.3.0",
@@ -2443,6 +2443,21 @@ function hasRecentDuplicateDispatch(ctx, args) {
2443
2443
  }
2444
2444
  return { duplicate: false };
2445
2445
  }
2446
+ function buildMissionInactiveWarning(ctx, missionId) {
2447
+ if (!missionId) return void 0;
2448
+ const mission = (0, import_daemon_core3.getMeshMission)(ctx.mesh.id, missionId);
2449
+ if (!mission || mission.status === "active") return void 0;
2450
+ const hintByStatus = {
2451
+ paused: `Mission '${missionId}' (${mission.title}) is paused \u2014 a new task was just attached to it anyway. Mission status is never auto-transitioned; if this mission should be active again, call mesh_mission_upsert(mission_id: '${missionId}', status: 'active').`,
2452
+ completed: `Mission '${missionId}' (${mission.title}) is already marked completed \u2014 a new task was just attached to it anyway. If this is intentional follow-up work (e.g. a regression fix or post-deploy verification), consider whether it belongs on a new mission, or reopen this one via mesh_mission_upsert(mission_id: '${missionId}', status: 'active') if it isn't actually done.`,
2453
+ abandoned: `Mission '${missionId}' (${mission.title}) is marked abandoned \u2014 a new task was just attached to it anyway. If this mission is being revived, call mesh_mission_upsert(mission_id: '${missionId}', status: 'active').`
2454
+ };
2455
+ const hint = hintByStatus[mission.status] ?? `Mission '${missionId}' (${mission.title}) is not active (status: '${mission.status}') \u2014 a new task was just attached to it anyway. Mission status is never auto-transitioned; call mesh_mission_upsert(mission_id: '${missionId}', status: 'active') if that was not intentional.`;
2456
+ return {
2457
+ missionInactive: { missionId, status: mission.status, title: mission.title },
2458
+ missionInactiveHint: hint
2459
+ };
2460
+ }
2446
2461
  function buildMissingNodeReadChatRecovery(ctx, args) {
2447
2462
  const entries = (0, import_daemon_core3.readLedgerEntries)(ctx.mesh.id, { tail: 300 });
2448
2463
  const relatedEntries = entries.filter((entry) => entry.nodeId === args.node_id || entry.sessionId === args.session_id);
@@ -4097,22 +4112,18 @@ async function meshStatus(ctx, args = {}) {
4097
4112
  }
4098
4113
  return out;
4099
4114
  })() : results;
4115
+ const { maxParallelTasks: _omitPolicyMaxParallelTasks, ...policyForResponse } = mesh.policy || {};
4100
4116
  const response = {
4101
4117
  meshId: mesh.id,
4102
4118
  meshName: mesh.name,
4103
4119
  repoIdentity: mesh.repoIdentity,
4104
- policy: mesh.policy,
4105
- // Mesh-level scheduling rollup (strategy + global cap consumption). Per-node
4106
- // detail (load/priority/provider caps/claim-block reasons) lives on each
4120
+ policy: policyForResponse,
4121
+ // Mesh-level scheduling rollup (strategy only — the global cap numbers are
4122
+ // deliberately not surfaced here, see the comment above). Per-node detail
4123
+ // (load/priority/provider caps/claim-block reasons) lives on each
4107
4124
  // nodes[].scheduling; the node array is dropped here to avoid duplicating it.
4108
4125
  scheduling: {
4109
- strategy: schedulingRuntime.strategy,
4110
- maxParallelTasks: schedulingRuntime.maxParallelTasks,
4111
- maxReadonlyParallelTasks: schedulingRuntime.maxReadonlyParallelTasks,
4112
- activeWriteAssigned: schedulingRuntime.activeWriteAssigned,
4113
- activeReadonlyAssigned: schedulingRuntime.activeReadonlyAssigned,
4114
- globalWriteCapReached: schedulingRuntime.globalWriteCapReached,
4115
- globalReadonlyCapReached: schedulingRuntime.globalReadonlyCapReached
4126
+ strategy: schedulingRuntime.strategy
4116
4127
  },
4117
4128
  payloadMode: compact ? "compact" : "full",
4118
4129
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4370,6 +4381,7 @@ async function meshEnqueueTask(ctx, args) {
4370
4381
  ...ctx.coordinatorSessionId ? { sourceCoordinatorSessionId: ctx.coordinatorSessionId } : {}
4371
4382
  });
4372
4383
  const duplicateWarning = duplicateSuspect ? { duplicateSuspect: { taskId: duplicateSuspect.id, status: duplicateSuspect.status, assignedNodeId: duplicateSuspect.assignedNodeId, targetNodeId: duplicateSuspect.targetNodeId }, duplicateSuspectHint: "An in-flight task with the same message+target already exists. This new task was enqueued anyway (warn-only). Cancel one via mesh_queue_cancel if it is an accidental re-enqueue, or pass allow_duplicate=true to silence this, or block_duplicate=true to refuse next time." } : {};
4384
+ const missionWarning = buildMissionInactiveWarning(ctx, missionId) ?? {};
4373
4385
  const enqueueEcho = {
4374
4386
  ...task.priority ? { priority: task.priority } : {},
4375
4387
  ...task.notBefore ? { notBefore: task.notBefore } : {},
@@ -4388,6 +4400,7 @@ async function meshEnqueueTask(ctx, args) {
4388
4400
  ...targetNodeId ? { targetNodeId } : {},
4389
4401
  ...preferWorktree && !explicitTargetRaw && !targetNodeId ? { preferWorktreeNoOp: true } : {},
4390
4402
  ...duplicateWarning,
4403
+ ...missionWarning,
4391
4404
  queueTrigger,
4392
4405
  ...buildQueueTriggerGuidance(queueTrigger)
4393
4406
  });
@@ -4472,6 +4485,7 @@ async function meshEnqueueTask(ctx, args) {
4472
4485
  ...preferWorktree && !explicitTargetRaw && !targetNodeId ? { preferWorktreeNoOp: true } : {},
4473
4486
  ...eagerPushDeferred ? { eagerPushDeferred: true, eagerPushDeferredReason: "dependencies_unsatisfied" } : {},
4474
4487
  ...duplicateWarning,
4488
+ ...missionWarning,
4475
4489
  queueTrigger,
4476
4490
  ...buildQueueTriggerGuidance(queueTrigger)
4477
4491
  });
@@ -7052,7 +7066,8 @@ async function meshSendTask(ctx, args) {
7052
7066
  ...result2.success ? { source: "direct", taskId } : {},
7053
7067
  taskMode,
7054
7068
  ...result2.success && result2.providerType ? { providerType: result2.providerType } : {},
7055
- dispatched: result2.success === true
7069
+ dispatched: result2.success === true,
7070
+ ...result2.success ? buildMissionInactiveWarning(ctx, missionId) ?? {} : {}
7056
7071
  });
7057
7072
  }
7058
7073
  if (args.session_id) {
@@ -7154,7 +7169,8 @@ async function meshSendTask(ctx, args) {
7154
7169
  sessionStatus,
7155
7170
  taskMode: taskMode || void 0,
7156
7171
  message: policyResult.message,
7157
- nextAction: `Task '${queuedTask.id}' is queued and pinned to session '${args.session_id}' \u2014 it auto-delivers the moment the session goes idle. Use mesh_status or mesh_task_history to track it; no manual resend needed.`
7172
+ nextAction: `Task '${queuedTask.id}' is queued and pinned to session '${args.session_id}' \u2014 it auto-delivers the moment the session goes idle. Use mesh_status or mesh_task_history to track it; no manual resend needed.`,
7173
+ ...buildMissionInactiveWarning(ctx, missionId) ?? {}
7158
7174
  });
7159
7175
  }
7160
7176
  }
@@ -7274,7 +7290,8 @@ async function meshSendTask(ctx, args) {
7274
7290
  // DISPATCH-ACK-RISK-STALE: only warn on a GENUINE residual loss risk — an idle
7275
7291
  // session whose dispatch row did NOT survive pre-record. A successfully
7276
7292
  // pre-recorded idle dispatch (the NOTIF-DROP / CANON-A path) is not at risk.
7277
- ...computeIdleDispatchAckRisk(sessionWasIdle, dispatchPreRecorded, args.session_id)
7293
+ ...computeIdleDispatchAckRisk(sessionWasIdle, dispatchPreRecorded, args.session_id),
7294
+ ...buildMissionInactiveWarning(ctx, missionId) ?? {}
7278
7295
  });
7279
7296
  }
7280
7297
  const task = (0, import_daemon_core4.enqueueTask)(ctx.mesh.id, message, {
@@ -7295,7 +7312,8 @@ async function meshSendTask(ctx, args) {
7295
7312
  status: task.status,
7296
7313
  taskMode: task.taskMode,
7297
7314
  queueTrigger,
7298
- ...buildQueueTriggerGuidance(queueTrigger)
7315
+ ...buildQueueTriggerGuidance(queueTrigger),
7316
+ ...buildMissionInactiveWarning(ctx, missionId) ?? {}
7299
7317
  };
7300
7318
  if (pendingEvents.length > 0) {
7301
7319
  result.pendingCoordinatorEvents = pendingEvents;