@adhdev/daemon-core 0.9.82-rc.36 → 0.9.82-rc.38

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
@@ -24328,12 +24328,89 @@ var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
24328
24328
  var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
24329
24329
  var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
24330
24330
  var REFINE_VALIDATION_MAX_COMMANDS = 4;
24331
+ var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
24331
24332
  function truncateValidationOutput(value) {
24332
24333
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
24333
24334
  if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
24334
24335
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
24335
24336
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
24336
24337
  }
24338
+ function recordMeshRefineStage(stages, stage, status, startedAt, details) {
24339
+ stages.push({
24340
+ stage,
24341
+ status,
24342
+ durationMs: Date.now() - startedAt,
24343
+ ...details || {}
24344
+ });
24345
+ }
24346
+ async function computeGitPatchId(cwd, fromRef, toRef) {
24347
+ const { execFileSync: execFileSync4 } = await import("child_process");
24348
+ const diff = execFileSync4("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
24349
+ cwd,
24350
+ encoding: "utf8",
24351
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24352
+ });
24353
+ if (!diff.trim()) return "";
24354
+ const patchId = execFileSync4("git", ["patch-id", "--stable"], {
24355
+ cwd,
24356
+ input: diff,
24357
+ encoding: "utf8",
24358
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24359
+ }).trim();
24360
+ return patchId.split(/\s+/)[0] || "";
24361
+ }
24362
+ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
24363
+ const startedAt = Date.now();
24364
+ try {
24365
+ const { execFileSync: execFileSync4 } = await import("child_process");
24366
+ const git = (args) => execFileSync4("git", args, {
24367
+ cwd: repoRoot,
24368
+ encoding: "utf8",
24369
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24370
+ });
24371
+ const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
24372
+ const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
24373
+ const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
24374
+ if (!mergeBase || !mergedTree) {
24375
+ return {
24376
+ status: "failed",
24377
+ equivalent: false,
24378
+ baseHead,
24379
+ branchHead,
24380
+ mergeBase: mergeBase || void 0,
24381
+ mergedTree: mergedTree || void 0,
24382
+ durationMs: Date.now() - startedAt,
24383
+ error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
24384
+ stdout: truncateValidationOutput(mergeTreeStdout)
24385
+ };
24386
+ }
24387
+ const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
24388
+ const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
24389
+ const equivalent = expectedPatchId === actualPatchId;
24390
+ return {
24391
+ status: equivalent ? "passed" : "failed",
24392
+ equivalent,
24393
+ baseHead,
24394
+ branchHead,
24395
+ mergeBase,
24396
+ mergedTree,
24397
+ expectedPatchId,
24398
+ actualPatchId,
24399
+ durationMs: Date.now() - startedAt
24400
+ };
24401
+ } catch (e) {
24402
+ return {
24403
+ status: "failed",
24404
+ equivalent: false,
24405
+ baseHead,
24406
+ branchHead,
24407
+ durationMs: Date.now() - startedAt,
24408
+ error: e?.message || String(e),
24409
+ stdout: truncateValidationOutput(e?.stdout),
24410
+ stderr: truncateValidationOutput(e?.stderr)
24411
+ };
24412
+ }
24413
+ }
24337
24414
  function readPackageScripts(workspace) {
24338
24415
  try {
24339
24416
  const packageJsonPath = pathJoin(workspace, "package.json");
@@ -25978,26 +26055,41 @@ var DaemonCommandRouter = class {
25978
26055
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
25979
26056
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
25980
26057
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
26058
+ const refineStages = [];
25981
26059
  try {
25982
26060
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
25983
26061
  const mesh = meshRecord?.mesh;
25984
26062
  const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
25985
- if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
26063
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
25986
26064
  if (!node.isLocalWorktree || !node.workspace) {
25987
- return { success: false, error: `Refinery requires a local worktree node` };
26065
+ return { success: false, error: `Refinery requires a local worktree node`, refineStages };
25988
26066
  }
25989
26067
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
25990
26068
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
25991
- if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
26069
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
25992
26070
  const { execFile: execFile3 } = await import("child_process");
25993
26071
  const { promisify: promisify3 } = await import("util");
25994
26072
  const execFileAsync3 = promisify3(execFile3);
26073
+ const resolveStarted = Date.now();
25995
26074
  const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
25996
26075
  const branch = branchStdout.trim();
25997
- if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
26076
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
25998
26077
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
25999
26078
  const baseBranch = baseBranchStdout.trim();
26079
+ const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
26080
+ const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
26081
+ const baseHead = baseHeadStdout.trim();
26082
+ const branchHead = branchHeadStdout.trim();
26083
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
26084
+ const validationStarted = Date.now();
26000
26085
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
26086
+ recordMeshRefineStage(
26087
+ refineStages,
26088
+ "validation",
26089
+ validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
26090
+ validationStarted,
26091
+ { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
26092
+ );
26001
26093
  if (validationSummary.status === "failed") {
26002
26094
  return {
26003
26095
  success: false,
@@ -26007,6 +26099,7 @@ var DaemonCommandRouter = class {
26007
26099
  branch,
26008
26100
  into: baseBranch,
26009
26101
  validationSummary,
26102
+ refineStages,
26010
26103
  finalBranchConvergenceState: {
26011
26104
  branch,
26012
26105
  baseBranch,
@@ -26026,6 +26119,7 @@ var DaemonCommandRouter = class {
26026
26119
  branch,
26027
26120
  into: baseBranch,
26028
26121
  validationSummary,
26122
+ refineStages,
26029
26123
  finalBranchConvergenceState: {
26030
26124
  branch,
26031
26125
  baseBranch,
@@ -26036,37 +26130,121 @@ var DaemonCommandRouter = class {
26036
26130
  }
26037
26131
  };
26038
26132
  }
26133
+ const patchEquivalenceStarted = Date.now();
26134
+ const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
26135
+ recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
26136
+ equivalent: patchEquivalence.equivalent,
26137
+ expectedPatchId: patchEquivalence.expectedPatchId,
26138
+ actualPatchId: patchEquivalence.actualPatchId,
26139
+ error: patchEquivalence.error
26140
+ });
26141
+ if (!patchEquivalence.equivalent) {
26142
+ return {
26143
+ success: false,
26144
+ code: "patch_equivalence_failed",
26145
+ convergenceStatus: "blocked_review",
26146
+ error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
26147
+ branch,
26148
+ into: baseBranch,
26149
+ validationSummary,
26150
+ patchEquivalence,
26151
+ refineStages,
26152
+ finalBranchConvergenceState: {
26153
+ branch,
26154
+ baseBranch,
26155
+ merged: false,
26156
+ removed: false,
26157
+ validation: "passed",
26158
+ patchEquivalence: "failed",
26159
+ status: "blocked_review"
26160
+ }
26161
+ };
26162
+ }
26163
+ let mergeResult;
26164
+ const mergeStarted = Date.now();
26039
26165
  try {
26040
- await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26166
+ const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26167
+ mergeResult = {
26168
+ stdout: truncateValidationOutput(result.stdout),
26169
+ stderr: truncateValidationOutput(result.stderr),
26170
+ durationMs: Date.now() - mergeStarted
26171
+ };
26172
+ recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
26041
26173
  } catch (e) {
26174
+ recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
26175
+ error: e?.message || String(e),
26176
+ stdout: truncateValidationOutput(e?.stdout),
26177
+ stderr: truncateValidationOutput(e?.stderr)
26178
+ });
26042
26179
  return {
26043
26180
  success: false,
26044
26181
  error: `Merge failed (conflicts?): ${e.message}`,
26045
26182
  validationSummary,
26183
+ patchEquivalence,
26184
+ refineStages,
26046
26185
  finalBranchConvergenceState: {
26047
26186
  branch,
26048
26187
  baseBranch,
26049
26188
  merged: false,
26050
26189
  removed: false,
26051
26190
  validation: "passed",
26191
+ patchEquivalence: "passed",
26052
26192
  status: "not_mergeable"
26053
26193
  }
26054
26194
  };
26055
26195
  }
26196
+ const cleanupStarted = Date.now();
26056
26197
  const removeResult = await this.execute("remove_mesh_node", {
26057
26198
  meshId,
26058
26199
  nodeId,
26059
- sessionCleanupMode: "kill",
26200
+ sessionCleanupMode: "preserve",
26060
26201
  inlineMesh: args?.inlineMesh
26061
26202
  });
26203
+ recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
26204
+ removed: removeResult?.removed,
26205
+ code: removeResult?.code,
26206
+ error: removeResult?.error
26207
+ });
26208
+ let ledgerError;
26209
+ const ledgerStarted = Date.now();
26062
26210
  try {
26063
26211
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
26064
26212
  appendLedgerEntry2(meshId, {
26065
26213
  kind: "node_removed",
26066
26214
  nodeId,
26067
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
26215
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
26068
26216
  });
26069
- } catch {
26217
+ recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
26218
+ } catch (e) {
26219
+ ledgerError = e?.message || String(e);
26220
+ recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
26221
+ }
26222
+ const finalBranchConvergenceState = {
26223
+ branch: baseBranch,
26224
+ mergedBranch: branch,
26225
+ baseBranch,
26226
+ merged: true,
26227
+ removed: removeResult?.success !== false,
26228
+ validation: "passed",
26229
+ patchEquivalence: "passed",
26230
+ status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26231
+ };
26232
+ if (removeResult?.success === false) {
26233
+ return {
26234
+ success: false,
26235
+ code: "cleanup_failed",
26236
+ error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
26237
+ merged: true,
26238
+ branch,
26239
+ into: baseBranch,
26240
+ removeResult,
26241
+ validationSummary,
26242
+ patchEquivalence,
26243
+ mergeResult,
26244
+ refineStages,
26245
+ ...ledgerError ? { ledgerError } : {},
26246
+ finalBranchConvergenceState
26247
+ };
26070
26248
  }
26071
26249
  return {
26072
26250
  success: true,
@@ -26075,18 +26253,14 @@ var DaemonCommandRouter = class {
26075
26253
  into: baseBranch,
26076
26254
  removeResult,
26077
26255
  validationSummary,
26078
- finalBranchConvergenceState: {
26079
- branch: baseBranch,
26080
- mergedBranch: branch,
26081
- baseBranch,
26082
- merged: true,
26083
- removed: removeResult?.success !== false,
26084
- validation: "passed",
26085
- status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26086
- }
26256
+ patchEquivalence,
26257
+ mergeResult,
26258
+ refineStages,
26259
+ ...ledgerError ? { ledgerError } : {},
26260
+ finalBranchConvergenceState
26087
26261
  };
26088
26262
  } catch (e) {
26089
- return { success: false, error: e.message };
26263
+ return { success: false, error: e.message, refineStages };
26090
26264
  }
26091
26265
  }
26092
26266
  case "remove_mesh_node": {
@@ -26598,6 +26772,43 @@ ${block}`);
26598
26772
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26599
26773
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26600
26774
  const localMachineId = loadConfig().machineId || "";
26775
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
26776
+ const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
26777
+ mesh,
26778
+ meshSource: meshRecord.source,
26779
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
26780
+ statusInstanceId: this.deps.statusInstanceId,
26781
+ localMachineId
26782
+ }) : {
26783
+ directEvidenceCount: 0,
26784
+ localConfirmedCount: 0,
26785
+ peerAttemptedCount: 0,
26786
+ peerConfirmedCount: 0,
26787
+ unavailableNodeIds: []
26788
+ };
26789
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
26790
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
26791
+ return {
26792
+ success: false,
26793
+ code: "mesh_direct_peer_truth_unavailable",
26794
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
26795
+ sourceOfTruth: {
26796
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26797
+ coordinatorOwnsLiveTruth: false,
26798
+ currentStatus: "direct_peer_truth_unavailable",
26799
+ directPeerTruth: {
26800
+ required: true,
26801
+ satisfied: false,
26802
+ directEvidenceCount: directTruth.directEvidenceCount,
26803
+ localConfirmedCount: directTruth.localConfirmedCount,
26804
+ peerAttemptedCount: directTruth.peerAttemptedCount,
26805
+ peerConfirmedCount: directTruth.peerConfirmedCount,
26806
+ unavailableNodeIds: directTruth.unavailableNodeIds
26807
+ }
26808
+ }
26809
+ };
26810
+ }
26811
+ const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
26601
26812
  const selectedCoordinatorNodeId = readStringValue(
26602
26813
  mesh.coordinator?.preferredNodeId,
26603
26814
  mesh.nodes?.[0]?.id,
@@ -26693,7 +26904,7 @@ ${block}`);
26693
26904
  status.git = inlineTransitGit;
26694
26905
  status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
26695
26906
  remoteProbeApplied = true;
26696
- } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
26907
+ } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
26697
26908
  try {
26698
26909
  const remoteGit = await probeRemoteMeshGitStatus({
26699
26910
  dispatchMeshCommand: this.deps.dispatchMeshCommand,
@@ -26784,7 +26995,19 @@ ${block}`);
26784
26995
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
26785
26996
  sourceOfTruth: {
26786
26997
  membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
26787
- coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
26998
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
26999
+ ...requireDirectPeerTruth ? {
27000
+ currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
27001
+ directPeerTruth: {
27002
+ required: true,
27003
+ satisfied: directTruthSatisfied,
27004
+ directEvidenceCount: directTruth.directEvidenceCount,
27005
+ localConfirmedCount: directTruth.localConfirmedCount,
27006
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27007
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27008
+ unavailableNodeIds: directTruth.unavailableNodeIds
27009
+ }
27010
+ } : {},
26788
27011
  historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
26789
27012
  },
26790
27013
  nodes: nodeStatuses,