@adhdev/daemon-core 0.9.82-rc.63 → 0.9.82-rc.65

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
@@ -25149,6 +25149,7 @@ function summarizeRepoMeshStatusDebug(status) {
25149
25149
  meshId: readStringValue(status?.meshId, status?.mesh_id) ?? null,
25150
25150
  refreshedAt: readStringValue(status?.refreshedAt, status?.refreshed_at) ?? null,
25151
25151
  sourceOfTruth: status?.sourceOfTruth ?? null,
25152
+ branchConvergenceSummary: status?.branchConvergenceSummary ?? status?.branch_convergence_summary ?? null,
25152
25153
  nodeCount: nodes.length,
25153
25154
  nodes: nodes.map((node) => ({
25154
25155
  nodeId: readStringValue(node?.nodeId, node?.id) ?? null,
@@ -25164,7 +25165,8 @@ function summarizeRepoMeshStatusDebug(status) {
25164
25165
  } : null,
25165
25166
  gitProbePending: node?.gitProbePending === true,
25166
25167
  launchReady: node?.launchReady === true,
25167
- git: summarizeRepoMeshDebugGit(node?.git)
25168
+ git: summarizeRepoMeshDebugGit(node?.git),
25169
+ branchConvergence: node?.branchConvergence ?? node?.branch_convergence ?? null
25168
25170
  }))
25169
25171
  };
25170
25172
  }
@@ -25219,6 +25221,9 @@ function normalizeInlineMeshGitStatus(status, node, options) {
25219
25221
  headCommit: readStringValue(status.headCommit) ?? null,
25220
25222
  headMessage: readStringValue(status.headMessage) ?? null,
25221
25223
  upstream: readStringValue(status.upstream) ?? null,
25224
+ upstreamStatus: readStringValue(status.upstreamStatus, status.upstream_status) ?? (readStringValue(status.upstream) ? "unchecked" : "no_upstream"),
25225
+ upstreamFetchedAt: readNumberValue(status.upstreamFetchedAt, status.upstream_fetched_at),
25226
+ upstreamFetchError: readStringValue(status.upstreamFetchError, status.upstream_fetch_error),
25222
25227
  ahead: readNumberValue(status.ahead) ?? 0,
25223
25228
  behind: readNumberValue(status.behind) ?? 0,
25224
25229
  staged: readNumberValue(status.staged) ?? 0,
@@ -25417,8 +25422,11 @@ function reconcileInlineMeshCache(cached, incoming) {
25417
25422
  };
25418
25423
  }
25419
25424
  function hasGitWorktreeChanges(git) {
25420
- if (!git) return false;
25421
- return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0) > 0;
25425
+ return countGitWorktreeChanges(git) > 0;
25426
+ }
25427
+ function countGitWorktreeChanges(git) {
25428
+ if (!git) return 0;
25429
+ return Number(git.staged || 0) + Number(git.modified || 0) + Number(git.untracked || 0) + Number(git.deleted || 0) + Number(git.renamed || 0);
25422
25430
  }
