@adhdev/daemon-core 0.9.82-rc.376 → 0.9.82-rc.378

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.
Files changed (48) hide show
  1. package/dist/commands/chat-commands-debug-bundle.d.ts +14 -0
  2. package/dist/commands/chat-commands-read.d.ts +7 -0
  3. package/dist/commands/chat-commands-scope.d.ts +39 -0
  4. package/dist/commands/chat-commands-shared.d.ts +33 -0
  5. package/dist/commands/chat-commands-write.d.ts +14 -0
  6. package/dist/commands/chat-commands.d.ts +9 -49
  7. package/dist/commands/router.d.ts +3 -470
  8. package/dist/index.js +3166 -3115
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +3561 -3510
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/mesh/mesh-coordinator-config.d.ts +21 -0
  13. package/dist/mesh/mesh-event-classify.d.ts +5 -0
  14. package/dist/mesh/mesh-event-forwarding.d.ts +18 -0
  15. package/dist/mesh/mesh-events-coordinator.d.ts +4 -92
  16. package/dist/mesh/mesh-events-utils.d.ts +3 -0
  17. package/dist/mesh/mesh-ledger-reconciliation.d.ts +0 -1
  18. package/dist/mesh/mesh-node-identity.d.ts +289 -0
  19. package/dist/mesh/mesh-queue-assignment.d.ts +86 -0
  20. package/dist/mesh/mesh-refine-gates.d.ts +428 -0
  21. package/dist/mesh/mesh-runtime-store.d.ts +0 -3
  22. package/dist/providers/native-history/constants.d.ts +12 -0
  23. package/dist/runtime-defaults.d.ts +2 -0
  24. package/package.json +2 -2
  25. package/src/commands/chat-commands-debug-bundle.ts +398 -0
  26. package/src/commands/chat-commands-read.ts +2327 -0
  27. package/src/commands/chat-commands-scope.ts +54 -0
  28. package/src/commands/chat-commands-shared.ts +114 -0
  29. package/src/commands/chat-commands-write.ts +880 -0
  30. package/src/commands/chat-commands.ts +20 -3697
  31. package/src/commands/router.ts +59 -3631
  32. package/src/mesh/mesh-coordinator-config.ts +97 -0
  33. package/src/mesh/mesh-event-classify.ts +51 -0
  34. package/src/mesh/mesh-event-forwarding.ts +1502 -0
  35. package/src/mesh/mesh-events-coordinator.ts +30 -2993
  36. package/src/mesh/mesh-events-pending.ts +1 -10
  37. package/src/mesh/mesh-events-stale.ts +3 -14
  38. package/src/mesh/mesh-events-utils.ts +52 -14
  39. package/src/mesh/mesh-ledger-reconciliation.ts +0 -2
  40. package/src/mesh/mesh-node-identity.ts +1887 -0
  41. package/src/mesh/mesh-queue-assignment.ts +1457 -0
  42. package/src/mesh/mesh-refine-gates.ts +1652 -0
  43. package/src/mesh/mesh-runtime-store.ts +0 -37
  44. package/src/providers/cli-provider-instance.ts +40 -1
  45. package/src/providers/native-history/constants.ts +19 -0
  46. package/src/providers/native-history/dispatcher.ts +2 -3
  47. package/src/providers/spec/native-history-executor.ts +1 -9
  48. package/src/runtime-defaults.ts +39 -0
@@ -152,21 +152,6 @@ export class MeshRuntimeStore {
152
152
  expires_at INTEGER NOT NULL
153
153
  );
154
154
 
