@adhdev/daemon-core 0.9.82-rc.194 → 0.9.82-rc.196

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 (37) hide show
  1. package/dist/cli-adapter-types.d.ts +1 -0
  2. package/dist/index.js +202 -70
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +205 -73
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/mesh/contracts.d.ts +1 -1
  7. package/dist/mesh/mesh-active-work.d.ts +1 -1
  8. package/dist/mesh/{beads-db.d.ts → mesh-runtime-store.d.ts} +2 -2
  9. package/dist/mesh/mesh-work-queue.d.ts +3 -3
  10. package/dist/providers/provider-instance.d.ts +1 -1
  11. package/dist/providers/spec/driver.d.ts +4 -1
  12. package/dist/providers/spec/schema.gen.d.ts +46 -0
  13. package/dist/providers/spec/types.d.ts +39 -0
  14. package/dist/shared-types-extra.d.ts +1 -1
  15. package/dist/status/normalize.d.ts +1 -1
  16. package/dist/status/normalize.js +1 -0
  17. package/dist/status/normalize.js.map +1 -1
  18. package/dist/status/normalize.mjs +1 -0
  19. package/dist/status/normalize.mjs.map +1 -1
  20. package/package.json +1 -1
  21. package/src/cli-adapter-types.ts +1 -0
  22. package/src/cli-adapters/cli-state-engine.ts +44 -2
  23. package/src/mesh/contracts.ts +1 -1
  24. package/src/mesh/mesh-active-work.ts +8 -8
  25. package/src/mesh/mesh-events.ts +12 -12
  26. package/src/mesh/{beads-db.ts → mesh-runtime-store.ts} +30 -7
  27. package/src/mesh/mesh-work-queue.ts +33 -33
  28. package/src/providers/cli-provider-instance.ts +31 -8
  29. package/src/providers/provider-instance.ts +1 -1
  30. package/src/providers/spec/driver.ts +34 -3
  31. package/src/providers/spec/evaluator.ts +32 -3
  32. package/src/providers/spec/schema.gen.ts +22 -2
  33. package/src/providers/spec/schema.json +1 -0
  34. package/src/providers/spec/types.ts +39 -0
  35. package/src/providers/types/interactive-prompt.ts +21 -7
  36. package/src/shared-types-extra.ts +1 -1
  37. package/src/status/normalize.ts +2 -0
package/dist/index.mjs CHANGED
@@ -3290,8 +3290,8 @@ var init_mesh_fast_forward = __esm({
3290
3290
  }
3291
3291
  });
3292
3292
 
3293
- // src/mesh/beads-db.ts
3294
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, statSync as statSync4 } from "fs";
3293
+ // src/mesh/mesh-runtime-store.ts
3294
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, statSync as statSync4 } from "fs";
3295
3295
  import { dirname as dirname2, join as join12 } from "path";
3296
3296
  import { createRequire } from "module";
