@adhdev/daemon-core 1.0.21-rc.3 → 1.0.21-rc.5

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.
@@ -232,8 +232,18 @@ export interface CliProviderModule {
232
232
  requirePromptEchoBeforeSubmit?: boolean;
233
233
  /** Allow sending another prompt while the CLI is still generating so users can intervene mid-turn. */
234
234
  allowInputDuringGeneration?: boolean;
235
- /** When true, only transition to idle after the parsed transcript includes a final standard assistant message. */
235
+ /** When true, only transition to idle after the parsed transcript includes a final standard assistant message.
236
+ * Also selects the completion-timing FLOOR (mid-tool-valley-prone native source, e.g. codex/kimi/cursor/opencode):
237
+ * an idle-without-final-assistant holds the decoupled CANON-C completion under the min-elapsed floor. False = a
238
+ * write-lag native source (e.g. claude-cli) that emits immediately. See holdCompletionForTranscript for the
239
+ * third (hold) class. */
236
240
  requiresFinalAssistantBeforeIdle?: boolean;
241
+ /** Completion-timing HOLD class (e.g. antigravity-cli): a native-history provider whose live idle verdict is
242
+ * PTY-derived but whose authoritative answer lands in native history. When true, an idle-without-final-assistant
243
+ * HOLDS for the transcript to land (holdForTranscript) instead of emitting/flooring, and keeps holding past the
244
+ * 30s finalization cap while the PTY is still active (bounded by the hard cap). The third completion-timing class
245
+ * alongside immediate (requiresFinalAssistantBeforeIdle=false) and floor (requiresFinalAssistantBeforeIdle=true). */
246
+ holdCompletionForTranscript?: boolean;
237
247
  /** When true, allow providers to augment stale snapshot data before parse. Reserved for future use. */
238
248
  augmentStaleSnapshot?: boolean;
239
249
  /** When provider-owned, daemon treats provider parser output as canonical transcript authority. */
package/dist/index.js CHANGED
@@ -791,10 +791,10 @@ function readInjected(value) {
791
791
  }
792
792
  function getDaemonBuildInfo() {
793
793
  if (cached) return cached;
794
- const commit = readInjected(true ? "89c750927f379b7063a2d1481b08aa267e96f790" : void 0) ?? "unknown";
795
- const commitShort = readInjected(true ? "89c75092" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
796
- const version = readInjected(true ? "1.0.21-rc.3" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
797
- const builtAt = readInjected(true ? "2026-07-23T16:22:48.280Z" : void 0);
794
+ const commit = readInjected(true ? "57d6b342db3f9f235038696295dbc4761e227e3c" : void 0) ?? "unknown";
795
+ const commitShort = readInjected(true ? "57d6b342" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
796
+ const version = readInjected(true ? "1.0.21-rc.5" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
797
+ const builtAt = readInjected(true ? "2026-07-24T01:20:44.122Z" : void 0);
798
798
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
799
799
  return cached;
800
800
  }
@@ -16373,13 +16373,13 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
16373
16373
  });
16374
16374
  const workerResult = evidence.workerResult;
16375
16375
  const selfAttributing = workerResult.source === "final_summary_json";
16376
- const dispatchTime = dispatch?.timestamp ? new Date(dispatch.timestamp).getTime() : Number.NaN;
16376
+ const dispatchTime = dispatch?.timestamp ? new Date(dispatch.timestamp).getTime() : args.dispatchTimestamp ? new Date(args.dispatchTimestamp).getTime() : Number.NaN;
16377
16377
  const transcriptTime = args.transcriptMessageAt ? new Date(args.transcriptMessageAt).getTime() : Number.NaN;
16378
16378
  const transcriptAfterDispatch = Number.isFinite(dispatchTime) && Number.isFinite(transcriptTime) && transcriptTime >= dispatchTime;
16379
- if (workerResult.source !== "final_summary_json" && !transcriptAfterDispatch) {
16379
+ if (!args.preValidatedTranscriptEvidence && workerResult.source !== "final_summary_json" && !transcriptAfterDispatch) {
16380
16380
  return { reconciled: false, reason: "transcript_not_proven_after_dispatch" };
16381
16381
  }
16382
- if (Number.isFinite(dispatchTime) && workerResult.source !== "final_summary_json") {
16382
+ if (!args.preValidatedTranscriptEvidence && Number.isFinite(dispatchTime) && workerResult.source !== "final_summary_json") {
16383
16383
  const dispatchedToIdleSession = dispatch?.payload?.dispatchedToIdleSession === true;
16384
16384
  const graceMs = dispatchedToIdleSession ? DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS : DIRECT_DISPATCH_RECONCILE_GRACE_MS;
16385
16385
  if (Date.now() - dispatchTime < graceMs) {
@@ -24602,7 +24602,15 @@ async function pollAssignedTaskTerminalEvidence(components, mesh, row) {
24602
24602
  if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
24603
24603
  return null;
24604
24604
  }
24605
- return "completed";
24605
+ return {
24606
+ outcome: "completed",
24607
+ finalSummary: evidence.finalSummary,
24608
+ ...evidence.transcriptMessageAt ? { transcriptMessageAt: evidence.transcriptMessageAt } : {},
24609
+ ...readNonEmptyString(payload.providerSessionId) ? { providerSessionId: readNonEmptyString(payload.providerSessionId) } : {},
24610
+ ...providerType ? { providerType } : {},
24611
+ ...nodeId ? { nodeId } : {},
24612
+ sessionId
24613
+ };
24606
24614
  }
24607
24615
  var init_mesh_completion_synthesis = __esm({
24608
24616
  "src/mesh/mesh-completion-synthesis.ts"() {
@@ -24954,6 +24962,32 @@ async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, loca
24954
24962
  }
24955
24963
  return verdict === "UNKNOWN";
24956
24964
  }
24965
+ function propagateWatchdogTranscriptCompletion(meshId, row, evidence, source) {
24966
+ const sessionId = readNonEmptyString(row.assignedSessionId) || evidence.sessionId;
24967
+ if (!sessionId || !readNonEmptyString(evidence.finalSummary)) {
24968
+ return false;
24969
+ }
24970
+ try {
24971
+ const result = reconcileDirectDispatchCompletionFromTranscript({
24972
+ meshId,
24973
+ nodeId: readNonEmptyString(row.assignedNodeId) || evidence.nodeId,
24974
+ sessionId,
24975
+ providerType: readNonEmptyString(row.assignedProviderType) || evidence.providerType,
24976
+ providerSessionId: evidence.providerSessionId,
24977
+ taskId: row.id,
24978
+ finalSummary: evidence.finalSummary,
24979
+ ...evidence.transcriptMessageAt ? { transcriptMessageAt: evidence.transcriptMessageAt } : {},
24980
+ ...readNonEmptyString(row.dispatchTimestamp) ? { dispatchTimestamp: readNonEmptyString(row.dispatchTimestamp) } : {},
24981
+ // The watchdog poll already enforced idle + post-dispatch + no-trailing-tool + streak;
24982
+ // skip the reconcile's own grace/transcript_not_proven gates (dedup backstops remain).
24983
+ preValidatedTranscriptEvidence: true,
24984
+ source
24985
+ });
24986
+ return result.reconciled || result.alreadyTerminal === true;
24987
+ } catch {
24988
+ return false;
24989
+ }
24990
+ }
24957
24991
  async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
24958
24992
  const meshId = mesh.id;
24959
24993
  const assigned = getQueue(meshId, { status: ["assigned"] });
@@ -24984,11 +25018,17 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
24984
25018
  const terminalEvidence = await pollAssignedTaskTerminalEvidence(components, mesh, row);
24985
25019
  if (terminalEvidence) {
24986
25020
  assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
24987
- updateTaskStatus(meshId, row.id, terminalEvidence);
24988
- if (!findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
25021
+ updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
25022
+ const propagated = propagateWatchdogTranscriptCompletion(
25023
+ meshId,
25024
+ row,
25025
+ terminalEvidence,
25026
+ "early_idle_transcript_evidence"
25027
+ );
25028
+ if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
24989
25029
  try {
24990
25030
  appendLedgerEntry(meshId, {
24991
- kind: terminalEvidence === "completed" ? "task_completed" : "task_failed",
25031
+ kind: terminalEvidence.outcome === "completed" ? "task_completed" : "task_failed",
24992
25032
  nodeId: row.assignedNodeId,
24993
25033
  sessionId: row.assignedSessionId,
24994
25034
  providerType: row.assignedProviderType,
@@ -25001,14 +25041,14 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
25001
25041
  } catch {
25002
25042
  }
25003
25043
  }
25004
- LOG.warn("MeshReconcile", `Early-completed assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): worker idle with a final assistant message after dispatch for \u2265${Math.round(ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS / 1e3)}s \u2014 the completion event was lost/late (pure-PTY provider), task is ${terminalEvidence} without waiting the 15-min deadline`);
25005
- traceMeshEventDrop("assigned_early_transcript_completed", {
25044
+ LOG.warn("MeshReconcile", `Early-completed assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): worker idle with a final assistant message after dispatch for \u2265${Math.round(ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS / 1e3)}s \u2014 the completion event was lost/late (pure-PTY provider), task is ${terminalEvidence.outcome} without waiting the 15-min deadline${propagated ? " (finalSummary propagated to coordinator)" : ""}`);
25045
+ traceMeshEventStage("assigned_early_transcript_completed", {
25006
25046
  taskId: row.id,
25007
25047
  sessionId: row.assignedSessionId,
25008
25048
  nodeId: row.assignedNodeId,
25009
25049
  meshId,
25010
25050
  event: "agent:generating_completed"
25011
- }, terminalEvidence);
25051
+ }, propagated ? "propagated" : terminalEvidence.outcome);
25012
25052
  continue;
25013
25053
  }
25014
25054
  assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
@@ -25146,11 +25186,17 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
25146
25186
  const terminalEvidence = await pollAssignedTaskTerminalEvidence(components, mesh, row);
25147
25187
  if (terminalEvidence) {
25148
25188
  deliveredNoTurnUnknownStreak.delete(streakKey);
25149
- updateTaskStatus(meshId, row.id, terminalEvidence);
25150
- if (!findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
25189
+ updateTaskStatus(meshId, row.id, terminalEvidence.outcome);
25190
+ const propagated = propagateWatchdogTranscriptCompletion(
25191
+ meshId,
25192
+ row,
25193
+ terminalEvidence,
25194
+ "redrive_deadline_transcript_evidence"
25195
+ );
25196
+ if (!propagated && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
25151
25197
  try {
25152
25198
  appendLedgerEntry(meshId, {
25153
- kind: terminalEvidence === "completed" ? "task_completed" : "task_failed",
25199
+ kind: terminalEvidence.outcome === "completed" ? "task_completed" : "task_failed",
25154
25200
  nodeId: row.assignedNodeId,
25155
25201
  sessionId: row.assignedSessionId,
25156
25202
  providerType: row.assignedProviderType,
@@ -25163,14 +25209,14 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
25163
25209
  } catch {
25164
25210
  }
25165
25211
  }
25166
- LOG.warn("MeshReconcile", `Skipped delivered-no-turn re-drive for task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): worker transcript is idle with a final assistant message after dispatch \u2014 the completion event was lost/late, task is ${terminalEvidence}, NOT re-driving`);
25167
- traceMeshEventDrop("redrive_deadline_transcript_completed", {
25212
+ LOG.warn("MeshReconcile", `Skipped delivered-no-turn re-drive for task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): worker transcript is idle with a final assistant message after dispatch \u2014 the completion event was lost/late, task is ${terminalEvidence.outcome}, NOT re-driving${propagated ? " (finalSummary propagated to coordinator)" : ""}`);
25213
+ traceMeshEventStage("redrive_deadline_transcript_completed", {
25168
25214
  taskId: row.id,
25169
25215
  sessionId: row.assignedSessionId,
25170
25216
  nodeId: row.assignedNodeId,
25171
25217
  meshId,
25172
25218
  event: "agent:generating_completed"
25173
- }, `${reclaimReason} \u2192 transcript ${terminalEvidence}`);
25219
+ }, `${reclaimReason} \u2192 transcript ${terminalEvidence.outcome}${propagated ? " propagated" : ""}`);
25174
25220
  continue;
25175
25221
  }
25176
25222
  const reclaimedLost = reclaimStrandedAssignedTask(meshId, row.id, {
@@ -26084,7 +26130,12 @@ var init_provider_schema = __esm({
26084
26130
  requiresFinalAssistantBeforeIdle: {
26085
26131
  type: "boolean",
26086
26132
  default: false,
26087
- description: "When true, daemon defers generating\u2192idle until parseSession includes a final standard assistant message."
26133
+ description: "When true, daemon defers generating\u2192idle until parseSession includes a final standard assistant message. Also selects the completion-timing floor for a native-source provider: an idle without a final assistant reply is treated as a possible mid-tool-call quiet valley, so the decoupled CANON-C completion is held under the min-elapsed floor (noExternalTranscriptSource) rather than emitted immediately. A provider that leaves this false is a write-lag native source (e.g. claude-cli) whose transcript merely trails the finished idle by a write, so it emits immediately."
26134
+ },
26135
+ holdCompletionForTranscript: {
26136
+ type: "boolean",
26137
+ default: false,
26138
+ description: "Completion-timing authority for a native-history provider whose live idle verdict is PTY-derived but whose authoritative answer lands in native history (e.g. antigravity-cli). When true, an idle-without-final-assistant HOLDS for the native transcript to land (holdForTranscript) instead of emitting or applying the min-elapsed floor, and the hold persists past the 30s finalization cap while the PTY is still active (bounded by the hard cap). This is the third completion-timing class alongside immediate (requiresFinalAssistantBeforeIdle=false) and floor (requiresFinalAssistantBeforeIdle=true)."
26088
26139
  },
26089
26140
  augmentStaleSnapshot: {
26090
26141
  type: "boolean",
@@ -51307,7 +51358,7 @@ var CliProviderInstance = class _CliProviderInstance {
51307
51358
  if (probe?.lastRole === "assistant" && (probe.contentLen ?? 0) > 0) {
51308
51359
  return null;
51309
51360
  }
51310
- if (this.type === "antigravity-cli") {
51361
+ if (this.provider?.holdCompletionForTranscript === true) {
51311
51362
  if (allowMissingAssistantTimeout) {
51312
51363
  return { reason: "missing_final_assistant", terminal: false, holdForTranscript: true };
51313
51364
  }
@@ -51316,10 +51367,16 @@ var CliProviderInstance = class _CliProviderInstance {
51316
51367
  if (allowMissingAssistantTimeout && pending.previousStatus === "waiting_approval") {
51317
51368
  return { reason: "missing_final_assistant", terminal: false, holdForTranscript: true };
51318
51369
  }
51319
- return { reason: "missing_final_assistant", terminal: true, allowTimeout: allowMissingAssistantTimeout };
51370
+ const isWriteLagNativeSource = this.provider.requiresFinalAssistantBeforeIdle !== true;
51371
+ return {
51372
+ reason: "missing_final_assistant",
51373
+ terminal: true,
51374
+ allowTimeout: allowMissingAssistantTimeout,
51375
+ ...isWriteLagNativeSource ? {} : { noExternalTranscriptSource: true }
51376
+ };
51320
51377
  }
51321
51378
  if (this.provider.requiresFinalAssistantBeforeIdle === true) {
51322
- return { reason: "missing_final_assistant", terminal: true, allowTimeout: allowMissingAssistantTimeout };
51379
+ return { reason: "missing_final_assistant", terminal: true, allowTimeout: allowMissingAssistantTimeout, noExternalTranscriptSource: true };
51323
51380
  }
51324
51381
  } else {
51325
51382
  LOG.debug("CLI", `[${this.type}] missing_final_assistant (not ownsExternal) requiresFinalAssistant=${!!this.provider.requiresFinalAssistantBeforeIdle}`);
@@ -52095,7 +52152,7 @@ var CliProviderInstance = class _CliProviderInstance {
52095
52152
  this.scheduleCompletedDebounceFlush(COMPLETED_FINALIZATION_RETRY_MS);
52096
52153
  return;
52097
52154
  }
52098
- if (this.type === "antigravity-cli" && block2.holdForTranscript === true && waitedMs < ANTIGRAVITY_HOLD_HARD_CAP_MS && this.antigravityHoldPtyStillActive()) {
52155
+ if (this.provider?.holdCompletionForTranscript === true && block2.holdForTranscript === true && waitedMs < ANTIGRAVITY_HOLD_HARD_CAP_MS && this.antigravityHoldPtyStillActive()) {
52099
52156
  if (pending.loggedBlockReason !== "antigravity_hold_pty_active") {
52100
52157
  LOG.info("CLI", `[${this.type}] 30s cap reached but PTY still generating; holding antigravity completion past cap (waitedMs=${waitedMs} hardCap=${ANTIGRAVITY_HOLD_HARD_CAP_MS}) (${blockReason})`);
52101
52158
  if (this.isMeshWorkerSession()) {
@@ -56233,6 +56290,7 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
56233
56290
  "submitStrategy",
56234
56291
  "requirePromptEchoBeforeSubmit",
56235
56292
  "requiresFinalAssistantBeforeIdle",
56293
+ "holdCompletionForTranscript",
56236
56294
  "augmentStaleSnapshot",
56237
56295
  "timeouts",
56238
56296
  "disableUpstream"