25423
25431
  function getGitSubmoduleDriftState(git) {
25424
25432
  const submodules = Array.isArray(git?.submodules) ? git.submodules : [];
@@ -25440,6 +25448,146 @@ function deriveMeshNodeHealthFromGit(git) {
25440
25448
  if (submoduleDrift.dirty || hasGitWorktreeChanges(git)) return "dirty";
25441
25449
  return "online";
25442
25450
  }
25451
+ function readMeshNodeLabel(status, node) {
25452
+ return readStringValue(status.nodeId, node?.id, node?.nodeId) ?? "unknown";
25453
+ }
25454
+ function buildInlineMeshBranchConvergence(args) {
25455
+ const git = readObjectRecord(args.status.git);
25456
+ const nodeLabel = readMeshNodeLabel(args.status, args.node);
25457
+ const defaultBranch = readStringValue(args.mesh?.defaultBranch) ?? "main";
25458
+ const branch = readStringValue(git.branch, args.node?.worktreeBranch) ?? null;
25459
+ const upstream = readStringValue(git.upstream) ?? null;
25460
+ const upstreamStatus = readStringValue(git.upstreamStatus, git.upstream_status) ?? (upstream ? "unchecked" : "no_upstream");
25461
+ const ahead = readNumberValue(git.ahead) ?? 0;
25462
+ const behind = readNumberValue(git.behind) ?? 0;
25463
+ const uncommittedChanges = countGitWorktreeChanges(git);
25464
+ const hasConflicts = readBooleanValue(git.hasConflicts) ?? (Array.isArray(git.conflictFiles) && git.conflictFiles.length > 0);
25465
+ const base = {
25466
+ defaultBranch,
25467
+ branch,
25468
+ upstream,
25469
+ upstreamStatus,
25470
+ ahead,
25471
+ behind,
25472
+ isWorktree: args.node?.isLocalWorktree === true || args.status.isLocalWorktree === true,
25473
+ isDefaultBranch: branch === defaultBranch
25474
+ };
25475
+ if (readBooleanValue(git.isGitRepo) !== true) {
25476
+ return {
25477
+ ...base,
25478
+ status: "blocked_review",
25479
+ needsConvergence: true,
25480
+ reason: "git_status_unavailable",
25481
+ nextStep: `Resolve git status for node '${nodeLabel}' before marking the task complete.`
25482
+ };
25483
+ }
25484
+ if (!branch) {
25485
+ return {
25486
+ ...base,
25487
+ status: "blocked_review",
25488
+ needsConvergence: true,
25489
+ reason: "branch_unknown",
25490
+ nextStep: `Inspect node '${nodeLabel}' git branch before deciding whether it is merged to ${defaultBranch}.`
25491
+ };
25492
+ }
25493
+ if (hasConflicts || uncommittedChanges > 0) {
25494
+ return {
25495
+ ...base,
25496
+ status: "not_mergeable",
25497
+ needsConvergence: true,
25498
+ reason: hasConflicts ? "conflicts_present" : "dirty_workspace",
25499
+ nextStep: `Commit, checkpoint, or resolve node '${nodeLabel}' before any main convergence step.`
25500
+ };
25501
+ }
25502
+ if (branch === defaultBranch) {
25503
+ if (upstream && upstreamStatus !== "fresh") {
25504
+ return {
25505
+ ...base,
25506
+ status: "blocked_review",
25507
+ needsConvergence: true,
25508
+ reason: "default_branch_upstream_unverified",
25509
+ nextStep: `Refresh ${defaultBranch}'s upstream refs or resolve the fetch failure before declaring convergence complete for node '${nodeLabel}'.`
25510
+ };
25511
+ }
25512
+ if (ahead > 0 || behind > 0) {
25513
+ return {
25514
+ ...base,
25515
+ status: "blocked_review",
25516
+ needsConvergence: true,
25517
+ reason: "default_branch_not_even_with_upstream",
25518
+ nextStep: `Bring ${defaultBranch} even with its upstream before declaring convergence complete.`
25519
+ };
25520
+ }
25521
+ return {
25522
+ ...base,
25523
+ status: "merged_to_main",
25524
+ needsConvergence: false,
25525
+ reason: "clean_default_branch",
25526
+ nextStep: null
25527
+ };
25528
+ }
25529
+ if (args.node?.isLocalWorktree === true || args.status.isLocalWorktree === true) {
25530
+ return {
25531
+ ...base,
25532
+ status: "cleanup_candidate",
25533
+ needsConvergence: true,
25534
+ reason: "clean_non_default_worktree_branch",
25535
+ nextStep: `Run mesh_refine_node(node_id: "${nodeLabel}") or explicitly classify this worktree as blocked_review/not_mergeable before ending the task.`
25536
+ };
25537
+ }
25538
+ if (upstream && upstreamStatus !== "fresh") {
25539
+ return {
25540
+ ...base,
25541
+ status: "blocked_review",
25542
+ needsConvergence: true,
25543
+ reason: "feature_branch_upstream_unverified",
25544
+ nextStep: `Refresh branch '${branch}' upstream refs or resolve the fetch failure before deciding whether it is ready to merge into ${defaultBranch}.`
25545
+ };
25546
+ }
25547
+ if (!upstream || ahead > 0 || behind > 0) {
25548
+ return {
25549
+ ...base,
25550
+ status: "blocked_review",
25551
+ needsConvergence: true,
25552
+ reason: !upstream ? "feature_branch_missing_upstream" : "feature_branch_not_even_with_upstream",
25553
+ nextStep: `Push or reconcile branch '${branch}', then merge it into ${defaultBranch} or mark it not_mergeable with a reason.`
25554
+ };
25555
+ }
25556
+ return {
25557
+ ...base,
25558
+ status: "pushed_feature_branch_needs_merge",
25559
+ needsConvergence: true,
25560
+ reason: "clean_non_default_branch",
25561
+ nextStep: `Review and merge branch '${branch}' into ${defaultBranch}; do not report the task as fully complete while it remains off main.`
25562
+ };
25563
+ }
25564
+ function applyInlineMeshBranchConvergence(mesh, node, status) {
25565
+ const git = readObjectRecord(status.git);
25566
+ if (Object.keys(git).length === 0 && !status.gitProbePending) return;
25567
+ const uncommittedChanges = countGitWorktreeChanges(git);
25568
+ status.isDirty = uncommittedChanges > 0;
25569
+ status.uncommittedChanges = uncommittedChanges;
25570
+ status.branchConvergence = buildInlineMeshBranchConvergence({ mesh, node, status });
25571
+ }
25572
+ function summarizeInlineMeshBranchConvergence(nodes) {
25573
+ const followUps = nodes.filter((node) => readObjectRecord(node.branchConvergence).needsConvergence === true).map((node) => {
25574
+ const convergence = readObjectRecord(node.branchConvergence);
25575
+ return {
25576
+ nodeId: node.nodeId,
25577
+ workspace: node.workspace,
25578
+ branch: convergence.branch,
25579
+ status: convergence.status,
25580
+ reason: convergence.reason,
25581
+ nextStep: convergence.nextStep
25582
+ };
25583
+ });
25584
+ return {
25585
+ needsFollowUp: followUps.length > 0,
25586
+ unresolvedCount: followUps.length,
25587
+ requiredFinalStates: ["merged_to_main", "pushed_feature_branch_needs_merge", "blocked_review", "cleanup_candidate", "not_mergeable"],
25588
+ followUps
25589
+ };
25590
+ }
25443
25591
  function readCachedInlineMeshActiveSessions(node) {
25444
25592
  const cachedStatus = readObjectRecord(node?.cachedStatus);
25445
25593
  const activeSession = readObjectRecord(cachedStatus.activeSession);
@@ -25520,7 +25668,7 @@ function finalizeMeshNodeStatus(args) {
25520
25668
  async function probeRemoteMeshGitStatus(args) {
25521
25669
  if (!args.dispatchMeshCommand) return null;
25522
25670
  const remoteResult = await Promise.race([
25523
- args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace }),
25671
+ args.dispatchMeshCommand(args.daemonId, "git_status", { workspace: args.workspace, refreshUpstream: true }),
25524
25672
  new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), args.timeoutMs))
25525
25673
  ]);
