@adhdev/daemon-standalone 0.9.82-rc.52 → 0.9.82-rc.54

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
@@ -22482,9 +22482,9 @@ ${error48.message || ""}`;
22482
22482
  function parseWorktreeListOutput(output) {
22483
22483
  const entries = [];
22484
22484
  const blocks = output.trim().split(/\n\n+/);
22485
- for (const block of blocks) {
22486
- if (!block.trim()) continue;
22487
- const lines = block.trim().split("\n");
22485
+ for (const block2 of blocks) {
22486
+ if (!block2.trim()) continue;
22487
+ const lines = block2.trim().split("\n");
22488
22488
  const entry = { path: "", head: "", branch: null, bare: false };
22489
22489
  for (const line of lines) {
22490
22490
  if (line.startsWith("worktree ")) {
@@ -23311,7 +23311,8 @@ ${rules.join("\n")}`;
23311
23311
  - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
23312
23312
  - **Never fabricate tool results.** Always call the actual tool; never pretend you did.
23313
23313
  - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
23314
- - **Do not strand completed branches.** A checkpointed or clean feature/worktree branch is not done by itself. Merge/refine it to the mesh default branch, or explicitly report one of \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\` with the next action.
23314
+ - **Do not strand completed branches.** A checkpointed or clean feature/worktree branch is not done by itself. Merge/refine it to the mesh default branch, fast-forward obvious clean behind-only branches with \`mesh_fast_forward_node\`, or explicitly report one of \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\` with the next action.
23315
+ - **Keep Refinery validation project-configurable.** \`mesh_refine_node\` must execute validation from repo mesh/refine config (for example \`.adhdev/refine.{json,yaml,yml}\`, \`.adhdev/repo-mesh-refine.*\`, or \`repo-mesh.refine.*\`). Heuristics are suggestions/scaffolding only, not the execution path.
23315
23316
  - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
23316
23317
  }
23317
23318
  var TOOLS_SECTION;
@@ -23337,6 +23338,7 @@ ${rules.join("\n")}`;
23337
23338
  | \`mesh_read_debug\` | Collect a daemon-side chat/parser debug bundle for a session |
23338
23339
  | \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
23339
23340
  | \`mesh_git_status\` | Check git status on a specific node |
23341
+ | \`mesh_fast_forward_node\` | Safely dry-run or explicitly execute an obvious clean fast-forward without launching an agent session |
23340
23342
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
23341
23343
  | \`mesh_approve\` | Approve/reject a pending agent action |
23342
23344
  | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
@@ -23359,7 +23361,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
23359
23361
  4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Use \`mesh_view_queue\` to see the status of all pending, assigned, completed, and failed tasks. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal. Handle approvals via \`mesh_approve\`.
23360
23362
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
23361
23363
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
23362
- 7. **Converge branches** \u2014 Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary and \`mesh_refine_node\` for clean worktree branches when safe. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
23364
+ 7. **Converge branches** \u2014 Before marking any task complete, classify every touched node/branch into exactly one final state: \`merged_to_main\`, \`pushed_feature_branch_needs_merge\`, \`blocked_review\`, \`cleanup_candidate\`, or \`not_mergeable\`. Use \`mesh_status\` branchConvergenceSummary. For obvious clean branch catch-up (ahead 0, behind > 0, upstream fresh, no dirty/stash/submodule issues), use \`mesh_fast_forward_node\` dry-run first and execute only when explicitly safe/approved; this avoids consuming an agent session. Use \`mesh_refine_node\` for clean worktree branches when safe. A task that remains on a non-main branch is not fully complete unless the final report names the follow-up state and next step.
23363
23365
  8. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
23364
23366
  9. **Report** \u2014 Summarize what was done, what changed, any issues, and the branch convergence state.
23365
23367
 
@@ -28363,6 +28365,7 @@ ${lastSnapshot}`;
28363
28365
  enqueueTask: () => enqueueTask,
28364
28366
  ensureSessionHostReady: () => ensureSessionHostReady2,
28365
28367
  execNpmCommandSync: () => execNpmCommandSync,
28368
+ fastForwardMeshNode: () => fastForwardMeshNode,
28366
28369
  filterActivityChatMessages: () => filterActivityChatMessages,