3297
3297
  function loadDatabaseCtor() {
@@ -3306,13 +3306,31 @@ function safeMeshId(meshId) {
3306
3306
  function legacyQueuePath(meshId) {
3307
3307
  return join12(getLedgerDir(), `${safeMeshId(meshId)}.queue.json`);
3308
3308
  }
3309
- var DatabaseCtor, BeadsDB;
3310
- var init_beads_db = __esm({
3311
- "src/mesh/beads-db.ts"() {
3309
+ function meshRuntimeStorePath() {
3310
+ const dir = getLedgerDir();
3311
+ const nextPath = join12(dir, "mesh-runtime.db");
3312
+ if (existsSync11(nextPath)) return nextPath;
3313
+ const legacyPath = join12(dir, "beads.db");
3314
+ if (!existsSync11(legacyPath)) return nextPath;
3315
+ try {
3316
+ renameSync3(legacyPath, nextPath);
3317
+ for (const suffix of ["-wal", "-shm"]) {
3318
+ const legacyCompanion = `${legacyPath}${suffix}`;
3319
+ if (existsSync11(legacyCompanion)) {
3320
+ renameSync3(legacyCompanion, `${nextPath}${suffix}`);
3321
+ }
3322
+ }
3323
+ } catch {
3324
+ }
3325
+ return nextPath;
3326
+ }
3327
+ var DatabaseCtor, MeshRuntimeStore;
3328
+ var init_mesh_runtime_store = __esm({
3329
+ "src/mesh/mesh-runtime-store.ts"() {
3312
3330
  "use strict";
3313
3331
  init_mesh_ledger();
3314
3332
  init_mesh_work_queue();
3315
- BeadsDB = class _BeadsDB {
3333
+ MeshRuntimeStore = class _MeshRuntimeStore {
3316
3334
  static instance;
3317
3335
  db;
3318
3336
  dbPath;
@@ -3335,7 +3353,7 @@ var init_beads_db = __esm({
3335
3353
  }
3336
3354
  static getInstance() {
3337
3355
  if (!this.instance) {
3338
- this.instance = new _BeadsDB(join12(getLedgerDir(), "beads.db"));
3356
+ this.instance = new _MeshRuntimeStore(meshRuntimeStorePath());
3339
3357
  }
3340
3358
  return this.instance;
3341
3359
  }
@@ -3420,13 +3438,13 @@ var init_beads_db = __esm({
3420
3438
  this.db.prepare("DELETE FROM mesh_completion_fingerprints WHERE expires_at <= ?").run(Date.now());
3421
3439
  }
3422
3440
  maybeCheckpointWal() {
3423
- if (++this.walWriteCounter < _BeadsDB.WAL_CHECK_INTERVAL) return;
3441
+ if (++this.walWriteCounter < _MeshRuntimeStore.WAL_CHECK_INTERVAL) return;
3424
3442
  this.walWriteCounter = 0;
3425
3443
  try {
3426
3444
  const walPath = `${this.dbPath}-wal`;
3427
3445
  if (!existsSync11(walPath)) return;
3428
3446
  const size = statSync4(walPath).size;
3429
- if (size < _BeadsDB.WAL_MAX_BYTES) return;
3447
+ if (size < _MeshRuntimeStore.WAL_MAX_BYTES) return;
3430
3448
  process.stderr.write(
3431
3449
  `[adhdev-mesh] WAL file ${Math.round(size / 1024 / 1024)}MB exceeds threshold; forcing checkpoint
3432
3450
  `
@@ -3737,7 +3755,7 @@ __export(mesh_work_queue_exports, {
3737
3755
  __clearDirectDispatchesForTests: () => __clearDirectDispatchesForTests,
3738
3756
  __clearMeshQueueForTests: () => __clearMeshQueueForTests,
3739
3757
  __replaceMeshQueueForTests: () => __replaceMeshQueueForTests,
3740
- __resetBeadsDBForTests: () => __resetBeadsDBForTests,
3758
+ __resetMeshRuntimeStoreForTests: () => __resetMeshRuntimeStoreForTests,
3741
3759
  buildMeshNodeCapabilityTags: () => buildMeshNodeCapabilityTags,
3742
3760
  cancelTask: () => cancelTask,
3743
3761
  claimNextTask: () => claimNextTask,
@@ -3816,7 +3834,7 @@ function nodeSatisfiesRequiredTags(requiredTags, capabilityTags) {
3816
3834
  return required.every((tag) => available.has(tag));
3817
3835
  }
3818
3836
  function withQueueLock(_meshId, fn) {
3819
- return BeadsDB.getInstance().transaction(fn);
3837
+ return MeshRuntimeStore.getInstance().transaction(fn);
3820
3838
  }
3821
3839
  function enqueueTask(meshId, message, opts) {
3822
3840
  requireMeshHostQueueOwner(opts);
@@ -3836,55 +3854,55 @@ function enqueueTask(meshId, message, opts) {
3836
3854
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
3837
3855
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3838
3856
  };
3839
- BeadsDB.getInstance().insertQueueEntry(entry);
3857
+ MeshRuntimeStore.getInstance().insertQueueEntry(entry);
3840
3858
  return entry;
3841
3859
  }
3842
3860
  function getQueue(meshId, opts) {
3843
- return BeadsDB.getInstance().getQueueEntries(meshId, opts?.status?.length ? opts.status : void 0);
3861
+ return MeshRuntimeStore.getInstance().getQueueEntries(meshId, opts?.status?.length ? opts.status : void 0);
3844
3862
  }
3845
3863
  function getMeshQueueRevision(meshId) {
3846
- return BeadsDB.getInstance().getQueueRevision(meshId);
3864
+ return MeshRuntimeStore.getInstance().getQueueRevision(meshId);
3847
3865
  }
3848
3866
  function claimNextTask(meshId, nodeId, sessionId, capabilityTags) {
3849
- return BeadsDB.getInstance().claimNextQueueTask(meshId, nodeId, sessionId, capabilityTags);
3867
+ return MeshRuntimeStore.getInstance().claimNextQueueTask(meshId, nodeId, sessionId, capabilityTags);
3850
3868
  }
3851
3869
  function updateTaskStatus(meshId, taskId, status, opts) {
3852
3870
  requireMeshHostQueueOwner(opts);
3853
3871
  return withQueueLock(meshId, () => {
3854
- const entry = BeadsDB.getInstance().findQueueEntryById(meshId, taskId);
3872
+ const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
3855
3873
  if (!entry) return null;
3856
3874
  entry.status = status;
3857
- BeadsDB.getInstance().updateQueueEntry(entry);
3875
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
3858
3876
  return entry;
3859
3877
  });
3860
3878
  }
3861
3879
  function recordTaskAutoLaunch(meshId, taskId, autoLaunch) {
3862
3880
  return withQueueLock(meshId, () => {
3863
- const entry = BeadsDB.getInstance().findQueueEntryById(meshId, taskId);
3881
+ const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
3864
3882
  if (!entry) return null;
3865
3883
  const now = (/* @__PURE__ */ new Date()).toISOString();
3866
3884
  entry.autoLaunch = { ...autoLaunch, updatedAt: now };
3867
- BeadsDB.getInstance().updateQueueEntry(entry);
3885
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
3868
3886
  return entry;
3869
3887
  });
3870
3888
  }
3871
3889
  function cancelTask(meshId, taskId, opts) {
3872
3890
  requireMeshHostQueueOwner(opts);
3873
3891
  return withQueueLock(meshId, () => {
3874
- const entry = BeadsDB.getInstance().findQueueEntryById(meshId, taskId);
3892
+ const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
3875
3893
  if (!entry) return null;
3876
3894
  const now = (/* @__PURE__ */ new Date()).toISOString();
3877
3895
  entry.status = "cancelled";
3878
3896
  entry.cancelledAt = now;
3879
3897
  if (opts?.reason) entry.cancelReason = opts.reason;
3880
- BeadsDB.getInstance().updateQueueEntry(entry);
3898
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
3881
3899
  return entry;
3882
3900
  });
3883
3901
  }
3884
3902
  function requeueTask(meshId, taskId, opts) {
3885
3903
  requireMeshHostQueueOwner(opts);
3886
3904
  return withQueueLock(meshId, () => {
3887
- const entry = BeadsDB.getInstance().findQueueEntryById(meshId, taskId);
3905
+ const entry = MeshRuntimeStore.getInstance().findQueueEntryById(meshId, taskId);
3888
3906
  if (!entry) return null;
3889
3907
  entry.status = "pending";
3890
3908
  delete entry.assignedNodeId;
@@ -3898,22 +3916,22 @@ function requeueTask(meshId, taskId, opts) {
3898
3916
  entry.requeuedAt = (/* @__PURE__ */ new Date()).toISOString();
3899
3917
  entry.requeueCount = (entry.requeueCount || 0) + 1;
3900
3918
  if (opts?.reason) entry.requeueReason = opts.reason;
3901
- BeadsDB.getInstance().updateQueueEntry(entry);
3919
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
3902
3920
  return entry;
3903
3921
  });
3904
3922
  }
3905
3923
  function updateSessionTaskStatus(meshId, sessionId, status, opts) {
3906
3924
  return withQueueLock(meshId, () => {
3907
3925
  const occurredAtIso = opts?.occurredAt ? new Date(opts.occurredAt).toISOString() : void 0;
3908
- const entry = BeadsDB.getInstance().findAssignedBySession(meshId, sessionId, occurredAtIso);
3926
+ const entry = MeshRuntimeStore.getInstance().findAssignedBySession(meshId, sessionId, occurredAtIso);
3909
3927
  if (!entry) return null;
3910
3928
  entry.status = status;
3911
- BeadsDB.getInstance().updateQueueEntry(entry);
3929
+ MeshRuntimeStore.getInstance().updateQueueEntry(entry);
3912
3930
  return entry;
3913
3931
  });
3914
3932
  }
3915
3933
  function getMeshQueueStats(meshId) {
3916
- const rows = BeadsDB.getInstance().getQueueStatsByStatus(meshId);
3934
+ const rows = MeshRuntimeStore.getInstance().getQueueStatsByStatus(meshId);
3917
3935
  const counts = {};
3918
3936
  for (const r of rows) counts[r.status] = r.count;
3919
3937
  const pending = counts["pending"] ?? 0;
@@ -3932,26 +3950,26 @@ function getMeshQueueStats(meshId) {
3932
3950
  cancelled,
3933
3951
  activeCounts: { pending, assigned },
3934
3952
  historicalCounts: { completed, failed, cancelled },
3935
- activeAssignments: BeadsDB.getInstance().getActiveAssignmentDetails(meshId)
3953
+ activeAssignments: MeshRuntimeStore.getInstance().getActiveAssignmentDetails(meshId)
3936
3954
  };
3937
3955
  }
3938
3956
  function __replaceMeshQueueForTests(meshId, queue) {
3939
- BeadsDB.getInstance().transaction(() => {
3940
- BeadsDB.getInstance().replaceQueue(meshId, queue);
3957
+ MeshRuntimeStore.getInstance().transaction(() => {
3958
+ MeshRuntimeStore.getInstance().replaceQueue(meshId, queue);
3941
3959
  });
3942
3960
  }
3943
3961
  function __clearMeshQueueForTests(meshId) {
3944
- BeadsDB.getInstance().deleteQueue(meshId);
3962
+ MeshRuntimeStore.getInstance().deleteQueue(meshId);
3945
3963
  }
3946
3964
  function __clearDirectDispatchesForTests(meshId) {
3947
- BeadsDB.getInstance().deleteDirectDispatches(meshId);
3965
+ MeshRuntimeStore.getInstance().deleteDirectDispatches(meshId);
3948
3966
  }
3949
- function __resetBeadsDBForTests() {
3950
- BeadsDB.resetForTests();
3967
+ function __resetMeshRuntimeStoreForTests() {
3968
+ MeshRuntimeStore.resetForTests();
3951
3969
  }
3952
3970
  function insertDirectDispatch(meshId, data) {
3953
3971
  try {
3954
- BeadsDB.getInstance().insertDirectDispatch({ ...data, meshId });
3972
+ MeshRuntimeStore.getInstance().insertDirectDispatch({ ...data, meshId });
3955
3973
  } catch (e) {
3956
3974
  process.stderr.write(`[adhdev-mesh] insertDirectDispatch failed for task ${data.taskId}: ${e?.message || e}
3957
3975
  `);
@@ -3959,26 +3977,26 @@ function insertDirectDispatch(meshId, data) {
3959
3977
  }
3960
3978
  function getActiveDirectDispatches(meshId) {
3961
3979
  try {
3962
- return BeadsDB.getInstance().getActiveDirectDispatches(meshId);
3980
+ return MeshRuntimeStore.getInstance().getActiveDirectDispatches(meshId);
3963
3981
  } catch {
3964
3982
  return [];
3965
3983
  }
3966
3984
  }
3967
3985
  function updateDirectDispatchStatus(meshId, sessionId, status) {
3968
3986
  try {
3969
- BeadsDB.getInstance().updateDirectDispatchStatus(meshId, sessionId, status);
3987
+ MeshRuntimeStore.getInstance().updateDirectDispatchStatus(meshId, sessionId, status);
3970
3988
  } catch {
3971
3989
  }
3972
3990
  }
3973
3991
  function cleanupTerminalDirectDispatches(olderThanMs = 7 * 24 * 60 * 6e4) {
3974
3992
  try {
3975
- BeadsDB.getInstance().cleanupTerminalDirectDispatches(olderThanMs);
3993
+ MeshRuntimeStore.getInstance().cleanupTerminalDirectDispatches(olderThanMs);
3976
3994
  } catch {
3977
3995
  }
3978
3996
  }
3979
3997
  function markStaleDirectDispatches(meshId, olderThanMs = 60 * 6e4) {
3980
3998
  try {
3981
- BeadsDB.getInstance().markStaleDirectDispatches(meshId, olderThanMs);
3999
+ MeshRuntimeStore.getInstance().markStaleDirectDispatches(meshId, olderThanMs);
3982
4000
  } catch {
3983
4001
  }
3984
4002
  }
@@ -3987,7 +4005,7 @@ var init_mesh_work_queue = __esm({
3987
4005
  "src/mesh/mesh-work-queue.ts"() {
3988
4006
  "use strict";
3989
4007
  init_mesh_host_ownership();
3990
- init_beads_db();
4008
+ init_mesh_runtime_store();
3991
4009
  ACTIVE_MESH_QUEUE_STATUSES = ["pending", "assigned"];
3992
4010
  HISTORICAL_MESH_QUEUE_STATUSES = ["completed", "failed", "cancelled"];
3993
4011
  MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
@@ -4151,7 +4169,7 @@ __export(mesh_events_exports, {
4151
4169
  triggerMeshQueue: () => triggerMeshQueue,
4152
4170
  tryAssignQueueTask: () => tryAssignQueueTask
4153
4171
  });
4154
- import { appendFileSync as appendFileSync2, existsSync as existsSync13, readFileSync as readFileSync10, renameSync as renameSync3, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
4172
+ import { appendFileSync as appendFileSync2, existsSync as existsSync13, readFileSync as readFileSync10, renameSync as renameSync4, statSync as statSync5, unlinkSync as unlinkSync2, writeFileSync as writeFileSync6 } from "fs";
4155
4173
  import { join as join14 } from "path";
4156
4174
  function getCachedMeshByWorkspace(workspace) {
4157
4175
  const now = Date.now();
@@ -4169,7 +4187,7 @@ function __resetIdleAutoFastForwardForTests() {
4169
4187
  }
4170
4188
  function sweepExpiredRemoteIdleSessions() {
4171
4189
  try {
4172
- BeadsDB.getInstance().pruneExpiredRemoteIdleSessions();
4190
+ MeshRuntimeStore.getInstance().pruneExpiredRemoteIdleSessions();
4173
4191
  } catch {
4174
4192
  }
4175
4193
  }
@@ -4338,7 +4356,7 @@ function queuePendingMeshCoordinatorEvent(event) {
4338
4356
  function atomicDrainFile(path40) {
4339
4357
  const tmpPath = `${path40}.draining`;
4340
4358
  try {
4341
- renameSync3(path40, tmpPath);
4359
+ renameSync4(path40, tmpPath);
4342
4360
  } catch {
4343
4361
  return null;
4344
4362
  }
@@ -4445,14 +4463,14 @@ function shouldSuppressIntentionalCleanupStop(args) {
4445
4463
  }
4446
4464
  function hasFingerprintSeen(fingerprint) {
4447
4465
  try {
4448
- return BeadsDB.getInstance().hasCompletionFingerprint(fingerprint);
4466
+ return MeshRuntimeStore.getInstance().hasCompletionFingerprint(fingerprint);
4449
4467
  } catch {
4450
4468
  return false;
4451
4469
  }
4452
4470
  }
4453
4471
  function recordFingerprintSeen(fingerprint) {
4454
4472
  try {
4455
- const db = BeadsDB.getInstance();
4473
+ const db = MeshRuntimeStore.getInstance();
4456
4474
  db.recordCompletionFingerprint(fingerprint, RECENT_COMPLETION_FINGERPRINT_TTL_MS);
4457
4475
  db.sweepExpiredFingerprints();
4458
4476
  } catch {
@@ -5072,7 +5090,7 @@ async function triggerMeshQueue(components, meshId) {
5072
5090
  }
5073
5091
  let remoteSessions = [];
5074
5092
  try {
5075
- remoteSessions = BeadsDB.getInstance().getRemoteIdleSessions();
5093
+ remoteSessions = MeshRuntimeStore.getInstance().getRemoteIdleSessions();
5076
5094
  } catch {
5077
5095
  }
5078
5096
  for (const idle of remoteSessions) {
@@ -5082,7 +5100,7 @@ async function triggerMeshQueue(components, meshId) {
5082
5100
  const assigned = tryAssignQueueTask(components, meshId, idle.nodeId, idle.sessionId, idle.providerType);
5083
5101
  if (assigned) {
5084
5102
  try {
5085
- BeadsDB.getInstance().deleteRemoteIdleSession(idle.nodeId, idle.sessionId);
5103
+ MeshRuntimeStore.getInstance().deleteRemoteIdleSession(idle.nodeId, idle.sessionId);
5086
5104
  } catch {
5087
5105
  }
5088
5106
  }
@@ -5284,7 +5302,7 @@ function injectMeshSystemMessage(components, args) {
5284
5302
  if (intentionalCleanupStop) {
5285
5303
  if (eventSessionId && eventNodeId) {
5286
5304
  try {
5287
- BeadsDB.getInstance().deleteRemoteIdleSession(eventNodeId, eventSessionId);
5305
+ MeshRuntimeStore.getInstance().deleteRemoteIdleSession(eventNodeId, eventSessionId);
5288
5306
  } catch {
5289
5307
  }
5290
5308
  }
@@ -5452,14 +5470,14 @@ function injectMeshSystemMessage(components, args) {
5452
5470
  if (sessionId && nodeId && providerType) {
5453
5471
  sweepExpiredRemoteIdleSessions();
5454
5472
  try {
5455
- BeadsDB.getInstance().setRemoteIdleSession(nodeId, sessionId, providerType, Date.now() + REMOTE_IDLE_SESSION_TTL_MS);
5473
+ MeshRuntimeStore.getInstance().setRemoteIdleSession(nodeId, sessionId, providerType, Date.now() + REMOTE_IDLE_SESSION_TTL_MS);
5456
5474
  } catch {
5457
5475
  }
5458
5476
  setImmediate(() => {
5459
5477
  maybeAutoFastForwardIdleNode(components, { meshId: args.meshId, nodeId, sessionId, providerType }).finally(() => {
5460
5478
  try {
5461
5479
  const assigned = tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
5462
- if (assigned) BeadsDB.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5480
+ if (assigned) MeshRuntimeStore.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5463
5481
  } catch (e) {
5464
5482
  LOG.warn("MeshQueue", `Failed to assign idle queue task after maintenance for ${nodeId}: ${e?.message || e}`);
5465
5483
  }
@@ -5471,7 +5489,7 @@ function injectMeshSystemMessage(components, args) {
5471
5489
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
5472
5490
  if (sessionId && nodeId) {
5473
5491
  try {
5474
- BeadsDB.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5492
+ MeshRuntimeStore.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5475
5493
  } catch {
5476
5494
  }
5477
5495
  }
@@ -5483,7 +5501,7 @@ function injectMeshSystemMessage(components, args) {
5483
5501
  const nodeId = readNonEmptyString2(args.nodeId) || readNonEmptyString2(args.metadataEvent.meshNodeId);
5484
5502
  if (sessionId && nodeId) {
5485
5503
  try {
5486
- BeadsDB.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5504
+ MeshRuntimeStore.getInstance().deleteRemoteIdleSession(nodeId, sessionId);
5487
5505
  } catch {
5488
5506
  }
5489
5507
  }
@@ -5755,7 +5773,7 @@ var init_mesh_events = __esm({
5755
5773
  init_logger();
5756
5774
  init_mesh_ledger();
5757
5775
  init_mesh_work_queue();
5758
- init_beads_db();
5776
+ init_mesh_runtime_store();
5759
5777
  init_mesh_fast_forward();
5760
5778
  REMOTE_IDLE_SESSION_TTL_MS = 5 * 60 * 1e3;
5761
5779
  meshByWorkspaceCache = /* @__PURE__ */ new Map();
@@ -8706,11 +8724,12 @@ var init_cli_state_engine = __esm({
8706
8724
  }
8707
8725
  applyGenerating(ctx) {
8708
8726
  const { modal, parsedMessages, lastParsedAssistant, parsedStatus, prevStatus } = ctx;
8727
+ const noActiveTurn = !this.currentTurnScope;
8728
+ if (!this.isWaitingForResponse && noActiveTurn && !modal) return;
8709
8729
  this.clearIdleFinishCandidate("generating");
8710
8730
  this.cancelPendingIdleFinish("generating_signal_returned");
8711
8731
  const snap = this.transport.getSnapshot();
8712
8732
  const effectiveScreenText = snap.screenText || snap.accumulatedBuffer;
8713
- const noActiveTurn = !this.currentTurnScope;
8714
8733
  const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
8715
8734
  const parsedShowsLiveProgress = parsedStatus === "generating" && !!lastParsedAssistant;
8716
8735
  if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveProgress) return;
@@ -8970,7 +8989,25 @@ var init_cli_state_engine = __esm({
8970
8989
  const parsedStatus = typeof parsed?.status === "string" ? parsed.status.trim() : "";
8971
8990
  if (parsedStatus !== "idle") return true;
8972
8991
  if (parsed?.activeModal || parsed?.modal) return true;
8973
- return !this.parsedStatusHasFinalStandardAssistantMessage(parsed);
8992
+ const messages = Array.isArray(parsed?.messages) ? parsed.messages : [];
8993
+ let lastUserIdx = -1;
8994
+ for (let i = messages.length - 1; i >= 0; i--) {
8995
+ if (messages[i]?.role === "user") {
8996
+ lastUserIdx = i;
8997
+ break;
8998
+ }
8999
+ }
9000
+ if (lastUserIdx < 0) {
9001
+ if (messages.length === 0) return false;
9002
+ return !this.parsedStatusHasFinalStandardAssistantMessage(parsed);
9003
+ }
9004
+ const hasCurrentTurnAssistant = messages.slice(lastUserIdx + 1).some((m) => {
9005
+ if (!m || m.role !== "assistant") return false;
9006
+ if (typeof m.content !== "string" || !m.content.trim()) return false;
9007
+ const kind = typeof m.kind === "string" && m.kind.trim() ? m.kind.trim() : "standard";
9008
+ return kind === "standard" && m.meta?.streaming !== true;
9009
+ });
9010
+ return !hasCurrentTurnAssistant;
8974
9011
  }
8975
9012
  rescheduleTranscriptFinishCheck(reason) {
8976
9013
  this.clearIdleFinishCandidate(reason);
@@ -11432,14 +11469,19 @@ function buildClaudeInteractiveTuiAnswerSteps(prompt, response) {
11432
11469
  if (question.multiSelect) throw new Error("Claude TUI multi-select prompts are not supported yet");
11433
11470
  const answer = response.answers[question.questionId];
11434
11471
  if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
11435
- if (answer.freeformText) throw new Error("Claude TUI freeform answers are not supported yet");
11436
- if (answer.selectedLabels.length !== 1) throw new Error(`Expected one selected label for ${question.questionId}`);
11437
- const selectedIndex = question.options.findIndex((option) => option.label === answer.selectedLabels[0]);
11438
- if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${answer.selectedLabels[0]}`);
11439
- for (let i = 0; i < selectedIndex; i += 1) {
11440
- steps.push("\x1B[B");
11472
+ const freeformText = answer.freeformText?.trim() ?? "";
11473
+ if (freeformText) {
11474
+ const typeOptionIndex = question.options.findIndex((o) => /^Type something\.?$/i.test(o.label));
11475
+ const optionNumber = typeOptionIndex >= 0 ? typeOptionIndex + 1 : question.options.length;
11476
+ steps.push(String(optionNumber));
11477
+ for (const ch of freeformText) steps.push(ch);
11478
+ steps.push("\r");
11479
+ } else {
11480
+ if (answer.selectedLabels.length !== 1) throw new Error(`Expected one selected label for ${question.questionId}`);
11481
+ const selectedIndex = question.options.findIndex((option) => option.label === answer.selectedLabels[0]);
11482
+ if (selectedIndex < 0) throw new Error(`Unknown option for ${question.questionId}: ${answer.selectedLabels[0]}`);
11483
+ steps.push(String(selectedIndex + 1));
11441
11484
  }
11442
- steps.push("\r");
11443
11485
  }
11444
11486
  steps.push("\r");
11445
11487
  return steps;
@@ -19772,6 +19814,7 @@ function normalizeManagedStatus(status, opts) {
19772
19814
  if (hasApprovalButtons(opts?.activeModal)) return "waiting_approval";
19773
19815
  const normalized = String(status || "idle").trim().toLowerCase();
19774
19816
  if (normalized === "waiting_approval") return "waiting_approval";
19817
+ if (normalized === "waiting_choice") return "waiting_choice";
19775
19818
  if (WORKING_STATUSES.has(normalized)) return "generating";
19776
19819
  if (normalized === "error") return "error";
19777
19820
  if (normalized === "stopped") return "stopped";
@@ -25790,10 +25833,47 @@ function resolveSections(spec, lines) {
25790
25833
  for (const sec of spec.layout.sections) {
25791
25834
  let from = 0;
25792
25835
  let to = total;
25793
- if (sec.from_top !== void 0) {
25836
+ if (sec.anchor_regex !== void 0) {
25837
+ try {
25838
+ const re = new RegExp(sec.anchor_regex, sec.anchor_flags ?? "");
25839
+ const prevRe = sec.anchor_context?.prev !== void 0 ? new RegExp(sec.anchor_context.prev, sec.anchor_context.prev_flags ?? "") : null;
25840
+ const nextRe = sec.anchor_context?.next !== void 0 ? new RegExp(sec.anchor_context.next, sec.anchor_context.next_flags ?? "") : null;
25841
+ const matches = (i) => re.test(lines[i]) && (prevRe === null || i > 0 && prevRe.test(lines[i - 1])) && (nextRe === null || i < total - 1 && nextRe.test(lines[i + 1]));
25842
+ let idx = -1;
25843
+ if (sec.anchor_last) {
25844
+ for (let i = total - 1; i >= 0; i--) {
25845
+ if (matches(i)) {
25846
+ idx = i;
25847
+ break;
25848
+ }
25849
+ }
25850
+ } else {
25851
+ for (let i = 0; i < total; i++) {
25852
+ if (matches(i)) {
25853
+ idx = i;
25854
+ break;
25855
+ }
25856
+ }
25857
+ }
25858
+ if (idx !== -1) {
25859
+ from = idx;
25860
+ to = total;
25861
+ if (sec.until_regex !== void 0) {
25862
+ try {
25863
+ const ure = new RegExp(sec.until_regex, sec.until_regex_flags ?? "");
25864
+ const end = lines.findIndex((l, i) => i > idx && ure.test(l));
25865
+ if (end !== -1) to = end;
25866
+ } catch {
25867
+ }
25868
+ } else if (sec.lines !== void 0) {
25869
+ to = Math.min(total, from + sec.lines);
25870
+ }
25871
+ }
25872
+ } catch {
25873
+ }
25874
+ } else if (sec.from_top !== void 0) {
25794
25875
  from = resolveSize(sec.from_top, total);
25795
- }
25796
- if (sec.from_bottom !== void 0) {
25876
+ } else if (sec.from_bottom !== void 0) {
25797
25877
  const sz = resolveSize(sec.from_bottom, total);
25798
25878
  from = total - sz;
25799
25879
  to = total;
@@ -26111,6 +26191,9 @@ var SCHEMA = {
26111
26191
  "type": "string",
26112
26192
  "minLength": 1
26113
26193
  },
26194
+ "requiresFinalAssistantBeforeIdle": {
26195
+ "type": "boolean"
26196
+ },
26114
26197
  "debounce": {
26115
26198
  "type": "object",
26116
26199
  "additionalProperties": false,
@@ -26125,7 +26208,8 @@ var SCHEMA = {
26125
26208
  "section": { "type": "string", "minLength": 1 },
26126
26209
  "regex": { "type": "string", "minLength": 1 },
26127
26210
  "flags": { "type": "string" },
26128
- "hold_ms": { "type": "integer", "minimum": 0 }
26211
+ "hold_ms": { "type": "integer", "minimum": 0 },
26212
+ "force_after_ms": { "type": "integer", "minimum": 0 }
26129
26213
  }
26130
26214
  }
26131
26215
  }
@@ -26173,7 +26257,23 @@ var SCHEMA = {
26173
26257
  "type": "string"
26174
26258
  }
26175
26259
  }
26176
- }
26260
+ },
26261
+ "anchor_regex": { "type": "string", "minLength": 1 },
26262
+ "anchor_flags": { "type": "string" },
26263
+ "anchor_last": { "type": "boolean" },
26264
+ "anchor_context": {
26265
+ "type": "object",
26266
+ "additionalProperties": false,
26267
+ "properties": {
26268
+ "prev": { "type": "string" },
26269
+ "prev_flags": { "type": "string" },
26270
+ "next": { "type": "string" },
26271
+ "next_flags": { "type": "string" }
26272
+ }
26273
+ },
26274
+ "lines": { "type": "integer", "minimum": 1 },
26275
+ "until_regex": { "type": "string", "minLength": 1 },
26276
+ "until_regex_flags": { "type": "string" }
26177
26277
  }
26178
26278
  },
26179
26279
  "sectionRegex": {
@@ -26609,6 +26709,7 @@ function resolveSpecPath(providerDir) {
26609
26709
  }
26610
26710
 
26611
26711
  // src/providers/spec/driver.ts
26712
+ init_logger();
26612
26713
  var STARTUP_GRACE_MS = 2500;
26613
26714
  var BUSY_HOLD_MS = 6e3;
26614
26715
  var SUBMIT_DELAY_FLOOR_MS = 200;
@@ -26636,9 +26737,16 @@ function matchesCompletionIdleRule(spec, ev, screen) {
26636
26737
  return null;
26637
26738
  }
26638
26739
  }
26639
- function matchesCompletionIdleTargetState(spec, ev, screen) {
26740
+ function matchesCompletionIdleTargetState(spec, ev, screen, cursor) {
26640
26741
  const target = spec.states.find((state) => state.id === spec.default_state) ?? spec.states.find((state) => state.id === "idle");
26641
- if (!target?.when?.regex) return false;
26742
+ if (!target?.when) return false;
26743
+ const hasCursorGuard = target.when.cursor_row_min !== void 0 || target.when.cursor_row_max !== void 0 || target.when.cursor_col_min !== void 0 || target.when.cursor_col_max !== void 0;
26744
+ if (hasCursorGuard && cursor !== void 0) {
26745
+ const { cursor_row_min, cursor_row_max, cursor_col_min, cursor_col_max } = target.when;
26746
+ const cursorOk = (cursor_row_min === void 0 || cursor.row >= cursor_row_min) && (cursor_row_max === void 0 || cursor.row <= cursor_row_max) && (cursor_col_min === void 0 || cursor.col >= cursor_col_min) && (cursor_col_max === void 0 || cursor.col <= cursor_col_max);
26747
+ if (cursorOk) return true;
26748
+ }
26749
+ if (!target.when.regex) return false;
26642
26750
  const haystack = target.when.section ? ev.sections.find((section) => section.id === target.when.section)?.text ?? "" : screen;
26643
26751
  if (!haystack) return false;
26644
26752
  try {
@@ -26800,6 +26908,7 @@ var SpecDriver = class {
26800
26908
  if (this.busyExpiryTimer) clearTimeout(this.busyExpiryTimer);
26801
26909
  this.busyExpiryTimer = setTimeout(() => {
26802
26910
  this.busyExpiryTimer = null;
26911
+ LOG.debug("SpecDriver", `[${this.opts.specPath.split("/").slice(-3).join("/")}] busyExpiry fired holdMs=${holdMs}`);
26803
26912
  this.reevaluate();
26804
26913
  }, Math.max(holdMs + 50, 100));
26805
26914
  }
@@ -26824,11 +26933,16 @@ var SpecDriver = class {
26824
26933
  if (completionKey !== this.completionIdleKey) {
26825
26934
  this.completionIdleKey = completionKey;
26826
26935
  this.completionIdleFirstSeenAt = now;
26936
+ LOG.debug("SpecDriver", `[${this.opts.specPath.split("/").slice(-3).join("/")}] completion_idle_after matched: key="${completionKey}"`);
26827
26937
  }
26828
26938
  const holdMs = Math.max(0, completionIdleRule.hold_ms || 0);
26939
+ const forceAfterMs = typeof completionIdleRule.force_after_ms === "number" ? completionIdleRule.force_after_ms : null;
26829
26940
  const ageMs = now - this.completionIdleFirstSeenAt;
26830
26941
  if (ageMs >= holdMs) {
26831
- if (matchesCompletionIdleTargetState(this.spec, ev, screen)) {
26942
+ const targetMatches = matchesCompletionIdleTargetState(this.spec, ev, screen, cursor);
26943
+ const forced = !targetMatches && forceAfterMs !== null && ageMs >= holdMs + forceAfterMs;
26944
+ LOG.debug("SpecDriver", `[${this.opts.specPath.split("/").slice(-3).join("/")}] completion_idle_after hold expired ageMs=${ageMs} targetState=${targetMatches} forced=${forced} screenTail="${screen.split(/\r?\n/).slice(-3).join("\\n").slice(-200)}"`);
26945
+ if (targetMatches || forced) {
26832
26946
  const idle = this.spec.states.find((state) => state.id === this.spec.default_state) ?? this.spec.states.find((state) => state.id === "idle");
26833
26947
  evState = idle ? { id: idle.id, label: idle.label, title: null } : { id: "idle", label: "Ready", title: null };
26834
26948
  } else {
@@ -27969,16 +28083,19 @@ var CliProviderInstance = class {
27969
28083
  controlValues: this.controlValues
27970
28084
  });
27971
28085
  const activeChatStatus = parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : adapterStatus.status !== "idle" ? visibleStatus : suppressStaleParsedBusyStatus ? visibleStatus : parsedChatStatus || visibleStatus;
28086
+ const hasInteractivePrompt = !!this.activeInteractivePrompt;
28087
+ const finalStatus = hasInteractivePrompt ? "waiting_choice" : visibleStatus;
28088
+ const finalChatStatus = hasInteractivePrompt ? "waiting_choice" : activeChatStatus;
27972
28089
  return {
27973
28090
  type: this.type,
27974
28091
  name: this.provider.name,
27975
28092
  category: "cli",
27976
- status: visibleStatus,
28093
+ status: finalStatus,
27977
28094
  mode: this.presentationMode,
27978
28095
  activeChat: {
27979
28096
  id: activeChatId,
27980
28097
  title: parsedStatus?.title || dirName,
27981
- status: activeChatStatus,
28098
+ status: finalChatStatus,
27982
28099
  messages: statusMessages,
27983
28100
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
27984
28101
  activeInteractivePrompt: this.activeInteractivePrompt,
@@ -28449,6 +28566,7 @@ var CliProviderInstance = class {
28449
28566
  const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
28450
28567
  const finalAssistantEvidence = this.completionFinalAssistantEvidence(parsed?.messages);
28451
28568
  const allowMissingAssistantTimeout = !!(this.settings.meshNodeFor || this.settings.meshActiveTaskId || this.settings.launchedByCoordinator);
28569
+ LOG.debug("CLI", `[${this.type}] finalAssistantEvidence: present=${finalAssistantEvidence.present} source=${finalAssistantEvidence.source} adapterOwnsMessagesElsewhere=${adapterOwnsMessagesElsewhere} parsedStatus=${parsedStatus}`);
28452
28570
  if (!finalAssistantEvidence.present) {
28453
28571
  if (adapterOwnsMessagesElsewhere) {
28454
28572
  if (finalAssistantEvidence.source === "external-native") {
@@ -28457,6 +28575,10 @@ var CliProviderInstance = class {
28457
28575
  LOG.info("CLI", `[${this.type}] external transcript probe: msgCount=${probe.msgCount} lastRole=${probe.lastRole || "none"} lastKind=${probe.lastKind || "none"} contentLen=${probe.contentLen} sourceMtime=${probe.sourceMtimeMs ?? "unknown"} mtimeAge=${probe.mtimeAgeMs ?? "unknown"}ms`);
28458
28576
  pending.loggedTranscriptProbe = true;
28459
28577
  }
28578
+ LOG.debug("CLI", `[${this.type}] external-native probe result: lastRole=${probe?.lastRole} contentLen=${probe?.contentLen}`);
28579
+ if (probe?.lastRole === "assistant" && (probe.contentLen ?? 0) > 0) {
28580
+ return null;
28581
+ }
28460
28582
  if (this.type === "antigravity-cli") {
28461
28583
  return null;
28462
28584
  }
@@ -28466,6 +28588,7 @@ var CliProviderInstance = class {
28466
28588
  return { reason: "missing_final_assistant", terminal: true, allowTimeout: allowMissingAssistantTimeout };
28467
28589
  }
28468
28590
  } else {
28591
+ LOG.debug("CLI", `[${this.type}] missing_final_assistant (not ownsExternal) requiresFinalAssistant=${!!this.provider.requiresFinalAssistantBeforeIdle}`);
28469
28592
  return {
28470
28593
  reason: "missing_final_assistant",
28471
28594
  terminal: this.provider.requiresFinalAssistantBeforeIdle === true,
@@ -28499,6 +28622,7 @@ var CliProviderInstance = class {
28499
28622
  const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
28500
28623
  const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, latestStatus);
28501
28624
  const latestVisibleStatus = externalNativeFinal && isCliGeneratingLikeStatus(latestStatus.status) ? "idle" : latestAutoApproveActive ? "generating" : latestStatus.status;
28625
+ LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} externalNativeFinal=${!!externalNativeFinal} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
28502
28626
  if (latestVisibleStatus !== "idle") {
28503
28627
  LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed ${latestVisibleStatus})`);
28504
28628
  this.completedDebouncePending = null;
@@ -28509,6 +28633,7 @@ var CliProviderInstance = class {
28509
28633
  if (block2) {
28510
28634
  const blockReason = block2.reason;
28511
28635
  const waitedMs = Date.now() - pending.firstObservedAt;
28636
+ LOG.debug("CLI", `[${this.type}] finalization block: reason=${blockReason} terminal=${block2.terminal} waitedMs=${waitedMs} maxWait=${COMPLETED_FINALIZATION_MAX_WAIT_MS}`);
28512
28637
  if (block2.terminal && !block2.allowTimeout || waitedMs < COMPLETED_FINALIZATION_MAX_WAIT_MS) {
28513
28638
  if (pending.loggedBlockReason !== blockReason) {
28514
28639
  LOG.info("CLI", `[${this.type}] waiting to emit completed until transcript finalizes (${blockReason})`);
@@ -28623,9 +28748,13 @@ var CliProviderInstance = class {
28623
28748
  if (newStatus !== this.lastStatus) {
28624
28749
  LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
28625
28750
  if (this.lastStatus === "idle" && newStatus === "generating") {
28751
+ if (this.completedDebouncePending && this.generatingStartedAt === 0) {
28752
+ LOG.debug("CLI", `[${this.type}] ignoring post-completion PTY generating blip (generatingStartedAt=0)`);
28753
+ return;
28754
+ }
28626
28755
  this.suppressIdleHistoryReplay = false;
28627
28756
  if (this.completedDebouncePending) {
28628
- LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed generating)`);
28757
+ LOG.info("CLI", `[${this.type}] cancelled pending completed (resumed generating) generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse}`);
28629
28758
  if (this.completedDebounceTimer) {
28630
28759
  clearTimeout(this.completedDebounceTimer);
28631
28760
  this.completedDebounceTimer = null;
@@ -28723,7 +28852,10 @@ var CliProviderInstance = class {
28723
28852
  firstObservedAt: now,
28724
28853
  previousStatus: this.lastStatus
28725
28854
  };
28726
- this.scheduleCompletedDebounceFlush(3e3);
28855
+ const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
28856
+ const flushDelay = ownsExternalHistory ? 0 : 3e3;
28857
+ LOG.debug("CLI", `[${this.type}] set completedDebouncePending duration=${duration}s ownsExternalHistory=${ownsExternalHistory} flushDelay=${flushDelay}ms generatingStartedAt=${this.generatingStartedAt}`);
28858
+ this.scheduleCompletedDebounceFlush(flushDelay);
28727
28859
  }
28728
28860
  } else if (newStatus === "idle" && this.lastStatus === "starting") {
28729
28861
  this.pushEvent({ event: "agent:ready", chatTitle, timestamp: now });