@adhdev/daemon-core 0.9.82-rc.479 → 0.9.82-rc.480

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.
@@ -154,6 +154,26 @@ export declare class CliStateEngine {
154
154
  clearAllTimers(): void;
155
155
  resetActiveTurnState(): void;
156
156
  clearIdleFinishCandidate(reason: string): void;
157
+ /**
158
+ * Poll-driven static-idle confirm (D4). A hosted CLI session (e.g. a fresh
159
+ * antigravity coordinator) whose boot banner drove the FSM into 'generating'
160
+ * can then sit at a STATIC ready prompt emitting no further PTY output. Every
161
+ * output-driven busy→idle re-eval (handleOutput/resolveStartupState/settle)
162
+ * is starved because there is no new output, and the startup-settle loop has
163
+ * hard-stopped past spawnAt+10s — so currentStatus stays frozen at generating
164
+ * and the dashboard disables Send. This is the ONE path that can release that
165
+ * wedge from the read-only status poll.
166
+ *
167
+ * Safety: this must NEVER flip a real generating turn to idle. The gate is
168
+ * done by the caller (getStatus) reusing resolveStartupState's proven
169
+ * predicates: no recent PTY output for a grace window, runDetectStatus of the
170
+ * current screen === 'idle', and no active/parsed modal. Here we add the
171
+ * final structural guard: there must be NO active turn scope. A live user
172
+ * turn always carries a currentTurnScope (set in onTurnStarted), so this only
173
+ * releases the boot-banner wedge and the post-turn static-idle case, both of
174
+ * which have already had their scope nulled. Returns true when it transitioned.
175
+ */
176
+ confirmPollStaticIdle(reason: string): boolean;
157
177
  hasActionableApproval(startupModal?: {
158
178
  message: string;
159
179
  buttons: string[];
@@ -11,5 +11,13 @@ import type { CommandResult, CommandHelpers } from './handler.js';
11
11
  * worker. Not part of the runtime contract.
12
12
  */
13
13
  export declare function __resetProviderSessionPinsForTest(): void;
14
+ /**
15
+ * Test-only: read the in-memory read-pin (the mesh-session → conversation-uuid
16
+ * bind recorded by recordBoundProviderSessionId and mirrored to state.json
17
+ * sessionProviderSessionPins). Lets the antigravity-coordinator-pin tests assert
18
+ * that an owner-confirmed workspace-latest read recorded the pin — and that a
19
+ * non-owner-confirmed read did NOT. Not part of the runtime contract.
20
+ */
21
+ export declare function __getProviderSessionPinForTest(meshSessionId: string): string | undefined;
14
22
  export declare function handleChatHistory(h: CommandHelpers, args: any): Promise<CommandResult>;
15
23
  export declare function handleReadChat(h: CommandHelpers, args: any): Promise<CommandResult>;
@@ -10,5 +10,5 @@
10
10
  export { READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, buildSendInputSignature } from './chat-commands-shared.js';
11
11
  export { evaluateReadChatNodeWorkspaceScope } from './chat-commands-scope.js';
12
12
  export { sanitizeDebugBundleValue, handleGetChatDebugBundle } from './chat-commands-debug-bundle.js';
13
- export { handleChatHistory, handleReadChat, __resetProviderSessionPinsForTest } from './chat-commands-read.js';
13
+ export { handleChatHistory, handleReadChat, __resetProviderSessionPinsForTest, __getProviderSessionPinForTest } from './chat-commands-read.js';
14
14
  export { handleSendChat, handleListChats, handleNewChat, handleSwitchChat, handleSetMode, handleChangeModel, handleSetThoughtLevel, handleResolveAction, } from './chat-commands-write.js';
@@ -61,6 +61,14 @@ export interface HostedCliRuntimeDescriptor {
61
61
  cliArgs?: string[];
62
62
  providerSessionId?: string;
63
63
  managedBy?: string;
64
+ /**
65
+ * Real spawn time (ms epoch) of the underlying session-host runtime — a PAST
66
+ * timestamp recorded when the runtime first started. Threaded through so an
67
+ * attach can restore the native-history session-floor to the runtime's actual
68
+ * birth instead of collapsing spawnedAtMs to 0. Undefined when unrecoverable
69
+ * (genuine post-restart-unknown), in which case the caller keeps the 0 fallback.
70
+ */
71
+ startedAtMs?: number;
64
72
  }
65
73
  type CliLaunchMode = 'new' | 'resume' | 'manual';
66
74
  type CliSessionBinding = {
@@ -84,6 +92,24 @@ export interface CoordinatorDelegatedCliLaunchOptions {
84
92
  cliArgs: string[];
85
93
  env: Record<string, string>;
86
94
  }
95
+ /**
96
+ * Decide the session-registry spawnedAtMs (the native-history session-floor) for a
97
+ * newly registered CLI instance.
98
+ *
99
+ * - Fresh launch (attachExisting=false): now (nowMs). A real live spawn floor
100
+ * isolates a fresh session's own store and holds prior-session leak protection.
101
+ * - Attach WITH a recoverable record startedAt (a PAST timestamp): that startedAt.
102
+ * Restoring a hosted runtime (coordinator / MAGI replica / hermes / claude /
103
+ * codex) after a daemon restart, the real spawn time is in the past. Using it
104
+ * restores each session's per-session birth-floor so co-located antigravity
105
+ * runtimes resolve their OWN conversation (ownerConfirmed) instead of the
106
+ * floor-less newest-by-mtime path that let a replica claim the coordinator's conv.
107
+ * - Attach with NO recoverable startedAt: 0 — disables the floor for this session
108
+ * (recent_window_ms still bounds the look-back). NEVER use nowMs here: nowMs is in
109
+ * the FUTURE relative to existing transcripts and would push the floor past every
110
+ * transcript file, losing them (the ANTIGRAVITY-FINAL-MESSAGE-TAIL-GAP regression).
111
+ */
112
+ export declare function resolveHostedSpawnedAtMs(attachExisting: boolean, attachStartedAtMs: number | undefined, nowMs: number): number;
87
113
  export declare function buildCoordinatorDelegatedCliLaunchOptions(input: CoordinatorDelegatedCliLaunchOptionsInput): CoordinatorDelegatedCliLaunchOptions;
88
114
  export declare function supportsExplicitSessionResume(resume?: ProviderResumeCapability): boolean;
89
115
  export declare function resolveCliSessionBinding(provider: ProviderModule | undefined, normalizedType: string, cliArgs?: string[], requestedResumeSessionId?: string): CliSessionBinding;
@@ -126,6 +126,7 @@ export declare function readProviderChatHistory(agentType: string, options?: {
126
126
  nativeHistoryCoverage?: string;
127
127
  partialReason?: string;
128
128
  unavailableReason?: string;
129
+ ownerConfirmed?: boolean;
129
130
  };
130
131
  export declare function listProviderHistorySessions(agentType: string, options?: {
131
132
  canonicalHistory?: ProviderCanonicalHistoryConfig;
package/dist/index.d.ts CHANGED
@@ -85,7 +85,7 @@ export type { IDEInfo } from './detection/ide-detector.js';
85
85
  export { detectCLIs } from './detection/cli-detector.js';
86
86
  export { getHostMemorySnapshot } from './system/host-memory.js';
87
87
  export type { HostMemorySnapshot } from './system/host-memory.js';
88
- export { classifyHotChatSessionsForSubscriptionFlush, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, } from './status/chat-tail-hot-sessions.js';
88
+ export { classifyHotChatSessionsForSubscriptionFlush, detectNewlySettledCompletedSessions, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, } from './status/chat-tail-hot-sessions.js';
89
89
  export { DaemonCdpManager } from './cdp/manager.js';
90
90
  export { CdpDomHandlers } from './cdp/devtools.js';
91
91
  export { setupIdeInstance, registerExtensionProviders, connectCdpManager, probeCdpPort } from './cdp/setup.js';
package/dist/index.js CHANGED
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "6d7bacdddb31d77f5aa1c900d667702ab9acb472" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "6d7bacdd" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.479" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-06T19:58:17.279Z" : void 0);
412
+ const commit = readInjected(true ? "27de51660cbce2ce37049081744c09a168420b2f" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "27de5166" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.480" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-07T16:21:33.035Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -24257,6 +24257,41 @@ var init_cli_state_engine = __esm({
24257
24257
  this.recordTrace("idle_candidate_reset", { reason, candidate: this.idleFinishCandidate });
24258
24258
  this.idleFinishCandidate = null;
24259
24259
  }
24260
+ /**
24261
+ * Poll-driven static-idle confirm (D4). A hosted CLI session (e.g. a fresh
24262
+ * antigravity coordinator) whose boot banner drove the FSM into 'generating'
24263
+ * can then sit at a STATIC ready prompt emitting no further PTY output. Every
24264
+ * output-driven busy→idle re-eval (handleOutput/resolveStartupState/settle)
24265
+ * is starved because there is no new output, and the startup-settle loop has
24266
+ * hard-stopped past spawnAt+10s — so currentStatus stays frozen at generating
24267
+ * and the dashboard disables Send. This is the ONE path that can release that
24268
+ * wedge from the read-only status poll.
24269
+ *
24270
+ * Safety: this must NEVER flip a real generating turn to idle. The gate is
24271
+ * done by the caller (getStatus) reusing resolveStartupState's proven
24272
+ * predicates: no recent PTY output for a grace window, runDetectStatus of the
24273
+ * current screen === 'idle', and no active/parsed modal. Here we add the
24274
+ * final structural guard: there must be NO active turn scope. A live user
24275
+ * turn always carries a currentTurnScope (set in onTurnStarted), so this only
24276
+ * releases the boot-banner wedge and the post-turn static-idle case, both of
24277
+ * which have already had their scope nulled. Returns true when it transitioned.
24278
+ */
24279
+ confirmPollStaticIdle(reason) {
24280
+ if (this.currentStatus !== "generating") return false;
24281
+ if (this.currentTurnScope || this.activeModal) return false;
24282
+ this.clearAllTimers();
24283
+ this.clearIdleFinishCandidate(reason);
24284
+ this.isWaitingForResponse = false;
24285
+ this.responseSettleIgnoreUntil = 0;
24286
+ this.submitRetryUsed = false;
24287
+ this.submitRetryPromptSnippet = "";
24288
+ this.finishRetryCount = 0;
24289
+ this.currentTurnScope = null;
24290
+ this.activeModal = null;
24291
+ this.setStatus("idle", reason);
24292
+ this.recordTrace("poll_static_idle_confirmed", { reason });
24293
+ return true;
24294
+ }
24260
24295
  hasActionableApproval(startupModal) {
24261
24296
  return !!(startupModal ?? this.activeModal);
24262
24297
  }
@@ -25697,6 +25732,18 @@ ${lastSnapshot}`;
25697
25732
  const allowParse = options.allowParse !== false;
25698
25733
  const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
25699
25734
  const startupDetectedStatus = allowParse && this.startupParseGate && !startupModal ? this.runDetectStatus(this.recentOutputBuffer || this.terminalScreen.getText()) : null;
25735
+ if (allowParse && this.engine.currentStatus === "generating" && !this.engine.currentTurnScope && !this.engine.activeModal) {
25736
+ const now = Date.now();
25737
+ const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
25738
+ if (quietForMs >= this.getStatusActivityHoldMs()) {
25739
+ const screenText = this.terminalScreen.getText();
25740
+ const pollDetect = this.runDetectStatus(screenText || this.recentOutputBuffer);
25741
+ const pollModal = this.runParseApproval(screenText) || this.runParseApproval(this.recentOutputBuffer);
25742
+ if (pollDetect === "idle" && !pollModal) {
25743
+ this.engine.confirmPollStaticIdle("poll_static_idle");
25744
+ }
25745
+ }
25746
+ }
25700
25747
  let effectiveStatus = this.projectEffectiveStatus(startupModal);
25701
25748
  let effectiveModal = startupModal || this.engine.activeModal;
25702
25749
  if (allowParse && !effectiveModal && this.engine.isWaitingForResponse) {
@@ -27321,6 +27368,7 @@ __export(index_exports, {
27321
27368
  detectCLIs: () => detectCLIs,
27322
27369
  detectClaudeAskUserQuestionPromptFromJson: () => detectClaudeAskUserQuestionPromptFromJson,
27323
27370
  detectIDEs: () => detectIDEs,
27371
+ detectNewlySettledCompletedSessions: () => detectNewlySettledCompletedSessions,
27324
27372
  drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
27325
27373
  enqueueTask: () => enqueueTask,
27326
27374
  ensureSessionHostReady: () => ensureSessionHostReady,
@@ -29267,8 +29315,11 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
29267
29315
  );
29268
29316
  const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
29269
29317
  const activeSessionIds = options.activeSessionIds ?? /* @__PURE__ */ new Set();
29318
+ const deliveredCompletionTailAt = options.deliveredCompletionTailAt ?? null;
29319
+ const underDeliveredSessionIds = options.underDeliveredSessionIds ?? null;
29270
29320
  const active = /* @__PURE__ */ new Set();
29271
29321
  const excluded = /* @__PURE__ */ new Set();
29322
+ const guaranteedDelivery = /* @__PURE__ */ new Set();
29272
29323
  for (const session of sessions) {
29273
29324
  const sessionId = typeof session?.id === "string" ? session.id : "";
29274
29325
  if (!sessionId) continue;
@@ -29291,12 +29342,47 @@ function classifyHotChatSessionsForSubscriptionFlush(sessions, previousHotSessio
29291
29342
  const shouldKeepRecentTailHot = recentlyUpdated && (unread || inboxBucket === "task_complete" || inboxBucket === "needs_attention" || isLiveRuntime || activeStatuses.has(status));
29292
29343
  if (activeStatuses.has(status) || shouldKeepRecentTailHot) {
29293
29344
  active.add(sessionId);
29345
+ continue;
29346
+ }
29347
+ if (underDeliveredSessionIds && underDeliveredSessionIds.has(sessionId)) {
29348
+ active.add(sessionId);
29349
+ guaranteedDelivery.add(sessionId);
29350
+ continue;
29351
+ }
29352
+ const completedUnseen = unread || inboxBucket === "task_complete";
29353
+ if (!underDeliveredSessionIds && deliveredCompletionTailAt && completedUnseen) {
29354
+ const delivered = deliveredCompletionTailAt.get(sessionId) ?? 0;
29355
+ const alreadyDelivered = delivered > 0 && lastMessageAt > 0 && delivered >= lastMessageAt;
29356
+ if (!alreadyDelivered) {
29357
+ active.add(sessionId);
29358
+ guaranteedDelivery.add(sessionId);
29359
+ }
29294
29360
  }
29295
29361
  }
29296
29362
  const finalizing = new Set(
29297
29363
  Array.from(previousHotSessionIds).filter((sessionId) => !active.has(sessionId) && !excluded.has(sessionId))
29298
29364
  );
29299
- return { active, finalizing };
29365
+ return { active, finalizing, guaranteedDelivery };
29366
+ }
29367
+ function detectNewlySettledCompletedSessions(sessions, previousStatus, options = {}) {
29368
+ const activeStatuses = options.activeStatuses ?? DEFAULT_ACTIVE_CHAT_POLL_STATUSES;
29369
+ const settled = /* @__PURE__ */ new Set();
29370
+ const nextStatus = /* @__PURE__ */ new Map();
29371
+ for (const session of sessions) {
29372
+ const sessionId = typeof session?.id === "string" ? session.id : "";
29373
+ if (!sessionId) continue;
29374
+ const status = String(session?.status || "").toLowerCase();
29375
+ const prevStatus = previousStatus.get(sessionId);
29376
+ nextStatus.set(sessionId, status);
29377
+ const wasActive = prevStatus !== void 0 && activeStatuses.has(prevStatus);
29378
+ const isSettledNow = !activeStatuses.has(status);
29379
+ const inboxBucket = String(session?.inboxBucket || "").toLowerCase();
29380
+ const completedUnseen = session?.unread === true || inboxBucket === "task_complete";
29381
+ if (wasActive && isSettledNow && completedUnseen) {
29382
+ settled.add(sessionId);
29383
+ }
29384
+ }
29385
+ return { settled, nextStatus };
29300
29386
  }
29301
29387
 
29302
29388
  // src/cdp/manager.ts
@@ -32113,7 +32199,8 @@ function callProviderNativeHistoryRead(agentType, canonicalHistory, scripts, his
32113
32199
  workspace: typeof result.workspace === "string" ? result.workspace.trim() : void 0,
32114
32200
  nativeHistoryCoverage: typeof result.nativeHistoryCoverage === "string" ? result.nativeHistoryCoverage.trim() : void 0,
32115
32201
  partialReason: typeof result.partialReason === "string" ? result.partialReason.trim() : void 0,
32116
- unavailableReason: typeof result.unavailableReason === "string" ? result.unavailableReason.trim() : void 0
32202
+ unavailableReason: typeof result.unavailableReason === "string" ? result.unavailableReason.trim() : void 0,
32203
+ ownerConfirmed: typeof result.ownerConfirmed === "boolean" ? result.ownerConfirmed : void 0
32117
32204
  };
32118
32205
  }
32119
32206
  function buildNativeHistoryReadResult(agentType, canonicalHistory, scripts, historySessionId, workspace, excludeInProgressTurn, sessionStartedAtMs, envOverrides, forceRefresh, instanceId) {
@@ -32160,7 +32247,8 @@ function readProviderChatHistory(agentType, options = {}) {
32160
32247
  workspace: nativeResult.workspace,
32161
32248
  nativeHistoryCoverage: nativeResult.nativeHistoryCoverage,
32162
32249
  partialReason: nativeResult.partialReason,
32163
- unavailableReason: nativeResult.unavailableReason
32250
+ unavailableReason: nativeResult.unavailableReason,
32251
+ ownerConfirmed: nativeResult.ownerConfirmed
32164
32252
  };
32165
32253
  }
32166
32254
  return {
@@ -34525,6 +34613,12 @@ function getExplicitHistorySessionId(args) {
34525
34613
  if (explicitProviderSessionId) return explicitProviderSessionId;
34526
34614
  return void 0;
34527
34615
  }
34616
+ function isRuntimeFallbackHistorySessionId(candidateHistorySessionId, targetSessionId) {
34617
+ const target = typeof targetSessionId === "string" ? targetSessionId.trim() : "";
34618
+ if (!target) return false;
34619
+ const candidate = typeof candidateHistorySessionId === "string" ? candidateHistorySessionId.trim() : "";
34620
+ return candidate === target;
34621
+ }
34528
34622
  function getHistorySessionId(h, args) {
34529
34623
  const explicit = getExplicitHistorySessionId(args);
34530
34624
  if (explicit) return explicit;
@@ -35359,12 +35453,19 @@ async function handleChatHistory(h, args) {
35359
35453
  if (visibleCount > excludeRecentCount) excludeRecentCount = visibleCount;
35360
35454
  }
35361
35455
  const workspace = typeof args?.workspace === "string" ? args.workspace : typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
35456
+ const targetSidForHistory = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
35457
+ const explicitHistorySessionIdForHistory = getExplicitHistorySessionId(args);
35458
+ const historySessionIdIsRuntimeFallback = Boolean(
35459
+ targetSidForHistory && isRuntimeFallbackHistorySessionId(historySessionId, targetSidForHistory) && (!explicitHistorySessionIdForHistory || isRuntimeFallbackHistorySessionId(explicitHistorySessionIdForHistory, targetSidForHistory))
35460
+ );
35461
+ const pinnedProviderSessionIdForHistory = getBoundProviderSessionIdPin(args?.targetSessionId);
35462
+ const effectiveHistorySessionId = historySessionIdIsRuntimeFallback ? pinnedProviderSessionIdForHistory || void 0 : historySessionId;
35362
35463
  const exactNativeHistoryScope = Boolean(
35363
- typeof args?.targetSessionId === "string" && args.targetSessionId.trim() || typeof args?.historySessionId === "string" && args.historySessionId.trim() || typeof args?.providerSessionId === "string" && args.providerSessionId.trim()
35464
+ typeof args?.targetSessionId === "string" && args.targetSessionId.trim() || typeof args?.historySessionId === "string" && args.historySessionId.trim() && !historySessionIdIsRuntimeFallback || typeof args?.providerSessionId === "string" && args.providerSessionId.trim()
35364
35465
  );
35365
35466
  const result = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory) ? readCliProviderNativeHistory(agentStr, {
35366
35467
  canonicalHistory: provider?.nativeHistory,
35367
- historySessionId,
35468
+ historySessionId: effectiveHistorySessionId,
35368
35469
  workspace,
35369
35470
  offset: offset || 0,
35370
35471
  limit: limit || 30,
@@ -35374,7 +35475,8 @@ async function handleChatHistory(h, args) {
35374
35475
  sessionStartedAtMs: sessionStartedAtMsFromRegistry(h, args?.targetSessionId),
35375
35476
  envOverrides: sessionSpawnEnvFromAdapter(h, args?.targetSessionId),
35376
35477
  instanceId: effectiveReadSessionId(h, args?.targetSessionId) || void 0,
35377
- pinnedProviderSessionId: getBoundProviderSessionIdPin(args?.targetSessionId)
35478
+ pinnedProviderSessionId: pinnedProviderSessionIdForHistory,
35479
+ allowWorkspaceLatestFallback: !pinnedProviderSessionIdForHistory && historySessionIdIsRuntimeFallback
35378
35480
  }) : readProviderChatHistory(agentStr, {
35379
35481
  canonicalHistory: provider?.nativeHistory,
35380
35482
  historySessionId,
@@ -35388,13 +35490,17 @@ async function handleChatHistory(h, args) {
35388
35490
  if (supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory)) {
35389
35491
  const lookup = result.lookup === "workspace" ? "workspace" : "session";
35390
35492
  const messages = Array.isArray(result.messages) ? normalizeAndFilterNativeHistory(h, agentStr, args, result.messages, result?.providerSessionId) : [];
35391
- const historyProviderSessionId = typeof result?.providerSessionId === "string" ? result.providerSessionId : readHistorySessionIdFromMessages(messages) || historySessionId;
35392
- if (typeof result?.providerSessionId === "string" && result.providerSessionId.trim()) {
35393
- recordBoundProviderSessionId(h, effectiveReadSessionId(h, args?.targetSessionId), result.providerSessionId.trim());
35493
+ const historyProviderSessionId = typeof result?.providerSessionId === "string" ? result.providerSessionId : readHistorySessionIdFromMessages(messages) || effectiveHistorySessionId;
35494
+ const resolvedProviderSessionId = typeof result?.providerSessionId === "string" ? result.providerSessionId.trim() : "";
35495
+ const resultLookupIsWorkspace = lookup === "workspace";
35496
+ const resultOwnerConfirmed = result?.ownerConfirmed === true;
35497
+ const ownerConfirmedUuid = resultOwnerConfirmed && typeof historyProviderSessionId === "string" && historyProviderSessionId.trim() ? historyProviderSessionId.trim() : "";
35498
+ if (resolvedProviderSessionId && (!resultLookupIsWorkspace || resultOwnerConfirmed)) {
35499
+ recordBoundProviderSessionId(h, effectiveReadSessionId(h, args?.targetSessionId), resolvedProviderSessionId);
35394
35500
  }
35395
35501
  const safeMapping = hasSafeNativeHistoryMapping({
35396
- historySessionId: lookup === "workspace" ? void 0 : historySessionId,
35397
- providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId,
35502
+ historySessionId: ownerConfirmedUuid || (lookup === "workspace" ? void 0 : effectiveHistorySessionId),
35503
+ providerSessionId: ownerConfirmedUuid || (lookup === "workspace" ? void 0 : historyProviderSessionId),
35398
35504
  workspace,
35399
35505
  nativeMessages: messages
35400
35506
  });
@@ -35515,8 +35621,9 @@ async function handleReadChat(h, args) {
35515
35621
  let nativeHistoryError;
35516
35622
  if (supportsNative) {
35517
35623
  const pinnedProviderSessionIdForRead = getBoundProviderSessionIdPin(targetSessionId);
35624
+ const explicitHistorySessionIdForRead = getExplicitHistorySessionId(args);
35518
35625
  const nativeReadSessionIdIsRuntimeFallback = Boolean(
35519
- targetSessionId && nativeHistoryReadSessionId === targetSessionId && !getExplicitHistorySessionId(args)
35626
+ targetSessionId && isRuntimeFallbackHistorySessionId(nativeHistoryReadSessionId, targetSessionId) && (!explicitHistorySessionIdForRead || isRuntimeFallbackHistorySessionId(explicitHistorySessionIdForRead, targetSessionId))
35520
35627
  );
35521
35628
  const effectiveNativeReadSessionId = nativeReadSessionIdIsRuntimeFallback ? pinnedProviderSessionIdForRead || void 0 : nativeHistoryReadSessionId;
35522
35629
  try {
@@ -35542,7 +35649,10 @@ async function handleReadChat(h, args) {
35542
35649
  allowWorkspaceLatestFallback: !pinnedProviderSessionIdForRead
35543
35650
  });
35544
35651
  const resolvedProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId.trim() : "";
35545
- if (resolvedProviderSessionId) {
35652
+ const resolvedLookupIsWorkspace = nativeHistory?.lookup === "workspace";
35653
+ const nativeOwnerConfirmed = nativeHistory?.ownerConfirmed === true;
35654
+ const mayPinResolvedProviderSessionId = resolvedProviderSessionId && (!resolvedLookupIsWorkspace || nativeOwnerConfirmed);
35655
+ if (mayPinResolvedProviderSessionId) {
35546
35656
  recordBoundProviderSessionId(h, effectiveReadSessionId(h, targetSessionId), resolvedProviderSessionId);
35547
35657
  }
35548
35658
  } catch (error) {
@@ -35554,14 +35664,15 @@ async function handleReadChat(h, args) {
35554
35664
  const sessionStartedAtMs = sessionStartedAtMsFromRegistry(h, args?.targetSessionId);
35555
35665
  let historyProviderSessionId = typeof nativeHistory?.providerSessionId === "string" ? nativeHistory.providerSessionId : readHistorySessionIdFromMessages(nativeMessages) || nativeHistoryReadSessionId || historySessionId;
35556
35666
  let lookup = nativeHistory?.lookup === "workspace" ? "workspace" : "session";
35557
- let nativeHistorySessionForMapping = adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistoryReadSessionId && historyProviderSessionId !== nativeHistoryReadSessionId ? void 0 : nativeHistoryReadSessionId;
35667
+ const ownerConfirmedUuid = adapter.cliType === "antigravity-cli" && nativeHistory?.ownerConfirmed === true && typeof historyProviderSessionId === "string" && historyProviderSessionId.trim() ? historyProviderSessionId.trim() : "";
35668
+ let nativeHistorySessionForMapping = ownerConfirmedUuid ? ownerConfirmedUuid : adapter.cliType === "antigravity-cli" && historyProviderSessionId && nativeHistoryReadSessionId && historyProviderSessionId !== nativeHistoryReadSessionId ? void 0 : nativeHistoryReadSessionId;
35558
35669
  let safeMapping = supportsNative && nativeHistory ? hasSafeNativeHistoryMapping({
35559
- historySessionId: lookup === "workspace" ? void 0 : nativeHistorySessionForMapping,
35560
- providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId,
35670
+ historySessionId: ownerConfirmedUuid || (lookup === "workspace" ? void 0 : nativeHistorySessionForMapping),
35671
+ providerSessionId: ownerConfirmedUuid || (lookup === "workspace" ? void 0 : historyProviderSessionId || providerSessionId),
35561
35672
  workspace,
35562
35673
  nativeMessages,
35563
35674
  ptyMessages: returnedMessages,
35564
- requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope
35675
+ requireWorkspaceContentOverlap: lookup === "workspace" && !exactNativeHistoryScope && !ownerConfirmedUuid
35565
35676
  }) : false;
35566
35677
  if (skipLiveNativeHistoryWithoutProviderSession && (!safeMapping || returnedMessages.length === 0)) {
35567
35678
  nativeHistory = null;
@@ -35792,8 +35903,9 @@ async function handleReadChat(h, args) {
35792
35903
  const intendedWorkspace = argsWorkspace;
35793
35904
  const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory);
35794
35905
  const pinnedProviderSessionIdForHistory = getBoundProviderSessionIdPin(targetSid);
35906
+ const explicitHistorySessionId = getExplicitHistorySessionId(args);
35795
35907
  const historySessionIdIsRuntimeFallback = Boolean(
35796
- targetSid && historySessionId === targetSid && !getExplicitHistorySessionId(args)
35908
+ targetSid && isRuntimeFallbackHistorySessionId(historySessionId, targetSid) && (!explicitHistorySessionId || isRuntimeFallbackHistorySessionId(explicitHistorySessionId, targetSid))
35797
35909
  );
35798
35910
  const effectiveHistorySessionIdForRead = historySessionIdIsRuntimeFallback ? pinnedProviderSessionIdForHistory || void 0 : historySessionId;
35799
35911
  const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
@@ -35825,17 +35937,21 @@ async function handleReadChat(h, args) {
35825
35937
  const lookup = history?.lookup === "workspace" ? "workspace" : "session";
35826
35938
  const historyMessages = Array.isArray(history?.messages) ? normalizeAndFilterNativeHistory(h, agentStr, args, history.messages, history?.providerSessionId) : [];
35827
35939
  const historyProviderSessionId = typeof history?.providerSessionId === "string" ? history.providerSessionId : readHistorySessionIdFromMessages(historyMessages) || effectiveHistorySessionIdForRead;
35828
- if (typeof history?.providerSessionId === "string" && history.providerSessionId.trim()) {
35940
+ const historyLookupIsWorkspace = lookup === "workspace";
35941
+ const historyOwnerConfirmed = agentStr === "antigravity-cli" && history?.ownerConfirmed === true;
35942
+ const historyOwnerConfirmedUuid = historyOwnerConfirmed && typeof historyProviderSessionId === "string" && historyProviderSessionId.trim() ? historyProviderSessionId.trim() : "";
35943
+ if (typeof history?.providerSessionId === "string" && history.providerSessionId.trim() && (!historyLookupIsWorkspace || !agentStr || agentStr !== "antigravity-cli" || historyOwnerConfirmed)) {
35829
35944
  recordBoundProviderSessionId(h, effectiveReadSessionId(h, targetSid), history.providerSessionId.trim());
35830
35945
  }
35831
- const mappingSessionId = effectiveHistorySessionIdForRead;
35832
- const safeMapping = supportsNative ? hasSafeNativeHistoryMapping({
35833
- historySessionId: lookup === "workspace" ? void 0 : mappingSessionId,
35834
- providerSessionId: lookup === "workspace" ? void 0 : historyProviderSessionId,
35946
+ const mappingSessionId = historyOwnerConfirmedUuid || effectiveHistorySessionIdForRead;
35947
+ const antigravityWorkspaceLatestUnconfirmed = agentStr === "antigravity-cli" && historyLookupIsWorkspace && !historyOwnerConfirmedUuid;
35948
+ const safeMapping = supportsNative && !antigravityWorkspaceLatestUnconfirmed ? hasSafeNativeHistoryMapping({
35949
+ historySessionId: historyOwnerConfirmedUuid || (lookup === "workspace" ? void 0 : mappingSessionId),
35950
+ providerSessionId: historyOwnerConfirmedUuid || (lookup === "workspace" ? void 0 : historyProviderSessionId),
35835
35951
  workspace,
35836
35952
  nativeMessages: historyMessages
35837
35953
  }) : false;
35838
- const trustedExactNativeIdentity = lookup !== "workspace" && Boolean(mappingSessionId) && Boolean(historyProviderSessionId) && mappingSessionId === historyProviderSessionId;
35954
+ const trustedExactNativeIdentity = (lookup !== "workspace" || Boolean(historyOwnerConfirmedUuid)) && Boolean(mappingSessionId) && Boolean(historyProviderSessionId) && mappingSessionId === historyProviderSessionId;
35839
35955
  const machineSessionKey = String(
35840
35956
  args?.targetSessionId || historyProviderSessionId || historySessionId || h.currentSession?.sessionId || ""
35841
35957
  );
@@ -39416,7 +39532,13 @@ function toHostedCliRuntimeDescriptor(record) {
39416
39532
  cliType,
39417
39533
  workspace,
39418
39534
  cliArgs: Array.isArray(record.meta?.cliArgs) ? record.meta.cliArgs : [],
39419
- providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
39535
+ providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0,
39536
+ // Real spawn time (PAST timestamp) of the underlying runtime — startedAt is
39537
+ // stamped on markStarted; fall back to createdAt (record creation). Threaded
39538
+ // through so an attach restores the native-history session-floor to the
39539
+ // runtime's actual birth instead of collapsing spawnedAtMs to 0 (which broke
39540
+ // the antigravity per-session birth-floor for co-located MAGI runtimes).
39541
+ startedAtMs: typeof record.startedAt === "number" && record.startedAt > 0 ? record.startedAt : typeof record.createdAt === "number" && record.createdAt > 0 ? record.createdAt : void 0
39420
39542
  };
39421
39543
  }
39422
39544
  function getWriteConflictOwnerClientId(error) {
@@ -48601,6 +48723,11 @@ var DEFAULT_COORDINATOR_DELEGATED_ENV_UNSETS = [
48601
48723
  function hasCliArg(args, flag) {
48602
48724
  return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
48603
48725
  }
48726
+ function resolveHostedSpawnedAtMs(attachExisting, attachStartedAtMs, nowMs) {
48727
+ if (!attachExisting) return nowMs;
48728
+ if (typeof attachStartedAtMs === "number" && attachStartedAtMs > 0) return attachStartedAtMs;
48729
+ return 0;
48730
+ }
48604
48731
  function hasConfigOverride(args, key2) {
48605
48732
  for (let index = 0; index < args.length; index += 1) {
48606
48733
  const arg = args[index];
@@ -48929,15 +49056,30 @@ var DaemonCliManager = class {
48929
49056
  workspace: resolvedDir,
48930
49057
  // attachExisting === true means we're restoring an already-spawned
48931
49058
  // hosted runtime after a daemon restart, not starting a fresh PTY.
48932
- // The real spawn time is in the past and we don't have it on the
48933
- // restored descriptor; pinning spawnedAtMs to Date.now() in that
48934
- // case would push the native-history session-floor cutoff past
48935
- // every existing transcript file, so the agy/hermes/claude reader
48936
- // would return null even though the transcript on disk is fresh.
48937
- // 0 disables the floor for this session — recent_window_ms in the
48938
- // spec still bounds how far back we look. Fresh launches still
48939
- // get a proper floor so prior-session leak protection holds.
48940
- spawnedAtMs: attachExisting ? 0 : Date.now()
49059
+ //
49060
+ // NEVER use Date.now() for the attach case: the real spawn time is in
49061
+ // the PAST, and pinning the floor to now would push the native-history
49062
+ // session-floor cutoff past every existing transcript file, so the
49063
+ // agy/hermes/claude reader would return null even though the transcript
49064
+ // on disk is fresh (the ANTIGRAVITY-FINAL-MESSAGE-TAIL-GAP regression).
49065
+ //
49066
+ // But collapsing to 0 for EVERY attach is also wrong: with the mesh
49067
+ // coordinator + MAGI replicas all running as hosted runtimes sharing one
49068
+ // workspace and attached with attachExisting=true, spawnedAtMs=0 disables
49069
+ // the per-session native-history birth-floor for all of them. Without a
49070
+ // floor, resolveAntigravityPath takes the floor-less newest-by-mtime
49071
+ // branch (ownerConfirmed:false) and a replica's read can claim the
49072
+ // coordinator's OWN conversation, which then reads as claimedByOther —
49073
+ // regressing the coordinator chat to the pty-parser (user-only) path.
49074
+ //
49075
+ // So when the session-host record's REAL startedAt (a PAST timestamp) is
49076
+ // recoverable, use it: the floor lands at the runtime's actual birth, the
49077
+ // transcript is still found, AND each session's floor isolates its own
49078
+ // conversation. Fall back to 0 ONLY when startedAt is unrecoverable (the
49079
+ // genuine post-restart-unknown case) — that preserves the tail-gap
49080
+ // protection. Fresh launches still get Date.now() so prior-session leak
49081
+ // protection holds.
49082
+ spawnedAtMs: resolveHostedSpawnedAtMs(attachExisting, options?.attachStartedAtMs, Date.now())
48941
49083
  });
48942
49084
  } catch (spawnErr) {
48943
49085
  LOG.error("CLI", `[${cliType}] Spawn failed: ${spawnErr?.message}`);
@@ -49300,7 +49442,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
49300
49442
  true,
49301
49443
  {
49302
49444
  providerSessionId: sessionBinding.providerSessionId,
49303
- launchMode: "manual"
49445
+ launchMode: "manual",
49446
+ // Thread the runtime's REAL past spawn time so the attach restores
49447
+ // the per-session native-history birth-floor instead of collapsing
49448
+ // to spawnedAtMs:0 (which disabled the antigravity per-session floor
49449
+ // and let MAGI replicas claim the coordinator's own conversation).
49450
+ // Undefined → registerCliInstance keeps the 0 fallback.
49451
+ attachStartedAtMs: record.startedAtMs
49304
49452
  }
49305
49453
  );
49306
49454
  restoredBindings.add(bindingKey);
@@ -51431,8 +51579,10 @@ function createNativeHistoryDispatcher(reader) {
51431
51579
  const requestedProviderSid = input.providerSessionId || "";
51432
51580
  const sessionStartedAtMs = typeof input.sessionStartedAtMs === "number" ? input.sessionStartedAtMs : typeof input.args?.sessionStartedAtMs === "number" ? input.args.sessionStartedAtMs : 0;
51433
51581
  const instanceId = typeof input.instanceId === "string" ? input.instanceId : typeof input.args?.instanceId === "string" ? input.args.instanceId : "";
51434
- const sourcePath = resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs, instanceId);
51582
+ const resolved = resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs, instanceId);
51583
+ const sourcePath = resolved?.path || null;
51435
51584
  if (!sourcePath) return null;
51585
+ const ownerConfirmed = reader === "antigravity-cli" ? resolved?.ownerConfirmed === true : void 0;
51436
51586
  if (input.forceRefresh === true || input.args?.forceRefresh === true) {
51437
51587
  try {
51438
51588
  fs26.statSync(sourcePath);
@@ -51462,20 +51612,27 @@ function createNativeHistoryDispatcher(reader) {
51462
51612
  providerSessionId: resolvedProviderSessionId,
51463
51613
  sourcePath: session.sourcePath,
51464
51614
  sourceMtimeMs: session.sourceMtimeMs,
51465
- nativeHistoryCoverage: session.nativeHistoryCoverage || "full"
51615
+ nativeHistoryCoverage: session.nativeHistoryCoverage || "full",
51616
+ ownerConfirmed
51466
51617
  };
51467
51618
  };
51468
51619
  }
51469
51620
  function resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs, instanceId) {
51470
51621
  switch (reader) {
51471
- case "claude-cli":
51472
- return resolveClaudePath(workspace, sessionId);
51473
- case "codex-cli":
51474
- return resolveCodexPath(workspace, sessionId, sessionStartedAtMs);
51622
+ case "claude-cli": {
51623
+ const p = resolveClaudePath(workspace, sessionId);
51624
+ return p ? { path: p } : null;
51625
+ }
51626
+ case "codex-cli": {
51627
+ const p = resolveCodexPath(workspace, sessionId, sessionStartedAtMs);
51628
+ return p ? { path: p } : null;
51629
+ }
51475
51630
  case "antigravity-cli":
51476
51631
  return resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId);
51477
- case "hermes-cli":
51478
- return resolveHermesPath(workspace, sessionId);
51632
+ case "hermes-cli": {
51633
+ const p = resolveHermesPath(workspace, sessionId);
51634
+ return p ? { path: p } : null;
51635
+ }
51479
51636
  }
51480
51637
  }
51481
51638
  function resolveClaudePath(workspace, sessionId) {
@@ -51607,7 +51764,7 @@ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instan
51607
51764
  const dbPath = path34.join(agyRoot, "conversations", `${sessionId}.db`);
51608
51765
  if (fs26.existsSync(dbPath)) {
51609
51766
  if (owner) claimAntigravityConversation(sessionId, owner);
51610
- return dbPath;
51767
+ return { path: dbPath, ownerConfirmed: true };
51611
51768
  }
51612
51769
  }
51613
51770
  const brainRoot2 = path34.join(agyRoot, "brain");
@@ -51622,6 +51779,7 @@ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instan
51622
51779
  return { uuid: e.name, p, mtime: safeMtime(p), birth: safeBirthtime(p) };
51623
51780
  }).filter((e) => e.mtime >= cutoff);
51624
51781
  let ordered = [];
51782
+ const brainOwnerConfirmed = sessionStartedAtMs > 0;
51625
51783
  if (sessionStartedAtMs > 0) {
51626
51784
  const floor = sessionStartedAtMs - AGY_SPAWN_CLAIM_GRACE_MS;
51627
51785
  ordered = all.filter((e) => (e.birth > 0 ? e.birth : e.mtime) >= floor).sort((a, b) => (a.birth || a.mtime) - (b.birth || b.mtime));
@@ -51632,7 +51790,7 @@ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instan
51632
51790
  const t = nonEmptyBrain(e.uuid, e.p);
51633
51791
  if (t) {
51634
51792
  if (owner) claimAntigravityConversation(e.uuid, owner);
51635
- return t;
51793
+ return { path: t, ownerConfirmed: brainOwnerConfirmed };
51636
51794
  }
51637
51795
  }
51638
51796
  }
@@ -51640,7 +51798,7 @@ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instan
51640
51798
  const picked = pickUnboundConversationDb(convRoot, sessionStartedAtMs, owner);
51641
51799
  if (picked) {
51642
51800
  if (owner) claimAntigravityConversation(picked.uuid, owner);
51643
- return picked.path;
51801
+ return { path: picked.path, ownerConfirmed: picked.ownerConfirmed };
51644
51802
  }
51645
51803
  return null;
51646
51804
  }
@@ -51671,10 +51829,10 @@ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
51671
51829
  const own = candidates.filter((c) => (c.birth > 0 ? c.birth : c.mtime) >= floor);
51672
51830
  if (own.length === 0) return null;
51673
51831
  own.sort((a, b) => (a.birth || a.mtime) - (b.birth || b.mtime));
51674
- return { path: own[0].path, uuid: own[0].uuid };
51832
+ return { path: own[0].path, uuid: own[0].uuid, ownerConfirmed: true };
51675
51833
  }
51676
51834
  candidates.sort((a, b) => b.mtime - a.mtime);
51677
- return { path: candidates[0].path, uuid: candidates[0].uuid };
51835
+ return { path: candidates[0].path, uuid: candidates[0].uuid, ownerConfirmed: false };
51678
51836
  }
51679
51837
  function spawnAwareCutoff(sessionStartedAtMs) {
51680
51838
  const recency = Date.now() - RECENT_WINDOW_MS;
@@ -69697,6 +69855,7 @@ var V1_CONTRACT_VERSION = "1.0.0";
69697
69855
  detectCLIs,
69698
69856
  detectClaudeAskUserQuestionPromptFromJson,
69699
69857
  detectIDEs,
69858
+ detectNewlySettledCompletedSessions,
69700
69859
  drainPendingMeshCoordinatorEvents,
69701
69860
  enqueueTask,
69702
69861
  ensureSessionHostReady,