@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.js CHANGED
@@ -24561,12 +24561,89 @@ var REFINE_VALIDATION_TIMEOUT_MS = 12e4;
24561
24561
  var REFINE_VALIDATION_OUTPUT_LIMIT_BYTES = 128 * 1024;
24562
24562
  var REFINE_VALIDATION_SUMMARY_CHARS = 2e3;
24563
24563
  var REFINE_VALIDATION_MAX_COMMANDS = 4;
24564
+ var REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES = 4 * 1024 * 1024;
24564
24565
  function truncateValidationOutput(value) {
24565
24566
  const text = typeof value === "string" ? value : value == null ? "" : String(value);
24566
24567
  if (text.length <= REFINE_VALIDATION_SUMMARY_CHARS) return text;
24567
24568
  return `${text.slice(0, REFINE_VALIDATION_SUMMARY_CHARS)}
24568
24569
  [truncated ${text.length - REFINE_VALIDATION_SUMMARY_CHARS} chars]`;
24569
24570
  }
24571
+ function recordMeshRefineStage(stages, stage, status, startedAt, details) {
24572
+ stages.push({
24573
+ stage,
24574
+ status,
24575
+ durationMs: Date.now() - startedAt,
24576
+ ...details || {}
24577
+ });
24578
+ }
24579
+ async function computeGitPatchId(cwd, fromRef, toRef) {
24580
+ const { execFileSync: execFileSync4 } = await import("child_process");
24581
+ const diff = execFileSync4("git", ["diff", "--patch", "--full-index", fromRef, toRef], {
24582
+ cwd,
24583
+ encoding: "utf8",
24584
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24585
+ });
24586
+ if (!diff.trim()) return "";
24587
+ const patchId = execFileSync4("git", ["patch-id", "--stable"], {
24588
+ cwd,
24589
+ input: diff,
24590
+ encoding: "utf8",
24591
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24592
+ }).trim();
24593
+ return patchId.split(/\s+/)[0] || "";
24594
+ }
24595
+ async function runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead) {
24596
+ const startedAt = Date.now();
24597
+ try {
24598
+ const { execFileSync: execFileSync4 } = await import("child_process");
24599
+ const git = (args) => execFileSync4("git", args, {
24600
+ cwd: repoRoot,
24601
+ encoding: "utf8",
24602
+ maxBuffer: REFINE_PATCH_EQUIVALENCE_OUTPUT_LIMIT_BYTES
24603
+ });
24604
+ const mergeBase = git(["merge-base", baseHead, branchHead]).trim();
24605
+ const mergeTreeStdout = git(["merge-tree", "--write-tree", baseHead, branchHead]);
24606
+ const mergedTree = mergeTreeStdout.trim().split(/\s+/)[0] || "";
24607
+ if (!mergeBase || !mergedTree) {
24608
+ return {
24609
+ status: "failed",
24610
+ equivalent: false,
24611
+ baseHead,
24612
+ branchHead,
24613
+ mergeBase: mergeBase || void 0,
24614
+ mergedTree: mergedTree || void 0,
24615
+ durationMs: Date.now() - startedAt,
24616
+ error: "patch equivalence preflight could not resolve merge-base or synthetic merge tree",
24617
+ stdout: truncateValidationOutput(mergeTreeStdout)
24618
+ };
24619
+ }
24620
+ const expectedPatchId = await computeGitPatchId(repoRoot, mergeBase, branchHead);
24621
+ const actualPatchId = await computeGitPatchId(repoRoot, baseHead, mergedTree);
24622
+ const equivalent = expectedPatchId === actualPatchId;
24623
+ return {
24624
+ status: equivalent ? "passed" : "failed",
24625
+ equivalent,
24626
+ baseHead,
24627
+ branchHead,
24628
+ mergeBase,
24629
+ mergedTree,
24630
+ expectedPatchId,
24631
+ actualPatchId,
24632
+ durationMs: Date.now() - startedAt
24633
+ };
24634
+ } catch (e) {
24635
+ return {
24636
+ status: "failed",
24637
+ equivalent: false,
24638
+ baseHead,
24639
+ branchHead,
24640
+ durationMs: Date.now() - startedAt,
24641
+ error: e?.message || String(e),
24642
+ stdout: truncateValidationOutput(e?.stdout),
24643
+ stderr: truncateValidationOutput(e?.stderr)
24644
+ };
24645
+ }
24646
+ }
24570
24647
  function readPackageScripts(workspace) {
24571
24648
  try {
24572
24649
  const packageJsonPath = (0, import_path7.join)(workspace, "package.json");
@@ -26211,26 +26288,41 @@ var DaemonCommandRouter = class {
26211
26288
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
26212
26289
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
26213
26290
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
26291
+ const refineStages = [];
26214
26292
  try {
26215
26293
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
26216
26294
  const mesh = meshRecord?.mesh;
26217
26295
  const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
26218
- if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
26296
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh`, refineStages };
26219
26297
  if (!node.isLocalWorktree || !node.workspace) {
26220
- return { success: false, error: `Refinery requires a local worktree node` };
26298
+ return { success: false, error: `Refinery requires a local worktree node`, refineStages };
26221
26299
  }
26222
26300
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
26223
26301
  const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
26224
- if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
26302
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found", refineStages };
26225
26303
  const { execFile: execFile3 } = await import("child_process");
26226
26304
  const { promisify: promisify3 } = await import("util");
26227
26305
  const execFileAsync3 = promisify3(execFile3);
26306
+ const resolveStarted = Date.now();
26228
26307
  const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
26229
26308
  const branch = branchStdout.trim();
26230
- if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
26309
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node", refineStages };
26231
26310
  const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
26232
26311
  const baseBranch = baseBranchStdout.trim();
26312
+ const { stdout: baseHeadStdout } = await execFileAsync3("git", ["rev-parse", "HEAD"], { cwd: repoRoot, encoding: "utf8" });
26313
+ const { stdout: branchHeadStdout } = await execFileAsync3("git", ["rev-parse", branch], { cwd: node.workspace, encoding: "utf8" });
26314
+ const baseHead = baseHeadStdout.trim();
26315
+ const branchHead = branchHeadStdout.trim();
26316
+ recordMeshRefineStage(refineStages, "resolve_refs", "passed", resolveStarted, { branch, baseBranch, baseHead, branchHead });
26317
+ const validationStarted = Date.now();
26233
26318
  const validationSummary = await runMeshRefineValidationGate(mesh, node.workspace);
26319
+ recordMeshRefineStage(
26320
+ refineStages,
26321
+ "validation",
26322
+ validationSummary.status === "passed" ? "passed" : validationSummary.status === "failed" ? "failed" : "skipped",
26323
+ validationStarted,
26324
+ { validationStatus: validationSummary.status, commandsRun: validationSummary.commandsRun.length }
26325
+ );
26234
26326
  if (validationSummary.status === "failed") {
26235
26327
  return {
26236
26328
  success: false,
@@ -26240,6 +26332,7 @@ var DaemonCommandRouter = class {
26240
26332
  branch,
26241
26333
  into: baseBranch,
26242
26334
  validationSummary,
26335
+ refineStages,
26243
26336
  finalBranchConvergenceState: {
26244
26337
  branch,
26245
26338
  baseBranch,
@@ -26259,6 +26352,7 @@ var DaemonCommandRouter = class {
26259
26352
  branch,
26260
26353
  into: baseBranch,
26261
26354
  validationSummary,
26355
+ refineStages,
26262
26356
  finalBranchConvergenceState: {
26263
26357
  branch,
26264
26358
  baseBranch,
@@ -26269,37 +26363,121 @@ var DaemonCommandRouter = class {
26269
26363
  }
26270
26364
  };
26271
26365
  }
26366
+ const patchEquivalenceStarted = Date.now();
26367
+ const patchEquivalence = await runMeshRefinePatchEquivalenceGate(repoRoot, baseHead, branchHead);
26368
+ recordMeshRefineStage(refineStages, "patch_equivalence", patchEquivalence.status, patchEquivalenceStarted, {
26369
+ equivalent: patchEquivalence.equivalent,
26370
+ expectedPatchId: patchEquivalence.expectedPatchId,
26371
+ actualPatchId: patchEquivalence.actualPatchId,
26372
+ error: patchEquivalence.error
26373
+ });
26374
+ if (!patchEquivalence.equivalent) {
26375
+ return {
26376
+ success: false,
26377
+ code: "patch_equivalence_failed",
26378
+ convergenceStatus: "blocked_review",
26379
+ error: "Refinery patch-equivalence preflight failed; merge/refine was not attempted.",
26380
+ branch,
26381
+ into: baseBranch,
26382
+ validationSummary,
26383
+ patchEquivalence,
26384
+ refineStages,
26385
+ finalBranchConvergenceState: {
26386
+ branch,
26387
+ baseBranch,
26388
+ merged: false,
26389
+ removed: false,
26390
+ validation: "passed",
26391
+ patchEquivalence: "failed",
26392
+ status: "blocked_review"
26393
+ }
26394
+ };
26395
+ }
26396
+ let mergeResult;
26397
+ const mergeStarted = Date.now();
26272
26398
  try {
26273
- await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26399
+ const result = await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
26400
+ mergeResult = {
26401
+ stdout: truncateValidationOutput(result.stdout),
26402
+ stderr: truncateValidationOutput(result.stderr),
26403
+ durationMs: Date.now() - mergeStarted
26404
+ };
26405
+ recordMeshRefineStage(refineStages, "merge", "passed", mergeStarted, mergeResult);
26274
26406
  } catch (e) {
26407
+ recordMeshRefineStage(refineStages, "merge", "failed", mergeStarted, {
26408
+ error: e?.message || String(e),
26409
+ stdout: truncateValidationOutput(e?.stdout),
26410
+ stderr: truncateValidationOutput(e?.stderr)
26411
+ });
26275
26412
  return {
26276
26413
  success: false,
26277
26414
  error: `Merge failed (conflicts?): ${e.message}`,
26278
26415
  validationSummary,
26416
+ patchEquivalence,
26417
+ refineStages,
26279
26418
  finalBranchConvergenceState: {
26280
26419
  branch,
26281
26420
  baseBranch,
26282
26421
  merged: false,
26283
26422
  removed: false,
26284
26423
  validation: "passed",
26424
+ patchEquivalence: "passed",
26285
26425
  status: "not_mergeable"
26286
26426
  }
26287
26427
  };
26288
26428
  }
26429
+ const cleanupStarted = Date.now();
26289
26430
  const removeResult = await this.execute("remove_mesh_node", {
26290
26431
  meshId,
26291
26432
  nodeId,
26292
- sessionCleanupMode: "kill",
26433
+ sessionCleanupMode: "preserve",
26293
26434
  inlineMesh: args?.inlineMesh
26294
26435
  });
26436
+ recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
26437
+ removed: removeResult?.removed,
26438
+ code: removeResult?.code,
26439
+ error: removeResult?.error
26440
+ });
26441
+ let ledgerError;
26442
+ const ledgerStarted = Date.now();
26295
26443
  try {
26296
26444
  const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
26297
26445
  appendLedgerEntry2(meshId, {
26298
26446
  kind: "node_removed",
26299
26447
  nodeId,
26300
- payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary }
26448
+ payload: { refined: true, mergedBranch: branch, into: baseBranch, validationSummary, patchEquivalence }
26301
26449
  });
26302
- } catch {
26450
+ recordMeshRefineStage(refineStages, "ledger", "passed", ledgerStarted);
26451
+ } catch (e) {
26452
+ ledgerError = e?.message || String(e);
26453
+ recordMeshRefineStage(refineStages, "ledger", "failed", ledgerStarted, { error: ledgerError });
26454
+ }
26455
+ const finalBranchConvergenceState = {
26456
+ branch: baseBranch,
26457
+ mergedBranch: branch,
26458
+ baseBranch,
26459
+ merged: true,
26460
+ removed: removeResult?.success !== false,
26461
+ validation: "passed",
26462
+ patchEquivalence: "passed",
26463
+ status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26464
+ };
26465
+ if (removeResult?.success === false) {
26466
+ return {
26467
+ success: false,
26468
+ code: "cleanup_failed",
26469
+ error: "Refinery merge completed but worktree cleanup failed; manual cleanup/retry is required.",
26470
+ merged: true,
26471
+ branch,
26472
+ into: baseBranch,
26473
+ removeResult,
26474
+ validationSummary,
26475
+ patchEquivalence,
26476
+ mergeResult,
26477
+ refineStages,
26478
+ ...ledgerError ? { ledgerError } : {},
26479
+ finalBranchConvergenceState
26480
+ };
26303
26481
  }
26304
26482
  return {
26305
26483
  success: true,
@@ -26308,18 +26486,14 @@ var DaemonCommandRouter = class {
26308
26486
  into: baseBranch,
26309
26487
  removeResult,
26310
26488
  validationSummary,
26311
- finalBranchConvergenceState: {
26312
- branch: baseBranch,
26313
- mergedBranch: branch,
26314
- baseBranch,
26315
- merged: true,
26316
- removed: removeResult?.success !== false,
26317
- validation: "passed",
26318
- status: removeResult?.success === false ? "merged_cleanup_failed" : "merged"
26319
- }
26489
+ patchEquivalence,
26490
+ mergeResult,
26491
+ refineStages,
26492
+ ...ledgerError ? { ledgerError } : {},
26493
+ finalBranchConvergenceState
26320
26494
  };
26321
26495
  } catch (e) {
26322
- return { success: false, error: e.message };
26496
+ return { success: false, error: e.message, refineStages };
26323
26497
  }
26324
26498
  }
26325
26499
  case "remove_mesh_node": {
@@ -26831,6 +27005,43 @@ ${block}`);
26831
27005
  const sessionHostRecords = this.deps.sessionHostControl?.listSessions ? await this.deps.sessionHostControl.listSessions().catch(() => []) : [];
26832
27006
  const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
26833
27007
  const localMachineId = loadConfig().machineId || "";
27008
+ const requireDirectPeerTruth = args?.requireDirectPeerTruth === true;
27009
+ const directTruth = requireDirectPeerTruth ? await hydrateInlineMeshDirectTruth({
27010
+ mesh,
27011
+ meshSource: meshRecord.source,
27012
+ dispatchMeshCommand: this.deps.dispatchMeshCommand,
27013
+ statusInstanceId: this.deps.statusInstanceId,
27014
+ localMachineId
27015
+ }) : {
27016
+ directEvidenceCount: 0,
27017
+ localConfirmedCount: 0,
27018
+ peerAttemptedCount: 0,
27019
+ peerConfirmedCount: 0,
27020
+ unavailableNodeIds: []
27021
+ };
27022
+ const directTruthSatisfied = meshRecord.source !== "inline_bootstrap" || directTruth.directEvidenceCount > 0;
27023
+ if (requireDirectPeerTruth && !directTruthSatisfied) {
27024
+ return {
27025
+ success: false,
27026
+ code: "mesh_direct_peer_truth_unavailable",
27027
+ error: "Selected coordinator could not confirm direct mesh truth yet. Bootstrap inventory stays unavailable until direct mesh_status probes succeed.",
27028
+ sourceOfTruth: {
27029
+ membership: meshRecord.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
27030
+ coordinatorOwnsLiveTruth: false,
27031
+ currentStatus: "direct_peer_truth_unavailable",
27032
+ directPeerTruth: {
27033
+ required: true,
27034
+ satisfied: false,
27035
+ directEvidenceCount: directTruth.directEvidenceCount,
27036
+ localConfirmedCount: directTruth.localConfirmedCount,
27037
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27038
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27039
+ unavailableNodeIds: directTruth.unavailableNodeIds
27040
+ }
27041
+ }
27042
+ };
27043
+ }
27044
+ const directTruthUnavailableNodeIds = new Set(directTruth.unavailableNodeIds);
26834
27045
  const selectedCoordinatorNodeId = readStringValue(
26835
27046
  mesh.coordinator?.preferredNodeId,
26836
27047
  mesh.nodes?.[0]?.id,
@@ -26926,7 +27137,7 @@ ${block}`);
26926
27137
  status.git = inlineTransitGit;
26927
27138
  status.health = inlineTransitGit.isGitRepo ? deriveMeshNodeHealthFromGit(inlineTransitGit) : "degraded";
26928
27139
  remoteProbeApplied = true;
26929
- } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand) {
27140
+ } else if (!isSelfNode && daemonId && this.deps.dispatchMeshCommand && !directTruthUnavailableNodeIds.has(nodeId)) {
26930
27141
  try {
26931
27142
  const remoteGit = await probeRemoteMeshGitStatus({
26932
27143
  dispatchMeshCommand: this.deps.dispatchMeshCommand,
@@ -27017,7 +27228,19 @@ ${block}`);
27017
27228
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
27018
27229
  sourceOfTruth: {
27019
27230
  membership: meshRecord?.source === "inline_cache" ? "coordinator_inline_mesh_cache" : meshRecord?.source === "local_config" ? "local_mesh_config" : "inline_bootstrap_snapshot",
27020
- coordinatorOwnsLiveTruth: meshRecord?.source !== "inline_bootstrap",
27231
+ coordinatorOwnsLiveTruth: directTruthSatisfied,
27232
+ ...requireDirectPeerTruth ? {
27233
+ currentStatus: directTruthSatisfied ? "live_git_and_session_probes" : "direct_peer_truth_unavailable",
27234
+ directPeerTruth: {
27235
+ required: true,
27236
+ satisfied: directTruthSatisfied,
27237
+ directEvidenceCount: directTruth.directEvidenceCount,
27238
+ localConfirmedCount: directTruth.localConfirmedCount,
27239
+ peerAttemptedCount: directTruth.peerAttemptedCount,
27240
+ peerConfirmedCount: directTruth.peerConfirmedCount,
27241
+ unavailableNodeIds: directTruth.unavailableNodeIds
27242
+ }
27243
+ } : {},
27021
27244
  historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
27022
27245
  },
27023
27246
  nodes: nodeStatuses,