155
- -- R3: idempotent coordinator inbox. When a terminal/force-inject event is
156
- -- direct-injected into a LIVE local CLI coordinator (coord.onEvent('send_message')),
157
- -- we record (coordinator_daemon_id, fingerprint) here. That same coordinator also
158
- -- polls get_pending_mesh_events, which would re-deliver the queued copy of the very
159
- -- event it just received in its PTY → user sees the completion twice. The drain for
160
- -- a coordinator daemon filters out events already direct-delivered to it, giving
161
- -- exactly-once-per-coordinator while keeping the queue for other consumers (idle /
162
- -- MCP-only / remote) that did NOT receive the direct inject.
163
- CREATE TABLE IF NOT EXISTS mesh_direct_delivered_events (
164
- coordinator_daemon_id TEXT NOT NULL,
165
- fingerprint TEXT NOT NULL,
166
- expires_at INTEGER NOT NULL,
167
- PRIMARY KEY (coordinator_daemon_id, fingerprint)
168
- );
169
-
170
155
  CREATE TABLE IF NOT EXISTS mesh_direct_dispatches (
171
156
  task_id TEXT PRIMARY KEY,
172
157
  mesh_id TEXT NOT NULL,
@@ -342,28 +327,6 @@ export class MeshRuntimeStore {
342
327
  this.db.prepare('DELETE FROM mesh_completion_fingerprints WHERE expires_at <= ?').run(Date.now());
343
328
  }
344
329
 
345
- // R3: record that an event (by pending-event fingerprint) was direct-injected into a live
346
- // coordinator on the given daemon, so that coordinator's own drain skips the queued copy.
347
- recordDirectDelivered(coordinatorDaemonId: string, fingerprint: string, ttlMs: number): void {
348
- if (!coordinatorDaemonId || !fingerprint) return;
349
- this.db.prepare(
350
- 'INSERT OR REPLACE INTO mesh_direct_delivered_events (coordinator_daemon_id, fingerprint, expires_at) VALUES (?, ?, ?)'
351
- ).run(coordinatorDaemonId, fingerprint, Date.now() + ttlMs);
352
- this.maybeCheckpointWal();
353
- }
354
-
355
- wasDirectDelivered(coordinatorDaemonId: string, fingerprint: string): boolean {
356
- if (!coordinatorDaemonId || !fingerprint) return false;
357
- const row = this.db.prepare(
358
- 'SELECT 1 FROM mesh_direct_delivered_events WHERE coordinator_daemon_id = ? AND fingerprint = ? AND expires_at > ?'
359
- ).get(coordinatorDaemonId, fingerprint, Date.now());
360
- return row !== undefined;
361
- }
362
-
363
- sweepExpiredDirectDelivered(): void {
364
- this.db.prepare('DELETE FROM mesh_direct_delivered_events WHERE expires_at <= ?').run(Date.now());
365
- }
366
-
367
330
  private maybeCheckpointWal(): void {
368
331
  if (++this.walWriteCounter < MeshRuntimeStore.WAL_CHECK_INTERVAL) return;
369
332
  this.walWriteCounter = 0;
@@ -81,6 +81,14 @@ type CompletedFinalizationBlock = {
81
81
  reason: string;
82
82
  terminal?: boolean;
83
83
  allowTimeout?: boolean;
84
+ // (SETTLE-VALLEY) When set, suppress the CANON-C decoupled-immediate emit for this
85
+ // missing_final_assistant block and HOLD (retry up to COMPLETED_FINALIZATION_MAX_WAIT_MS)
86
+ // until the native transcript's final assistant turn arrives (block clears → genuine emit)
87
+ // or the worker resumes (resume guard cancels). Set only for the inter-approval idle valley
88
+ // of a native-history mesh worker, where an immediate weak emit would freeze a truncated
89
+ // preamble summary (evidenceLevel=insufficient) into the append-only ledger before the
90
+ // worker's next approval turn resumes. Independent of valley length.
91
+ holdForTranscript?: boolean;
84
92
  };
85
93
 
86
94
  type CompletionFinalAssistantEvidence = {
@@ -113,7 +121,13 @@ const COMPLETED_FINALIZATION_MAX_WAIT_MS = 30_000;
113
121
  // agent picking the turn back up. A short non-zero settle window restores that resume guard for
114
122
  // mesh workers without delaying genuinely-finished turns beyond this bound. Scoped to mesh
115
123
  // worker sessions so interactive native-history sessions keep the immediate flush.
116
- const NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 1500;
124
+ // 4000ms (was 1500): live measurement showed the completion event can fire 1.6–3s
125
+ // BEFORE the worker's final-assistant turn lands in the transcript on a natural
126
+ // generating→idle completion (no approval modal), freezing a prior intermediate
127
+ // bubble as finalSummary (evidenceLevel=insufficient). The 68a3c324 waiting_approval
128
+ // hold only covers the approval-resolved valley; widening this settle window to 4000ms
129
+ // covers that race AND the ~3s waiting_approval valley within the settle bound.
130
+ const NATIVE_HISTORY_MESH_IDLE_SETTLE_MS = 4000;
117
131
  // TASKBUBBLE-DUP: window during which an identical user-input ack (same trimmed
118
132
  // content on the same instance) is treated as a redelivery of one dispatch and
119
133
  // suppressed from the chat transcript. Matches the coordinator-side
@@ -1441,6 +1455,22 @@ export class CliProviderInstance implements ProviderInstance {
1441
1455
  if (this.type === 'antigravity-cli') {
1442
1456
  return null;
1443
1457
  }
1458
+ // (SETTLE-VALLEY) The inter-approval idle valley: a native-history mesh worker
1459
+ // that resolved an approval and fell briefly idle (waiting_approval→idle) BEFORE
1460
+ // the next approval turn resumes. The live valley (~3s) is mostly covered by the
1461
+ // 4000ms NATIVE_HISTORY_MESH_IDLE_SETTLE_MS settle window, but a longer valley can
1462
+ // still let the flush run while the transcript's final assistant turn is not yet
1463
+ // written (source still the screen parse → finalAssistantPresent=false,
1464
+ // workerResult.source='default'). CANON-C would emit immediately here, freezing a
1465
+ // truncated preamble summary as evidenceLevel=insufficient. Instead HOLD: this
1466
+ // waiting_approval hold complements the settle window. Retry until the transcript finalizes
1467
+ // (block clears → genuine emit) or the worker resumes (resume guard cancels),
1468
+ // bounded by COMPLETED_FINALIZATION_MAX_WAIT_MS. Scoped to the approval-resolved
1469
+ // idle so a genuinely-finished background-child turn keeps the CANON-C immediate
1470
+ // emit (its transcript trails by a write, not by a whole resume).
1471
+ if (allowMissingAssistantTimeout && pending.previousStatus === 'waiting_approval') {
1472
+ return { reason: 'missing_final_assistant', terminal: false, holdForTranscript: true };
1473
+ }
1444
1474
  return { reason: 'missing_final_assistant', terminal: true, allowTimeout: allowMissingAssistantTimeout };
1445
1475
  }
1446
1476
  if ((this.provider as any).requiresFinalAssistantBeforeIdle === true) {
@@ -1585,6 +1615,15 @@ export class CliProviderInstance implements ProviderInstance {
1585
1615
  // one still surfaces, and isFalseIdleCompletion keeps the direct dispatch active until
1586
1616
  // then). All OTHER blocks (genuinely-busy adapter/partial/parsed states, transient
1587
1617
  // parse_error) keep the existing terminal-hold / 30s-retry behavior unchanged.
1618
+ //
1619
+ // (SETTLE-VALLEY) Exception: a `holdForTranscript` block is the inter-approval idle
1620
+ // valley of a native-history mesh worker (waiting_approval→idle that will resume into
1621
+ // the next approval). It deliberately does NOT carry allowTimeout, so it falls into the
1622
+ // hold-and-retry path below (terminal:false) rather than the CANON-C immediate emit —
1623
+ // the retry loop re-runs the resume guard each cycle, so when the worker resumes the
1624
+ // pending completion is cancelled, and when the transcript's final assistant arrives the
1625
+ // block clears for a GENUINE emit. This blocks the truncated weak (insufficient) summary
1626
+ // from ever being emitted during the valley, without depending on the valley's length.
1588
1627
  const isTranscriptEvidenceGate = block.allowTimeout === true;
1589
1628
  LOG.debug('CLI', `[${this.type}] finalization block: reason=${blockReason} terminal=${block.terminal} allowTimeout=${isTranscriptEvidenceGate} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
1590
1629
  if (!isTranscriptEvidenceGate && (block.terminal || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS)) {
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Shared constants for the native-history subtree.
3
+ *
4
+ * OSS code (AGPL-3.0). Must not import from packages/ (proprietary).
5
+ */
6
+ 'use strict';
7
+
8
+ /**
9
+ * Spawn-bind grace window: an on-disk rollout whose session_meta.timestamp
10
+ * lands within ±SPAWN_BIND_GRACE_MS of the daemon's spawnedAtMs is treated
11
+ * as belonging to that daemon session. 10s is long enough to absorb codex
12
+ * binary startup latency on cold caches and short enough that two
13
+ * back-to-back launches don't both fall inside the same window.
14
+ *
15
+ * Shared by the declarative executor (providers/spec/native-history-executor.ts)
16
+ * and the codex runtime disambiguator (providers/native-history/dispatcher.ts) —
17
+ * both apply the identical ±10s session-binding window.
18
+ */
19
+ export const SPAWN_BIND_GRACE_MS = 10_000;
@@ -18,6 +18,7 @@ import { readSession as readClaudeCliSession } from './claude-cli-transcript.js'
18
18
  import { readSession as readCodexCliSession } from './codex-cli-transcript.js';
19
19
  import { readSession as readAntigravityCliSession } from './antigravity-cli-transcript.js';
20
20
  import { readSession as readHermesCliSession } from './hermes-cli-transcript.js';
21
+ import { SPAWN_BIND_GRACE_MS } from './constants.js';
21
22
 
22
23
  export type ReaderId = 'claude-cli' | 'codex-cli' | 'antigravity-cli' | 'hermes-cli';
23
24
 
@@ -153,8 +154,6 @@ function findCodexPathBySessionId(root: string, sessionId: string): string | nul
153
154
  return matches[0]?.p ?? null;
154
155
  }
155
156
 
156
- const CODEX_SPAWN_BIND_GRACE_MS = 10_000;
157
-
158
157
  function findCodexPathByRuntime(root: string, workspace: string, sessionStartedAtMs: number): string | null {
159
158
  if (!fs.existsSync(root) || !workspace) return null;
160
159
  const workspaceResolved = resolveRealPath(workspace);
@@ -180,7 +179,7 @@ function findCodexPathByRuntime(root: string, workspace: string, sessionStartedA
180
179
  const diff = sessionStartedAtMs > 0 && meta.timestampMs != null
181
180
  ? Math.abs(meta.timestampMs - sessionStartedAtMs)
182
181
  : 0;
183
- if (sessionStartedAtMs > 0 && (meta.timestampMs == null || diff > CODEX_SPAWN_BIND_GRACE_MS)) continue;
182
+ if (sessionStartedAtMs > 0 && (meta.timestampMs == null || diff > SPAWN_BIND_GRACE_MS)) continue;
184
183
  matches.push({ p: entryPath, mtime, diff });
185
184
  }
186
185
  }
@@ -30,6 +30,7 @@ import type {
30
30
  NativeHistorySqliteSource,
31
31
  NativeHistoryToolMap,
32
32
  } from './types.js';
33
+ import { SPAWN_BIND_GRACE_MS } from '../native-history/constants.js';
33
34
 
34
35
  export interface NativeHistoryInput {
35
36
  agentType?: string;
@@ -707,15 +708,6 @@ function readCandidateSessionMeta(filePath: string): CandidateMeta | null {
707
708
  }
708
709
  }
709
710
 
710
- /**
711
- * Spawn-bind grace window: an on-disk rollout whose session_meta.timestamp
712
- * lands within ±SPAWN_BIND_GRACE_MS of the daemon's spawnedAtMs is treated
713
- * as belonging to that daemon session. 10s is long enough to absorb codex
714
- * binary startup latency on cold caches and short enough that two
715
- * back-to-back launches don't both fall inside the same window.
716
- */
717
- const SPAWN_BIND_GRACE_MS = 10_000;
718
-
719
711
  function pickBoundFromEntries(
720
712
  candidatePaths: string[],
721
713
  sessionFloorMs: number,
@@ -14,3 +14,42 @@ export const DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS = 10_000;
14
14
  export const DEFAULT_SESSION_HOST_READY_TIMEOUT_MS = 15_000;
15
15
 
16
16
  export const STANDALONE_CDP_SCAN_INTERVAL_MS = 15_000;
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Mesh P2P timeout windows (env-overridable)
20
+ // ---------------------------------------------------------------------------
21
+
22
+ // Reads a mesh timeout (ms) from the first non-empty env var in `names`, clamped
23
+ // to [1_000, 120_000]; falls back to `defaultMs` when none is set or the value is
24
+ // out of range. The clamp lets a slow real link be tuned up (TURN-relayed peers
25
+ // whose RTT is many seconds) and lets the test harness shrink the window to its
26
+ // 1s minimum, without ever degenerating to 0 or an absurd value. Multiple names
27
+ // are accepted so a renamed constant can keep honoring a legacy alias.
28
+ export function readMeshTimeoutEnvMs(names: string | string[], defaultMs: number): number {
29
+ const candidates = Array.isArray(names) ? names : [names];
30
+ for (const name of candidates) {
31
+ const raw = process.env[name]?.trim();
32
+ if (!raw) continue;
33
+ const parsed = Number.parseInt(raw, 10);
34
+ if (Number.isFinite(parsed) && parsed >= 1_000 && parsed <= 120_000) return parsed;
35
+ return defaultMs;
36
+ }
37
+ return defaultMs;
38
+ }
39
+
40
+ // SINGLE source of truth for the mesh cold-open *connect* budget — the time a
41
+ // caller grants a peer whose mesh DataChannel is not open yet to drive the
42
+ // cross-machine (often TURN-relayed) ICE/DTLS handshake before the response
43
+ // deadline takes over. Two call sites share this so an env override tunes BOTH:
44
+ // - commands/router.ts direct-peer git_status probe (requireDirectPeerTruth)
45
+ // - mesh/mesh-events-coordinator.ts remote task-dispatch (deliverTaskToSession)
46
+ // Before unification the coordinator hard-coded 45_000 while the router was
47
+ // env-overridable, so setting the env tuned the probe path but silently left the
48
+ // dispatch path at 45s — the same nominal 45s, but divergent the moment the env
49
+ // was set. Matches the daemon-cloud DaemonMeshManager CONNECT_TIMEOUT_MS (45s).
50
+ // `MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS` is honored as a backward-compat alias so
51
+ // environments already tuned under the old name keep working.
52
+ export const MESH_CONNECT_TIMEOUT_MS = readMeshTimeoutEnvMs(
53
+ ['MESH_CONNECT_TIMEOUT_MS', 'MESH_DIRECT_PROBE_CONNECT_TIMEOUT_MS'],
54
+ 45_000,
55
+ );