28367
28370
  filterChatMessagesByVisibility: () => filterChatMessagesByVisibility,
28368
28371
  filterInternalChatMessages: () => filterInternalChatMessages,
@@ -30480,6 +30483,354 @@ ${lastSnapshot}`;
30480
30483
  return result;
30481
30484
  }
30482
30485
  init_mesh_ledger();
30486
+ init_git_executor();
30487
+ var STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3 };
30488
+ async function fastForwardMeshNode(args) {
30489
+ const workspace = typeof args.workspace === "string" ? args.workspace.trim() : "";
30490
+ const nodeId = normalizeOptionalString(args.nodeId);
30491
+ const meshId = normalizeOptionalString(args.meshId);
30492
+ const requestedBranch = normalizeOptionalString(args.branch);
30493
+ const updateSubmodules = args.updateSubmodules === true;
30494
+ const dryRun = args.dryRun === true || args.execute !== true;
30495
+ const plannedSteps = buildPlannedSteps(updateSubmodules);
30496
+ const base = {
30497
+ ...nodeId ? { nodeId } : {},
30498
+ ...meshId ? { meshId } : {},
30499
+ workspace,
30500
+ dryRun,
30501
+ updateSubmodules,
30502
+ plannedSteps
30503
+ };
30504
+ if (!workspace) {
30505
+ return block(base, "invalid_workspace", ["workspace_required"]);
30506
+ }
30507
+ const current = await getGitRepoStatus(workspace, {
30508
+ ...STATUS_OPTIONS,
30509
+ submoduleIgnorePaths: args.submoduleIgnorePaths,
30510
+ timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
30511
+ });
30512
+ const earlyBlockers = collectPreflightBlockers(current, requestedBranch);
30513
+ if (earlyBlockers.length > 0) {
30514
+ return {
30515
+ ...block(base, chooseBlockCode(current, earlyBlockers), earlyBlockers),
30516
+ current,
30517
+ finalBranchConvergenceState: buildConvergenceState(current, codeToConvergenceStatus(chooseBlockCode(current, earlyBlockers)))
30518
+ };
30519
+ }
30520
+ if (current.behind === 0) {
30521
+ const result2 = {
30522
+ ...base,
30523
+ success: true,
30524
+ code: "already_up_to_date",
30525
+ allowed: true,
30526
+ willRun: false,
30527
+ executed: false,
30528
+ blockingReasons: [],
30529
+ current,
30530
+ preStatus: current,
30531
+ postStatus: current,
30532
+ finalBranchConvergenceState: buildConvergenceState(current, "up_to_date")
30533
+ };
30534
+ await appendFastForwardLedger(result2, "noop");
30535
+ return result2;
30536
+ }
30537
+ const ancestorCheck = await verifyHeadIsAncestorOfUpstream(workspace, current.upstream || "", args.timeoutMs);
30538
+ if (!ancestorCheck.ok) {
30539
+ const result2 = {
30540
+ ...block(base, "non_fast_forward", ["head_is_not_ancestor_of_upstream"]),
30541
+ current,
30542
+ preStatus: current,
30543
+ operationError: ancestorCheck.error,
30544
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
30545
+ };
30546
+ await appendFastForwardLedger(result2, "blocked");
30547
+ return result2;
30548
+ }
30549
+ if (dryRun) {
30550
+ const result2 = {
30551
+ ...base,
30552
+ success: true,
30553
+ code: "fast_forward_available",
30554
+ allowed: true,
30555
+ willRun: false,
30556
+ executed: false,
30557
+ blockingReasons: [],
30558
+ current,
30559
+ preStatus: current,
30560
+ finalBranchConvergenceState: buildConvergenceState(current, "fast_forward_available")
30561
+ };
30562
+ return result2;
30563
+ }
30564
+ try {
30565
+ await runGit(workspace, ["merge", "--ff-only", current.upstream || ""], { timeoutMs: args.timeoutMs ?? 3e4 });
30566
+ } catch (error48) {
30567
+ const result2 = {
30568
+ ...block(base, "merge_ff_only_failed", ["merge_ff_only_failed"]),
30569
+ current,
30570
+ preStatus: current,
30571
+ operationError: formatGitError2(error48),
30572
+ finalBranchConvergenceState: buildConvergenceState(current, "not_mergeable")
30573
+ };
30574
+ await appendFastForwardLedger(result2, "failed");
30575
+ return result2;
30576
+ }
30577
+ let postStatus = await getGitRepoStatus(workspace, {
30578
+ ...STATUS_OPTIONS,
30579
+ submoduleIgnorePaths: args.submoduleIgnorePaths,
30580
+ timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
30581
+ });
30582
+ const submoduleIssues = collectSubmoduleBlockers(postStatus, "post");
30583
+ let submoduleFollowUpRequired = false;
30584
+ let operationError;
30585
+ if (submoduleIssues.length > 0) {
30586
+ if (updateSubmodules) {
30587
+ try {
30588
+ await runGit(workspace, ["submodule", "update", "--init", "--recursive"], { timeoutMs: args.timeoutMs ?? 6e4 });
30589
+ postStatus = await getGitRepoStatus(workspace, {
30590
+ ...STATUS_OPTIONS,
30591
+ submoduleIgnorePaths: args.submoduleIgnorePaths,
30592
+ timeoutMs: args.timeoutMs ?? STATUS_OPTIONS.timeoutMs
30593
+ });
30594
+ } catch (error48) {
30595
+ operationError = formatGitError2(error48);
30596
+ }
30597
+ } else {
30598
+ submoduleFollowUpRequired = true;
30599
+ }
30600
+ }
30601
+ const postBlockers = collectPostExecutionBlockers(postStatus);
30602
+ if (operationError) postBlockers.push("submodule_update_failed");
30603
+ if (submoduleFollowUpRequired) postBlockers.push("submodule_update_required");
30604
+ const success2 = postBlockers.length === 0 || submoduleFollowUpRequired;
30605
+ const code = postBlockers.length === 0 ? "fast_forward_applied" : submoduleFollowUpRequired ? "fast_forward_applied_submodule_update_required" : "post_verify_failed";
30606
+ const result = {
30607
+ ...base,
30608
+ success: success2,
30609
+ code,
30610
+ allowed: true,
30611
+ willRun: true,
30612
+ executed: true,
30613
+ blockingReasons: postBlockers,
30614
+ current,
30615
+ preStatus: current,
30616
+ postStatus,
30617
+ ...operationError ? { operationError } : {},
30618
+ finalBranchConvergenceState: buildConvergenceState(
30619
+ postStatus,
30620
+ postBlockers.length === 0 ? "fast_forwarded" : submoduleFollowUpRequired ? "follow_up_required" : "post_verify_failed"
30621
+ )
30622
+ };
30623
+ await appendFastForwardLedger(result, success2 ? "executed" : "failed");
30624
+ return result;
30625
+ }
30626
+ function buildPlannedSteps(updateSubmodules) {
30627
+ const steps = [
30628
+ {
30629
+ operation: "refresh_upstream",
30630
+ description: "Refresh the tracked upstream remote ref before trusting ahead/behind state.",
30631
+ safe: true,
30632
+ willMutateWorktree: false
30633
+ },
30634
+ {
30635
+ operation: "verify_clean_worktree",
30636
+ description: "Require clean staged/modified/untracked/deleted/renamed/conflict/stash/submodule state.",
30637
+ safe: true,
30638
+ willMutateWorktree: false
30639
+ },
30640
+ {
30641
+ operation: "verify_fast_forward",
30642
+ description: "Require ahead=0, behind>0, and HEAD to be an ancestor of the upstream ref.",
30643
+ safe: true,
30644
+ willMutateWorktree: false
30645
+ },
30646
+ {
30647
+ operation: "merge_ff_only",
30648
+ description: "Apply git merge --ff-only against the tracked upstream; no force, reset, rebase, push, or deploy.",
30649
+ safe: true,
30650
+ willMutateWorktree: true
30651
+ }
30652
+ ];
30653
+ if (updateSubmodules) {
30654
+ steps.push({
30655
+ operation: "submodule_update",
30656
+ description: "If the fast-forward changes gitlinks, run git submodule update --init --recursive and re-verify submodules.",
30657
+ safe: true,
30658
+ willMutateWorktree: true
30659
+ });
30660
+ }
30661
+ steps.push({
30662
+ operation: "verify_post_status",
30663
+ description: "Re-read daemon-owned git status and report final branch convergence state.",
30664
+ safe: true,
30665
+ willMutateWorktree: false
30666
+ });
30667
+ return steps;
30668
+ }
30669
+ function collectPreflightBlockers(status, requestedBranch) {
30670
+ const blockers = [];
30671
+ if (!status.isGitRepo) blockers.push("not_git_repo");
30672
+ if (!status.branch) blockers.push("detached_head_or_unknown_branch");
30673
+ if (requestedBranch && status.branch !== requestedBranch) blockers.push("branch_mismatch");
30674
+ if (!status.upstream) blockers.push("upstream_missing");
30675
+ if (status.upstreamStatus !== "fresh") blockers.push("upstream_not_fresh");
30676
+ if (status.hasConflicts) blockers.push("conflicts_present");
30677
+ if (status.staged > 0) blockers.push("staged_changes_present");
30678
+ if (status.modified > 0) blockers.push("modified_changes_present");
30679
+ if (status.untracked > 0) blockers.push("untracked_changes_present");
30680
+ if (status.deleted > 0) blockers.push("deleted_changes_present");
30681
+ if (status.renamed > 0) blockers.push("renamed_changes_present");
30682
+ if (status.stashCount > 0) blockers.push("stash_entries_present");
30683
+ blockers.push(...collectSubmoduleBlockers(status, "pre"));
30684
+ if (status.ahead > 0 && status.behind > 0) {
30685
+ blockers.push("branch_diverged_from_upstream");
30686
+ blockers.push("branch_has_local_commits");
30687
+ } else if (status.ahead > 0) blockers.push("branch_has_local_commits");
30688
+ return blockers;
30689
+ }
30690
+ function collectPostExecutionBlockers(status) {
30691
+ const blockers = [];
30692
+ if (!status.isGitRepo) blockers.push("post_not_git_repo");
30693
+ if (status.hasConflicts) blockers.push("post_conflicts_present");
30694
+ if (status.ahead !== 0) blockers.push("post_branch_ahead");
30695
+ if (status.behind !== 0) blockers.push("post_branch_still_behind");
30696
+ if (status.staged > 0 || status.modified > 0 || status.untracked > 0 || status.deleted > 0 || status.renamed > 0) {
30697
+ blockers.push("post_working_tree_not_clean");
30698
+ }
30699
+ if (status.stashCount > 0) blockers.push("post_stash_entries_present");
30700
+ blockers.push(...collectSubmoduleBlockers(status, "post"));
30701
+ return blockers;
30702
+ }
30703
+ function collectSubmoduleBlockers(status, phase) {
30704
+ const submodules = Array.isArray(status.submodules) ? status.submodules : [];
30705
+ const blockers = [];
30706
+ for (const submodule of submodules) {
30707
+ if (submodule.error) blockers.push(`${phase}_submodule_status_error:${submodule.path}`);
30708
+ if (submodule.dirty) blockers.push(`${phase}_submodule_dirty:${submodule.path}`);
30709
+ if (submodule.outOfSync) blockers.push(`${phase}_submodule_out_of_sync:${submodule.path}`);
30710
+ }
30711
+ return blockers;
30712
+ }
30713
+ function chooseBlockCode(status, blockers) {
30714
+ if (blockers.includes("not_git_repo")) return "not_git_repo";
30715
+ if (blockers.includes("branch_mismatch")) return "branch_mismatch";
30716
+ if (blockers.includes("upstream_missing")) return "upstream_missing";
30717
+ if (blockers.includes("upstream_not_fresh")) return "upstream_not_fresh";
30718
+ if (blockers.some((reason) => reason.includes("submodule"))) return "submodule_not_clean";
30719
+ if (blockers.includes("branch_diverged_from_upstream")) return "branch_diverged";
30720
+ if (blockers.includes("branch_has_local_commits") || status.ahead > 0) return "branch_ahead";
30721
+ if (blockers.some((reason) => reason.includes("changes") || reason.includes("conflicts") || reason.includes("stash"))) return "dirty_worktree";
30722
+ return "preflight_blocked";
30723
+ }
30724
+ function codeToConvergenceStatus(code) {
30725
+ if (code === "branch_diverged" || code === "branch_ahead" || code === "non_fast_forward") return "not_mergeable";
30726
+ if (code === "dirty_worktree" || code === "submodule_not_clean") return "blocked_review";
30727
+ return "blocked";
30728
+ }
30729
+ async function verifyHeadIsAncestorOfUpstream(workspace, upstream, timeoutMs) {
30730
+ if (!upstream) return { ok: false, error: "missing upstream" };
30731
+ try {
30732
+ await runGit(workspace, ["merge-base", "--is-ancestor", "HEAD", upstream], { timeoutMs: timeoutMs ?? 15e3 });
30733
+ return { ok: true };
30734
+ } catch (error48) {
30735
+ return { ok: false, error: formatGitError2(error48) };
30736
+ }
30737
+ }
30738
+ function block(base, code, blockingReasons) {
30739
+ const normalizedReasons = normalizeBlockingReasons(blockingReasons);
30740
+ return {
30741
+ ...base,
30742
+ success: false,
30743
+ code,
30744
+ allowed: false,
30745
+ willRun: false,
30746
+ executed: false,
30747
+ blockingReasons: normalizedReasons
30748
+ };
30749
+ }
30750
+ function normalizeBlockingReasons(reasons) {
30751
+ const normalized = /* @__PURE__ */ new Set();
30752
+ for (const reason of reasons) {
30753
+ normalized.add(reason);
30754
+ }
30755
+ if ([
30756
+ "conflicts_present",
30757
+ "staged_changes_present",
30758
+ "modified_changes_present",
30759
+ "untracked_changes_present",
30760
+ "deleted_changes_present",
30761
+ "renamed_changes_present"
30762
+ ].some((reason) => normalized.has(reason))) {
30763
+ normalized.add("working_tree_not_clean");
30764
+ }
30765
+ return Array.from(normalized);
30766
+ }
30767
+ function buildConvergenceState(status, convergenceStatus) {
30768
+ return {
30769
+ status: convergenceStatus,
30770
+ branch: status.branch,
30771
+ headCommit: status.headCommit,
30772
+ upstream: status.upstream,
30773
+ ahead: status.ahead,
30774
+ behind: status.behind,
30775
+ dirty: status.staged + status.modified + status.untracked + status.deleted + status.renamed > 0 || status.hasConflicts,
30776
+ stashCount: status.stashCount,
30777
+ submodules: summarizeSubmodules(status.submodules)
30778
+ };
30779
+ }
30780
+ function summarizeSubmodules(submodules) {
30781
+ return (submodules || []).map((submodule) => ({
30782
+ path: submodule.path,
30783
+ commit: submodule.commit,
30784
+ dirty: submodule.dirty,
30785
+ outOfSync: submodule.outOfSync,
30786
+ ...submodule.error ? { error: submodule.error } : {}
30787
+ }));
30788
+ }
30789
+ function normalizeOptionalString(value) {
30790
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
30791
+ }
30792
+ function formatGitError2(error48) {
30793
+ if (error48 instanceof GitCommandError) {
30794
+ return error48.stderr || error48.stdout || error48.message;
30795
+ }
30796
+ if (error48 instanceof Error) return error48.message;
30797
+ return String(error48);
30798
+ }
30799
+ async function appendFastForwardLedger(result, outcome) {
30800
+ if (!result.meshId) return;
30801
+ try {
30802
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
30803
+ appendLedgerEntry2(result.meshId, {
30804
+ kind: "direct_fast_forward",
30805
+ ...result.nodeId ? { nodeId: result.nodeId } : {},
30806
+ payload: {
30807
+ operation: "mesh_fast_forward_node",
30808
+ outcome,
30809
+ code: result.code,
30810
+ workspace: result.workspace,
30811
+ allowed: result.allowed,
30812
+ dryRun: result.dryRun,
30813
+ willRun: result.willRun,
30814
+ executed: result.executed,
30815
+ branch: result.postStatus?.branch ?? result.current?.branch,
30816
+ upstream: result.postStatus?.upstream ?? result.current?.upstream,
30817
+ before: result.current ? {
30818
+ headCommit: result.current.headCommit,
30819
+ ahead: result.current.ahead,
30820
+ behind: result.current.behind
30821
+ } : void 0,
30822
+ after: result.postStatus ? {
30823
+ headCommit: result.postStatus.headCommit,
30824
+ ahead: result.postStatus.ahead,
30825
+ behind: result.postStatus.behind
30826
+ } : void 0,
30827
+ blockingReasons: result.blockingReasons
30828
+ }
30829
+ });
30830
+ } catch (error48) {
30831
+ result.ledgerError = error48 instanceof Error ? error48.message : String(error48);
30832
+ }
30833
+ }
30483
30834
  function lastTimestamp(slice) {
30484
30835
  const entries = Array.isArray(slice?.entries) ? slice.entries : [];
30485
30836
  return entries.length ? entries[entries.length - 1].timestamp : null;
@@ -45959,10 +46310,10 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
45959
46310
  function stringifyPreviewContent(content) {
45960
46311
  if (typeof content === "string") return content;
45961
46312
  if (Array.isArray(content)) {
45962
- return content.map((block) => {
45963
- if (typeof block === "string") return block;
45964
- if (block && typeof block === "object" && "text" in block) {
45965
- return String(block.text || "");
46313
+ return content.map((block2) => {
46314
+ if (typeof block2 === "string") return block2;
46315
+ if (block2 && typeof block2 === "object" && "text" in block2) {
46316
+ return String(block2.text || "");
45966
46317
  }
45967
46318
  return "";
45968
46319
  }).join(" ");
@@ -49203,6 +49554,32 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49203
49554
  cleanupWillRun: false
49204
49555
  };
49205
49556
  }
49557
+ case "fast_forward_mesh_node": {
49558
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
49559
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
49560
+ let workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
49561
+ let submoduleIgnorePaths = Array.isArray(args?.submoduleIgnorePaths) ? args.submoduleIgnorePaths.filter((value) => typeof value === "string") : void 0;
49562
+ if (!workspace && meshId && nodeId) {
49563
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
49564
+ const mesh = meshRecord?.mesh;
49565
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
49566
+ workspace = typeof node?.workspace === "string" ? node.workspace.trim() : "";
49567
+ if (!submoduleIgnorePaths && Array.isArray(node?.policy?.submoduleIgnorePaths)) {
49568
+ submoduleIgnorePaths = node.policy.submoduleIgnorePaths.filter((value) => typeof value === "string");
49569
+ }
49570
+ }
49571
+ const result = await fastForwardMeshNode({
49572
+ meshId: meshId || void 0,
49573
+ nodeId: nodeId || void 0,
49574
+ workspace,
49575
+ branch: typeof args?.branch === "string" ? args.branch : void 0,
49576
+ execute: args?.execute === true,
49577
+ dryRun: args?.dryRun === true,
49578
+ updateSubmodules: args?.updateSubmodules === true,
49579
+ submoduleIgnorePaths
49580
+ });
49581
+ return result;
49582
+ }
49206
49583
  case "refine_mesh_node": {
49207
49584
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
49208
49585
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
@@ -49713,20 +50090,20 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
49713
50090
  const geminiMdPath = `${workspace}/GEMINI.md`;
49714
50091
  const marker = "<!-- adhdev-mesh-coordinator-prompt -->";
49715
50092
  const markerEnd = "<!-- /adhdev-mesh-coordinator-prompt -->";
49716
- const block = `${marker}
50093
+ const block2 = `${marker}
49717
50094
  ${cliCmdSystemPrompt}
49718
50095
  ${markerEnd}`;
49719
50096
  if (efs(geminiMdPath)) {
49720
50097
  const existing = rfs(geminiMdPath, "utf-8");
49721
50098
  const replaced = existing.replace(
49722
50099
  new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, "g"),
49723
- block
50100
+ block2
49724
50101
  );
49725
50102
  wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}
49726
50103
 
49727
- ${block}`);
50104
+ ${block2}`);
49728
50105
  } else {
49729
- wfs(geminiMdPath, block);
50106
+ wfs(geminiMdPath, block2);
49730
50107
  }
49731
50108
  LOG2.info("MeshCoordinator", `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
49732
50109
  } catch (e) {