25526
25674
  const remoteGit = remoteResult?.status ?? remoteResult?.git ?? remoteResult;
@@ -26113,6 +26261,7 @@ var DaemonCommandRouter = class {
26113
26261
  const nextStatus = { ...statusNode };
26114
26262
  nextStatus.git = liveGit;
26115
26263
  nextStatus.health = deriveMeshNodeHealthFromGit(liveGit);
26264
+ applyInlineMeshBranchConvergence(mesh, inlineNode, nextStatus);
26116
26265
  nextStatus.launchReady = readBooleanValue(nextStatus.launchReady) ?? true;
26117
26266
  const connection = readObjectRecord(nextStatus.connection);
26118
26267
  const connectionState = readStringValue(connection.state);
@@ -26151,6 +26300,7 @@ var DaemonCommandRouter = class {
26151
26300
  error: "Selected coordinator could not confirm direct mesh truth for every remote node yet."
26152
26301
  } : {},
26153
26302
  sourceOfTruth: nextSourceOfTruth,
26303
+ branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodes),
26154
26304
  nodes
26155
26305
  };
26156
26306
  }
@@ -28885,11 +29035,13 @@ ${block2}`);
28885
29035
  node,
28886
29036
  pendingPeerGitProbe ? { skipGit: true, skipError: true, skipHealth: true } : void 0
28887
29037
  )) {
29038
+ applyInlineMeshBranchConvergence(mesh, node, status);
28888
29039
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
28889
29040
  nodeStatuses.push(status);
28890
29041
  continue;
28891
29042
  }
28892
29043
  if (meshRecord?.source === "inline_cache" && !isSelfNode) {
29044
+ applyInlineMeshBranchConvergence(mesh, node, status);
28893
29045
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
28894
29046
  nodeStatuses.push(status);
28895
29047
  continue;
@@ -28915,6 +29067,7 @@ ${block2}`);
28915
29067
  } else {
28916
29068
  applyCachedInlineMeshNodeStatus(status, node);
28917
29069
  }
29070
+ applyInlineMeshBranchConvergence(mesh, node, status);
28918
29071
  finalizeMeshNodeStatus({ status, node, daemonId, isSelfNode });
28919
29072
  nodeStatuses.push(status);
28920
29073
  }
@@ -28950,6 +29103,7 @@ ${block2}`);
28950
29103
  } : {},
28951
29104
  historicalEvidenceOnly: ["recoveryHints", "ledger.summary", "queue.summary"]
28952
29105
  },
29106
+ branchConvergenceSummary: summarizeInlineMeshBranchConvergence(nodeStatuses),
28953
29107
  nodes: nodeStatuses,
28954
29108
  queue: { tasks: queue, summary: queueSummary },
28955
29109
  ledger: { entries: ledgerEntries, summary: ledgerSummary }