@adhdev/daemon-core 0.9.82-rc.223 → 0.9.82-rc.225

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7693,7 +7693,9 @@ var init_mesh_events_coordinator = __esm({
7693
7693
  "monitor:long_generating",
7694
7694
  "refine:accepted",
7695
7695
  "refine:completed",
7696
- "refine:failed"
7696
+ "refine:failed",
7697
+ "worktree_bootstrap_complete",
7698
+ "worktree_bootstrap_failed"
7697
7699
  ]);
7698
7700
  EVENT_TO_LEDGER_KIND = {
7699
7701
  "agent:generating_completed": "task_completed",
@@ -25116,7 +25118,9 @@ async function handleReadChat(h, args) {
25116
25118
  const historyLimit = normalizeReadChatTailLimit(args);
25117
25119
  try {
25118
25120
  const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h);
25119
- const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
25121
+ const targetSid = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
25122
+ const registrySessionWorkspace = targetSid ? h.ctx?.sessionRegistry?.get?.(targetSid)?.workspace : void 0;
25123
+ const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : typeof registrySessionWorkspace === "string" ? registrySessionWorkspace : void 0;
25120
25124
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
25121
25125
  const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory);
25122
25126
  const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
@@ -31339,7 +31343,8 @@ var CliProviderInstance = class {
31339
31343
  const rawStatus = adapterStatus.status;
31340
31344
  const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
31341
31345
  const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
31342
- const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive ? "generating" : rawStatus;
31346
+ const autoApproveHoldIdle = this.autoApproveBusy && rawStatus === "idle";
31347
+ const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive || autoApproveHoldIdle ? "generating" : rawStatus;
31343
31348
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
31344
31349
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
31345
31350
  const partial = this.adapter.getPartialResponse();
@@ -39671,7 +39676,12 @@ function applyInlineMeshBranchConvergence(mesh, node, status) {
39671
39676
  }
39672
39677
  }
39673
39678
  function summarizeInlineMeshBranchConvergence(nodes) {
39674
- const followUps = nodes.filter((node) => readObjectRecord(node.branchConvergence).needsConvergence === true).map((node) => {
39679
+ const followUps = nodes.filter((node) => {
39680
+ if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
39681
+ const workspace = typeof node.workspace === "string" ? node.workspace : "";
39682
+ if (workspace && !fs23.existsSync(workspace)) return false;
39683
+ return true;
39684
+ }).map((node) => {
39675
39685
  const convergence = readObjectRecord(node.branchConvergence);
39676
39686
  return {
39677
39687
  nodeId: node.nodeId,
@@ -41182,7 +41192,66 @@ var DaemonCommandRouter = class {
41182
41192
  } catch (e) {
41183
41193
  const message = String(e?.message || e || "worktree cleanup failed");
41184
41194
  const dirty = message.includes("dirty worktree") || message.includes("local changes");
41185
- const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
41195
+ const isSubmoduleGuard = /working trees containing submodules cannot be moved or removed/i.test(message);
41196
+ const submoduleForceBlocked = isSubmoduleGuard && !forceFallbackConvergence.allow;
41197
+ if (isSubmoduleGuard && forceFallbackConvergence.allow) {
41198
+ const { execFile: execFile4 } = await import("child_process");
41199
+ const { promisify: promisify7 } = await import("util");
41200
+ const execFileAsync3 = promisify7(execFile4);
41201
+ const GIT_TIMEOUT_CLEANUP = 3e4;
41202
+ const GIT_MAX_BUFFER_CLEANUP = 4 * 1024 * 1024;
41203
+ try {
41204
+ await execFileAsync3("git", ["-C", workspace, "submodule", "deinit", "--all", "-f"], {
41205
+ encoding: "utf8",
41206
+ timeout: GIT_TIMEOUT_CLEANUP,
41207
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41208
+ windowsHide: true
41209
+ });
41210
+ await execFileAsync3("git", ["worktree", "remove", "--force", workspace], {
41211
+ cwd: repoRoot,
41212
+ encoding: "utf8",
41213
+ timeout: GIT_TIMEOUT_CLEANUP,
41214
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41215
+ windowsHide: true
41216
+ });
41217
+ return {
41218
+ success: true,
41219
+ removedPath: workspace,
41220
+ repoRoot,
41221
+ fallback: "git_worktree_remove_submodule_deinit",
41222
+ forced: true,
41223
+ reason: "working_trees_containing_submodules",
41224
+ convergence: forceFallbackConvergence
41225
+ };
41226
+ } catch (deinitError) {
41227
+ try {
41228
+ fs23.rmSync(workspace, { recursive: true, force: true });
41229
+ await execFileAsync3("git", ["worktree", "prune"], {
41230
+ cwd: repoRoot,
41231
+ encoding: "utf8",
41232
+ timeout: GIT_TIMEOUT_CLEANUP,
41233
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
41234
+ windowsHide: true
41235
+ });
41236
+ return {
41237
+ success: true,
41238
+ removedPath: workspace,
41239
+ repoRoot,
41240
+ fallback: "fs_rm_worktree_prune",
41241
+ forced: true,
41242
+ reason: "working_trees_containing_submodules",
41243
+ convergence: forceFallbackConvergence
41244
+ };
41245
+ } catch (rmError) {
41246
+ return {
41247
+ success: false,
41248
+ code: "mesh_worktree_cleanup_failed",
41249
+ error: `All removal fallbacks exhausted. deinit+remove: ${deinitError?.message || deinitError}; rmSync+prune: ${rmError?.message || rmError}`,
41250
+ recoveryHint: "Manually remove the worktree directory and run git worktree prune from the source repo."
41251
+ };
41252
+ }
41253
+ }
41254
+ }
41186
41255
  return {
41187
41256
  success: false,
41188
41257
  code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
@@ -41194,9 +41263,13 @@ var DaemonCommandRouter = class {
41194
41263
  }
41195
41264
  async getWorktreeForceCleanupConvergence(args) {
41196
41265
  const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
41197
- if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
41266
+ if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate" || metadataStatus === "merged_pushed") {
41198
41267
  return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
41199
41268
  }
41269
+ const refinedConvergence = typeof args.node?.refineState?.finalBranchConvergenceState?.status === "string" ? args.node.refineState.finalBranchConvergenceState.status : typeof args.node?.lastRefineResult?.finalBranchConvergenceState?.status === "string" ? args.node.lastRefineResult.finalBranchConvergenceState.status : "";
41270
+ if (refinedConvergence === "merged_pushed" || refinedConvergence === "merged_to_main") {
41271
+ return { allow: true, status: refinedConvergence, source: "node_refine_state" };
41272
+ }
41200
41273
  const { execFile: execFile4 } = await import("child_process");
41201
41274
  const { promisify: promisify7 } = await import("util");
41202
41275
  const execFileAsync3 = promisify7(execFile4);
@@ -41682,11 +41755,24 @@ var DaemonCommandRouter = class {
41682
41755
  if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
41683
41756
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
41684
41757
  const baseBranch = baseBranchStdout.trim();
41685
- const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41758
+ let fetchWarning;
41759
+ try {
41760
+ await execFileAsync3("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
41761
+ } catch (e) {
41762
+ fetchWarning = `git fetch origin ${baseBranch} failed (proceeding with local HEAD): ${e?.message}`;
41763
+ }
41764
+ let baseHeadRaw;
41765
+ try {
41766
+ const { stdout } = await execFileAsync3("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
41767
+ baseHeadRaw = stdout.trim();
41768
+ } catch {
41769
+ const { stdout: localHead } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41770
+ baseHeadRaw = localHead.trim();
41771
+ }
41686
41772
  const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
41687
- const baseHead = baseHeadStdout.trim();
41773
+ const baseHead = baseHeadRaw;
41688
41774
  let branchHead = branchHeadStdout.trim();
41689
- recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
41775
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead, ...fetchWarning ? { fetchWarning } : {} });
41690
41776
  const validationStarted = Date.now();
41691
41777
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace, {
41692
41778
  // M2-2: consume the node's persisted bootstrap state; persist re-runs.
@@ -41705,11 +41791,25 @@ var DaemonCommandRouter = class {
41705
41791
  { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
41706
41792
  );
41707
41793
  if (validationSummary.status === "failed") {
41794
+ const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
41795
+ const buildValidationFailedError = () => {
41796
+ const base = validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.";
41797
+ if (!firstFailedCmd) return base;
41798
+ const cmdName = typeof firstFailedCmd.displayCommand === "string" ? firstFailedCmd.displayCommand : typeof firstFailedCmd.command === "string" ? [firstFailedCmd.command, ...Array.isArray(firstFailedCmd.args) ? firstFailedCmd.args : []].join(" ").trim() : typeof firstFailedCmd.cmd === "string" ? firstFailedCmd.cmd : "";
41799
+ const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
41800
+ const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
41801
+ return [
41802
+ base,
41803
+ cmdName ? `First failing command: ${cmdName}` : "",
41804
+ tail ? `Output (tail):
41805
+ ${tail}` : ""
41806
+ ].filter(Boolean).join("\n");
41807
+ };
41708
41808
  return {
41709
41809
  success: false,
41710
41810
  code: validationSummary.failureCode || "validation_failed",
41711
41811
  convergenceStatus: "blocked_review",
41712
- error: validationSummary.failureCode === "missing_dependencies" ? "Refinery validation dependencies are missing; merge/refine was not attempted. Configure validation.bootstrapCommands if Refinery should bootstrap dependencies before validation." : validationSummary.failureCode === "dependency_bootstrap_failed" ? "Refinery dependency/bootstrap command failed; merge/refine was not attempted." : "Refinery validation gate failed; merge/refine was not attempted.",
41812
+ error: buildValidationFailedError(),
41713
41813
  branch,
41714
41814
  into: baseBranch,
41715
41815
  validationSummary,
@@ -42311,13 +42411,54 @@ var DaemonCommandRouter = class {
42311
42411
  this.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
42312
42412
  return { success: true };
42313
42413
  }
42314
- case "launch_cli":
42414
+ case "launch_cli": {
42415
+ const launchResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42416
+ const meshNodeId = readStringValue(args?.settings?.meshNodeId);
42417
+ const meshId = readStringValue(args?.settings?.meshNodeFor);
42418
+ if (meshNodeId && meshId && launchResult?.success !== false) {
42419
+ try {
42420
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42421
+ const meshObj = getMesh2(meshId) ?? this.getCachedInlineMesh(meshId);
42422
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === meshNodeId || n.nodeId === meshNodeId) : void 0;
42423
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42424
+ if (bootstrapStatus === "running") {
42425
+ return { success: true, ...launchResult, bootstrapPending: true };
42426
+ }
42427
+ } catch {
42428
+ }
42429
+ }
42430
+ return launchResult;
42431
+ }
42315
42432
  case "stop_cli":
42316
42433
  case "set_cli_view_mode":
42317
- case "record_provider_pty":
42318
- case "agent_command": {
42434
+ case "record_provider_pty": {
42319
42435
  return this.deps.cliManager.handleCliCommand(cmd, args);
42320
42436
  }
42437
+ case "agent_command": {
42438
+ const agentResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42439
+ const meshCtx = args?.meshContext;
42440
+ const dispatchNodeId = readStringValue(meshCtx?.nodeId);
42441
+ const dispatchMeshId = readStringValue(meshCtx?.meshId);
42442
+ if (dispatchNodeId && dispatchMeshId && agentResult?.success !== false) {
42443
+ try {
42444
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42445
+ const meshObj = getMesh2(dispatchMeshId) ?? this.getCachedInlineMesh(dispatchMeshId);
42446
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === dispatchNodeId || n.nodeId === dispatchNodeId) : void 0;
42447
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42448
+ if (bootstrapStatus === "running") {
42449
+ return {
42450
+ success: true,
42451
+ ...agentResult,
42452
+ dispatchAcknowledgementRisk: true,
42453
+ dispatchAcknowledgementRiskReason: "bootstrap_still_running",
42454
+ nextAction: "Wait for worktree_bootstrap_complete event before dispatching work to this node."
42455
+ };
42456
+ }
42457
+ } catch {
42458
+ }
42459
+ }
42460
+ return agentResult;
42461
+ }
42321
42462
  // ─── Logs ───
42322
42463
  case "get_logs": {
42323
42464
  const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
@@ -43702,9 +43843,11 @@ var DaemonCommandRouter = class {
43702
43843
  if (meshRecord?.inline) {
43703
43844
  removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
43704
43845
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43846
+ if (!removed && !node) removed = true;
43705
43847
  } else {
43706
43848
  const { removeNode: removeNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
43707
43849
  removed = removeNode2(meshId, nodeId);
43850
+ if (!removed && !node) removed = true;
43708
43851
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43709
43852
  }
43710
43853
  if (removed) {
@@ -43888,8 +44031,45 @@ var DaemonCommandRouter = class {
43888
44031
  setupPromise.then((value) => ({ completed: true, value })),
43889
44032
  new Promise((resolve23) => setTimeout(() => resolve23({ completed: false }), setupWaitMs))
43890
44033
  ]);
44034
+ const emitBootstrapEvent = (eventStatus2, bootstrapState2, startedAtMs, extraPayload) => {
44035
+ try {
44036
+ const durationMs = Date.now() - startedAtMs;
44037
+ const event = `worktree_${eventStatus2}`;
44038
+ const metadataEvent = {
44039
+ source: "clone_mesh_node_bootstrap",
44040
+ nodeId: node.id,
44041
+ status: eventStatus2,
44042
+ worktreePath: result.worktreePath,
44043
+ durationMs,
44044
+ bootstrapStatus: bootstrapState2.status,
44045
+ ...bootstrapState2.error ? { error: bootstrapState2.error } : {},
44046
+ ...bootstrapState2.exitCode !== void 0 ? { exitCode: bootstrapState2.exitCode } : {},
44047
+ ...extraPayload || {}
44048
+ };
44049
+ if (typeof this.deps.instanceManager?.getByCategory === "function") {
44050
+ const forwarded = handleMeshForwardEvent(
44051
+ { instanceManager: this.deps.instanceManager },
44052
+ { event, meshId, nodeId: node.id, workspace: result.worktreePath, metadataEvent }
44053
+ );
44054
+ if (forwarded?.success === true) return;
44055
+ }
44056
+ queuePendingMeshCoordinatorEvent({
44057
+ event,
44058
+ meshId,
44059
+ nodeLabel: node.id,
44060
+ nodeId: node.id,
44061
+ workspace: result.worktreePath,
44062
+ metadataEvent,
44063
+ queuedAt: Date.now()
44064
+ });
44065
+ } catch {
44066
+ }
44067
+ };
44068
+ const bootstrapStartedMs = Date.now();
43891
44069
  if (!setupResult.completed) {
43892
- setupPromise.catch((error) => {
44070
+ setupPromise.then(({ bootstrapState: bootstrapState2 }) => {
44071
+ emitBootstrapEvent("bootstrap_complete", bootstrapState2, bootstrapStartedMs);
44072
+ }).catch((error) => {
43893
44073
  const failedState = {
43894
44074
  ...runningBootstrapState,
43895
44075
  status: "failed",
@@ -43898,6 +44078,7 @@ var DaemonCommandRouter = class {
43898
44078
  };
43899
44079
  void persistWorktreeSetupState(failedState);
43900
44080
  void appendCloneLedger(false, failedState);
44081
+ emitBootstrapEvent("bootstrap_failed", failedState, bootstrapStartedMs, { error: error?.message || String(error) });
43901
44082
  });
43902
44083
  return {
43903
44084
  success: true,
@@ -43915,6 +44096,7 @@ var DaemonCommandRouter = class {
43915
44096
  };
43916
44097
  }
43917
44098
  const { submodulesInitialized, bootstrapState } = setupResult.value;
44099
+ emitBootstrapEvent("bootstrap_complete", bootstrapState, bootstrapStartedMs);
43918
44100
  return {
43919
44101
  success: true,
43920
44102
  node,
@@ -43982,7 +44164,34 @@ var DaemonCommandRouter = class {
43982
44164
  const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue trigger");
43983
44165
  if (ownerFailure) return ownerFailure;
43984
44166
  try {
43985
- const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
44167
+ const { triggerMeshQueue: triggerMeshQueue2, tryAssignQueueTask: tryAssignQueueTask2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
44168
+ const preferredNodeId = typeof args?.preferredNodeId === "string" ? args.preferredNodeId.trim() : "";
44169
+ if (preferredNodeId) {
44170
+ const cliInstances = this.deps.instanceManager.getByCategory("cli");
44171
+ const sorted = [...cliInstances].sort((a, b) => {
44172
+ const aSettings = a.getState().settings || {};
44173
+ const bSettings = b.getState().settings || {};
44174
+ const aNode = readStringValue(aSettings.meshNodeId, aSettings.nodeId);
44175
+ const bNode = readStringValue(bSettings.meshNodeId, bSettings.nodeId);
44176
+ return (aNode === preferredNodeId ? -1 : 0) - (bNode === preferredNodeId ? -1 : 0);
44177
+ });
44178
+ for (const inst of sorted) {
44179
+ const state = inst.getState();
44180
+ const settings = state.settings || {};
44181
+ const nodeId = readStringValue(settings.meshNodeId, settings.nodeId);
44182
+ if (!nodeId || nodeId !== preferredNodeId) continue;
44183
+ const meshNodeFor = readStringValue(settings.meshNodeFor);
44184
+ if (meshNodeFor !== meshId) continue;
44185
+ const status = (readStringValue(state.status) || "").toLowerCase();
44186
+ if (status !== "idle") continue;
44187
+ const sessionId = typeof state.instanceId === "string" ? state.instanceId : "";
44188
+ const providerType = readStringValue(state.type, settings.providerType) || "";
44189
+ if (sessionId && providerType) {
44190
+ tryAssignQueueTask2(this.deps, meshId, nodeId, sessionId, providerType);
44191
+ break;
44192
+ }
44193
+ }
44194
+ }
43986
44195
  const trigger = await triggerMeshQueue2(this.deps, meshId);
43987
44196
  return { success: true, trigger };
43988
44197
  } catch (e) {