@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.mjs CHANGED
@@ -7686,7 +7686,9 @@ var init_mesh_events_coordinator = __esm({
7686
7686
  "monitor:long_generating",
7687
7687
  "refine:accepted",
7688
7688
  "refine:completed",
7689
- "refine:failed"
7689
+ "refine:failed",
7690
+ "worktree_bootstrap_complete",
7691
+ "worktree_bootstrap_failed"
7690
7692
  ]);
7691
7693
  EVENT_TO_LEDGER_KIND = {
7692
7694
  "agent:generating_completed": "task_completed",
@@ -24784,7 +24786,9 @@ async function handleReadChat(h, args) {
24784
24786
  const historyLimit = normalizeReadChatTailLimit(args);
24785
24787
  try {
24786
24788
  const agentStr = provider?.type || args?.agentType || getCurrentProviderType(h);
24787
- const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : void 0;
24789
+ const targetSid = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : "";
24790
+ const registrySessionWorkspace = targetSid ? h.ctx?.sessionRegistry?.get?.(targetSid)?.workspace : void 0;
24791
+ const workspace = typeof h.currentSession?.workspace === "string" ? h.currentSession.workspace : typeof registrySessionWorkspace === "string" ? registrySessionWorkspace : void 0;
24788
24792
  const intendedWorkspace = typeof args?.workspace === "string" ? args.workspace : void 0;
24789
24793
  const supportsNative = supportsCliNativeTranscript(agentStr, provider) && isNativeSourceCanonicalHistory(provider?.nativeHistory);
24790
24794
  const history = supportsNative ? readCliProviderNativeHistory(agentStr, {
@@ -31007,7 +31011,8 @@ var CliProviderInstance = class {
31007
31011
  const rawStatus = adapterStatus.status;
31008
31012
  const autoApproveActive = this.maybeAutoApproveStatus(adapterStatus, now);
31009
31013
  const externalNativeFinal = this.getExternalNativeFinalReconciliation(void 0, adapterStatus);
31010
- const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive ? "generating" : rawStatus;
31014
+ const autoApproveHoldIdle = this.autoApproveBusy && rawStatus === "idle";
31015
+ const newStatus = externalNativeFinal && isCliGeneratingLikeStatus(rawStatus) ? "idle" : autoApproveActive || autoApproveHoldIdle ? "generating" : rawStatus;
31011
31016
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
31012
31017
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
31013
31018
  const partial = this.adapter.getPartialResponse();
@@ -39344,7 +39349,12 @@ function applyInlineMeshBranchConvergence(mesh, node, status) {
39344
39349
  }
39345
39350
  }
39346
39351
  function summarizeInlineMeshBranchConvergence(nodes) {
39347
- const followUps = nodes.filter((node) => readObjectRecord(node.branchConvergence).needsConvergence === true).map((node) => {
39352
+ const followUps = nodes.filter((node) => {
39353
+ if (readObjectRecord(node.branchConvergence).needsConvergence !== true) return false;
39354
+ const workspace = typeof node.workspace === "string" ? node.workspace : "";
39355
+ if (workspace && !fs23.existsSync(workspace)) return false;
39356
+ return true;
39357
+ }).map((node) => {
39348
39358
  const convergence = readObjectRecord(node.branchConvergence);
39349
39359
  return {
39350
39360
  nodeId: node.nodeId,
@@ -40855,7 +40865,66 @@ var DaemonCommandRouter = class {
40855
40865
  } catch (e) {
40856
40866
  const message = String(e?.message || e || "worktree cleanup failed");
40857
40867
  const dirty = message.includes("dirty worktree") || message.includes("local changes");
40858
- const submoduleForceBlocked = /working trees containing submodules cannot be moved or removed/i.test(message) && !forceFallbackConvergence.allow;
40868
+ const isSubmoduleGuard = /working trees containing submodules cannot be moved or removed/i.test(message);
40869
+ const submoduleForceBlocked = isSubmoduleGuard && !forceFallbackConvergence.allow;
40870
+ if (isSubmoduleGuard && forceFallbackConvergence.allow) {
40871
+ const { execFile: execFile4 } = await import("child_process");
40872
+ const { promisify: promisify7 } = await import("util");
40873
+ const execFileAsync3 = promisify7(execFile4);
40874
+ const GIT_TIMEOUT_CLEANUP = 3e4;
40875
+ const GIT_MAX_BUFFER_CLEANUP = 4 * 1024 * 1024;
40876
+ try {
40877
+ await execFileAsync3("git", ["-C", workspace, "submodule", "deinit", "--all", "-f"], {
40878
+ encoding: "utf8",
40879
+ timeout: GIT_TIMEOUT_CLEANUP,
40880
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
40881
+ windowsHide: true
40882
+ });
40883
+ await execFileAsync3("git", ["worktree", "remove", "--force", workspace], {
40884
+ cwd: repoRoot,
40885
+ encoding: "utf8",
40886
+ timeout: GIT_TIMEOUT_CLEANUP,
40887
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
40888
+ windowsHide: true
40889
+ });
40890
+ return {
40891
+ success: true,
40892
+ removedPath: workspace,
40893
+ repoRoot,
40894
+ fallback: "git_worktree_remove_submodule_deinit",
40895
+ forced: true,
40896
+ reason: "working_trees_containing_submodules",
40897
+ convergence: forceFallbackConvergence
40898
+ };
40899
+ } catch (deinitError) {
40900
+ try {
40901
+ fs23.rmSync(workspace, { recursive: true, force: true });
40902
+ await execFileAsync3("git", ["worktree", "prune"], {
40903
+ cwd: repoRoot,
40904
+ encoding: "utf8",
40905
+ timeout: GIT_TIMEOUT_CLEANUP,
40906
+ maxBuffer: GIT_MAX_BUFFER_CLEANUP,
40907
+ windowsHide: true
40908
+ });
40909
+ return {
40910
+ success: true,
40911
+ removedPath: workspace,
40912
+ repoRoot,
40913
+ fallback: "fs_rm_worktree_prune",
40914
+ forced: true,
40915
+ reason: "working_trees_containing_submodules",
40916
+ convergence: forceFallbackConvergence
40917
+ };
40918
+ } catch (rmError) {
40919
+ return {
40920
+ success: false,
40921
+ code: "mesh_worktree_cleanup_failed",
40922
+ error: `All removal fallbacks exhausted. deinit+remove: ${deinitError?.message || deinitError}; rmSync+prune: ${rmError?.message || rmError}`,
40923
+ recoveryHint: "Manually remove the worktree directory and run git worktree prune from the source repo."
40924
+ };
40925
+ }
40926
+ }
40927
+ }
40859
40928
  return {
40860
40929
  success: false,
40861
40930
  code: dirty ? "mesh_worktree_cleanup_dirty" : submoduleForceBlocked ? "mesh_worktree_cleanup_force_fallback_blocked" : "mesh_worktree_cleanup_failed",
@@ -40867,9 +40936,13 @@ var DaemonCommandRouter = class {
40867
40936
  }
40868
40937
  async getWorktreeForceCleanupConvergence(args) {
40869
40938
  const metadataStatus = typeof args.node?.branchConvergence?.status === "string" ? args.node.branchConvergence.status : "";
40870
- if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate") {
40939
+ if (metadataStatus === "merged_to_main" || metadataStatus === "cleanup_candidate" || metadataStatus === "merged_pushed") {
40871
40940
  return { allow: true, status: metadataStatus, source: "node_branch_convergence" };
40872
40941
  }
40942
+ 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 : "";
40943
+ if (refinedConvergence === "merged_pushed" || refinedConvergence === "merged_to_main") {
40944
+ return { allow: true, status: refinedConvergence, source: "node_refine_state" };
40945
+ }
40873
40946
  const { execFile: execFile4 } = await import("child_process");
40874
40947
  const { promisify: promisify7 } = await import("util");
40875
40948
  const execFileAsync3 = promisify7(execFile4);
@@ -41355,11 +41428,24 @@ var DaemonCommandRouter = class {
41355
41428
  if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
41356
41429
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
41357
41430
  const baseBranch = baseBranchStdout.trim();
41358
- const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41431
+ let fetchWarning;
41432
+ try {
41433
+ await execFileAsync3("git", ["fetch", "origin", baseBranch], { cwd: repoRoot, encoding: "utf8" });
41434
+ } catch (e) {
41435
+ fetchWarning = `git fetch origin ${baseBranch} failed (proceeding with local HEAD): ${e?.message}`;
41436
+ }
41437
+ let baseHeadRaw;
41438
+ try {
41439
+ const { stdout } = await execFileAsync3("git", ["rev-parse", `origin/${baseBranch}`], { cwd: repoRoot, encoding: "utf8" });
41440
+ baseHeadRaw = stdout.trim();
41441
+ } catch {
41442
+ const { stdout: localHead } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
41443
+ baseHeadRaw = localHead.trim();
41444
+ }
41359
41445
  const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
41360
- const baseHead = baseHeadStdout.trim();
41446
+ const baseHead = baseHeadRaw;
41361
41447
  let branchHead = branchHeadStdout.trim();
41362
- recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
41448
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead, ...fetchWarning ? { fetchWarning } : {} });
41363
41449
  const validationStarted = Date.now();
41364
41450
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace, {
41365
41451
  // M2-2: consume the node's persisted bootstrap state; persist re-runs.
@@ -41378,11 +41464,25 @@ var DaemonCommandRouter = class {
41378
41464
  { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
41379
41465
  );
41380
41466
  if (validationSummary.status === "failed") {
41467
+ const firstFailedCmd = Array.isArray(validationSummary.commandsRun) ? validationSummary.commandsRun.find((c) => c.success === false) : void 0;
41468
+ const buildValidationFailedError = () => {
41469
+ 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.";
41470
+ if (!firstFailedCmd) return base;
41471
+ 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 : "";
41472
+ const rawOutput = [firstFailedCmd.stdout, firstFailedCmd.stderr, firstFailedCmd.output].filter((s) => typeof s === "string" && s.length > 0).join("\n");
41473
+ const tail = rawOutput.length > 800 ? rawOutput.slice(-800) : rawOutput;
41474
+ return [
41475
+ base,
41476
+ cmdName ? `First failing command: ${cmdName}` : "",
41477
+ tail ? `Output (tail):
41478
+ ${tail}` : ""
41479
+ ].filter(Boolean).join("\n");
41480
+ };
41381
41481
  return {
41382
41482
  success: false,
41383
41483
  code: validationSummary.failureCode || "validation_failed",
41384
41484
  convergenceStatus: "blocked_review",
41385
- 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.",
41485
+ error: buildValidationFailedError(),
41386
41486
  branch,
41387
41487
  into: baseBranch,
41388
41488
  validationSummary,
@@ -41984,13 +42084,54 @@ var DaemonCommandRouter = class {
41984
42084
  this.deps.instanceManager.sendEvent(sessionId, "interactive_prompt_response", response);
41985
42085
  return { success: true };
41986
42086
  }
41987
- case "launch_cli":
42087
+ case "launch_cli": {
42088
+ const launchResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42089
+ const meshNodeId = readStringValue(args?.settings?.meshNodeId);
42090
+ const meshId = readStringValue(args?.settings?.meshNodeFor);
42091
+ if (meshNodeId && meshId && launchResult?.success !== false) {
42092
+ try {
42093
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42094
+ const meshObj = getMesh2(meshId) ?? this.getCachedInlineMesh(meshId);
42095
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === meshNodeId || n.nodeId === meshNodeId) : void 0;
42096
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42097
+ if (bootstrapStatus === "running") {
42098
+ return { success: true, ...launchResult, bootstrapPending: true };
42099
+ }
42100
+ } catch {
42101
+ }
42102
+ }
42103
+ return launchResult;
42104
+ }
41988
42105
  case "stop_cli":
41989
42106
  case "set_cli_view_mode":
41990
- case "record_provider_pty":
41991
- case "agent_command": {
42107
+ case "record_provider_pty": {
41992
42108
  return this.deps.cliManager.handleCliCommand(cmd, args);
41993
42109
  }
42110
+ case "agent_command": {
42111
+ const agentResult = await this.deps.cliManager.handleCliCommand(cmd, args);
42112
+ const meshCtx = args?.meshContext;
42113
+ const dispatchNodeId = readStringValue(meshCtx?.nodeId);
42114
+ const dispatchMeshId = readStringValue(meshCtx?.meshId);
42115
+ if (dispatchNodeId && dispatchMeshId && agentResult?.success !== false) {
42116
+ try {
42117
+ const { getMesh: getMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
42118
+ const meshObj = getMesh2(dispatchMeshId) ?? this.getCachedInlineMesh(dispatchMeshId);
42119
+ const nodeObj = Array.isArray(meshObj?.nodes) ? meshObj.nodes.find((n) => n.id === dispatchNodeId || n.nodeId === dispatchNodeId) : void 0;
42120
+ const bootstrapStatus = readStringValue(nodeObj?.worktreeBootstrap?.status);
42121
+ if (bootstrapStatus === "running") {
42122
+ return {
42123
+ success: true,
42124
+ ...agentResult,
42125
+ dispatchAcknowledgementRisk: true,
42126
+ dispatchAcknowledgementRiskReason: "bootstrap_still_running",
42127
+ nextAction: "Wait for worktree_bootstrap_complete event before dispatching work to this node."
42128
+ };
42129
+ }
42130
+ } catch {
42131
+ }
42132
+ }
42133
+ return agentResult;
42134
+ }
41994
42135
  // ─── Logs ───
41995
42136
  case "get_logs": {
41996
42137
  const count = parseInt(args?.count) || parseInt(args?.lines) || 100;
@@ -43375,9 +43516,11 @@ var DaemonCommandRouter = class {
43375
43516
  if (meshRecord?.inline) {
43376
43517
  removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
43377
43518
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43519
+ if (!removed && !node) removed = true;
43378
43520
  } else {
43379
43521
  const { removeNode: removeNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
43380
43522
  removed = removeNode2(meshId, nodeId);
43523
+ if (!removed && !node) removed = true;
43381
43524
  if (removed) this.invalidateAggregateMeshStatus(meshId);
43382
43525
  }
43383
43526
  if (removed) {
@@ -43561,8 +43704,45 @@ var DaemonCommandRouter = class {
43561
43704
  setupPromise.then((value) => ({ completed: true, value })),
43562
43705
  new Promise((resolve23) => setTimeout(() => resolve23({ completed: false }), setupWaitMs))
43563
43706
  ]);
43707
+ const emitBootstrapEvent = (eventStatus2, bootstrapState2, startedAtMs, extraPayload) => {
43708
+ try {
43709
+ const durationMs = Date.now() - startedAtMs;
43710
+ const event = `worktree_${eventStatus2}`;
43711
+ const metadataEvent = {
43712
+ source: "clone_mesh_node_bootstrap",
43713
+ nodeId: node.id,
43714
+ status: eventStatus2,
43715
+ worktreePath: result.worktreePath,
43716
+ durationMs,
43717
+ bootstrapStatus: bootstrapState2.status,
43718
+ ...bootstrapState2.error ? { error: bootstrapState2.error } : {},
43719
+ ...bootstrapState2.exitCode !== void 0 ? { exitCode: bootstrapState2.exitCode } : {},
43720
+ ...extraPayload || {}
43721
+ };
43722
+ if (typeof this.deps.instanceManager?.getByCategory === "function") {
43723
+ const forwarded = handleMeshForwardEvent(
43724
+ { instanceManager: this.deps.instanceManager },
43725
+ { event, meshId, nodeId: node.id, workspace: result.worktreePath, metadataEvent }
43726
+ );
43727
+ if (forwarded?.success === true) return;
43728
+ }
43729
+ queuePendingMeshCoordinatorEvent({
43730
+ event,
43731
+ meshId,
43732
+ nodeLabel: node.id,
43733
+ nodeId: node.id,
43734
+ workspace: result.worktreePath,
43735
+ metadataEvent,
43736
+ queuedAt: Date.now()
43737
+ });
43738
+ } catch {
43739
+ }
43740
+ };
43741
+ const bootstrapStartedMs = Date.now();
43564
43742
  if (!setupResult.completed) {
43565
- setupPromise.catch((error) => {
43743
+ setupPromise.then(({ bootstrapState: bootstrapState2 }) => {
43744
+ emitBootstrapEvent("bootstrap_complete", bootstrapState2, bootstrapStartedMs);
43745
+ }).catch((error) => {
43566
43746
  const failedState = {
43567
43747
  ...runningBootstrapState,
43568
43748
  status: "failed",
@@ -43571,6 +43751,7 @@ var DaemonCommandRouter = class {
43571
43751
  };
43572
43752
  void persistWorktreeSetupState(failedState);
43573
43753
  void appendCloneLedger(false, failedState);
43754
+ emitBootstrapEvent("bootstrap_failed", failedState, bootstrapStartedMs, { error: error?.message || String(error) });
43574
43755
  });
43575
43756
  return {
43576
43757
  success: true,
@@ -43588,6 +43769,7 @@ var DaemonCommandRouter = class {
43588
43769
  };
43589
43770
  }
43590
43771
  const { submodulesInitialized, bootstrapState } = setupResult.value;
43772
+ emitBootstrapEvent("bootstrap_complete", bootstrapState, bootstrapStartedMs);
43591
43773
  return {
43592
43774
  success: true,
43593
43775
  node,
@@ -43655,7 +43837,34 @@ var DaemonCommandRouter = class {
43655
43837
  const ownerFailure = await this.requireMeshHostMutationOwner(meshId, args?.inlineMesh, "queue trigger");
43656
43838
  if (ownerFailure) return ownerFailure;
43657
43839
  try {
43658
- const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
43840
+ const { triggerMeshQueue: triggerMeshQueue2, tryAssignQueueTask: tryAssignQueueTask2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
43841
+ const preferredNodeId = typeof args?.preferredNodeId === "string" ? args.preferredNodeId.trim() : "";
43842
+ if (preferredNodeId) {
43843
+ const cliInstances = this.deps.instanceManager.getByCategory("cli");
43844
+ const sorted = [...cliInstances].sort((a, b) => {
43845
+ const aSettings = a.getState().settings || {};
43846
+ const bSettings = b.getState().settings || {};
43847
+ const aNode = readStringValue(aSettings.meshNodeId, aSettings.nodeId);
43848
+ const bNode = readStringValue(bSettings.meshNodeId, bSettings.nodeId);
43849
+ return (aNode === preferredNodeId ? -1 : 0) - (bNode === preferredNodeId ? -1 : 0);
43850
+ });
43851
+ for (const inst of sorted) {
43852
+ const state = inst.getState();
43853
+ const settings = state.settings || {};
43854
+ const nodeId = readStringValue(settings.meshNodeId, settings.nodeId);
43855
+ if (!nodeId || nodeId !== preferredNodeId) continue;
43856
+ const meshNodeFor = readStringValue(settings.meshNodeFor);
43857
+ if (meshNodeFor !== meshId) continue;
43858
+ const status = (readStringValue(state.status) || "").toLowerCase();
43859
+ if (status !== "idle") continue;
43860
+ const sessionId = typeof state.instanceId === "string" ? state.instanceId : "";
43861
+ const providerType = readStringValue(state.type, settings.providerType) || "";
43862
+ if (sessionId && providerType) {
43863
+ tryAssignQueueTask2(this.deps, meshId, nodeId, sessionId, providerType);
43864
+ break;
43865
+ }
43866
+ }
43867
+ }
43659
43868
  const trigger = await triggerMeshQueue2(this.deps, meshId);
43660
43869
  return { success: true, trigger };
43661
43870
  } catch (e) {