adhdev 0.9.66 → 0.9.68

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/cli/index.js CHANGED
@@ -554,6 +554,22 @@ var init_source = __esm({
554
554
  }
555
555
  });
556
556
 
557
+ // ../../oss/packages/daemon-core/src/repo-mesh-types.ts
558
+ var DEFAULT_MESH_POLICY;
559
+ var init_repo_mesh_types = __esm({
560
+ "../../oss/packages/daemon-core/src/repo-mesh-types.ts"() {
561
+ "use strict";
562
+ DEFAULT_MESH_POLICY = {
563
+ requirePreTaskCheckpoint: false,
564
+ requirePostTaskCheckpoint: true,
565
+ requireApprovalForPush: true,
566
+ requireApprovalForDestructiveGit: true,
567
+ dirtyWorkspaceBehavior: "warn",
568
+ maxParallelTasks: 2
569
+ };
570
+ }
571
+ });
572
+
557
573
  // ../../oss/packages/daemon-core/src/git/git-executor.ts
558
574
  async function resolveGitRepository(workspace, options = {}) {
559
575
  const normalizedWorkspace = await validateWorkspace(workspace);
@@ -2682,12 +2698,343 @@ var init_saved_sessions = __esm({
2682
2698
  }
2683
2699
  });
2684
2700
 
2701
+ // ../../oss/packages/daemon-core/src/config/mesh-config.ts
2702
+ var mesh_config_exports = {};
2703
+ __export(mesh_config_exports, {
2704
+ addNode: () => addNode,
2705
+ createMesh: () => createMesh,
2706
+ deleteMesh: () => deleteMesh,
2707
+ getMesh: () => getMesh,
2708
+ getMeshByRepo: () => getMeshByRepo,
2709
+ listMeshes: () => listMeshes,
2710
+ normalizeRepoIdentity: () => normalizeRepoIdentity,
2711
+ removeNode: () => removeNode,
2712
+ updateMesh: () => updateMesh,
2713
+ updateNode: () => updateNode
2714
+ });
2715
+ function getMeshConfigPath() {
2716
+ return (0, import_path2.join)(getConfigDir(), "meshes.json");
2717
+ }
2718
+ function loadMeshConfig() {
2719
+ const path40 = getMeshConfigPath();
2720
+ if (!(0, import_fs2.existsSync)(path40)) return { meshes: [] };
2721
+ try {
2722
+ const raw = JSON.parse((0, import_fs2.readFileSync)(path40, "utf-8"));
2723
+ if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
2724
+ return raw;
2725
+ } catch {
2726
+ return { meshes: [] };
2727
+ }
2728
+ }
2729
+ function saveMeshConfig(config2) {
2730
+ const path40 = getMeshConfigPath();
2731
+ (0, import_fs2.writeFileSync)(path40, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
2732
+ }
2733
+ function normalizeRepoIdentity(remoteUrl) {
2734
+ let identity = remoteUrl.trim();
2735
+ if (identity.startsWith("http://") || identity.startsWith("https://")) {
2736
+ try {
2737
+ const url2 = new URL(identity);
2738
+ const path40 = url2.pathname.replace(/^\//, "").replace(/\.git$/, "");
2739
+ return `${url2.hostname}/${path40}`;
2740
+ } catch {
2741
+ }
2742
+ }
2743
+ const sshMatch = identity.match(/^(?:ssh:\/\/)?[\w.-]+@([\w.-]+)[:/]([\w.\-/]+?)(?:\.git)?$/);
2744
+ if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
2745
+ return identity;
2746
+ }
2747
+ function listMeshes() {
2748
+ return loadMeshConfig().meshes;
2749
+ }
2750
+ function getMesh(meshId) {
2751
+ return loadMeshConfig().meshes.find((m) => m.id === meshId);
2752
+ }
2753
+ function getMeshByRepo(repoIdentity) {
2754
+ return loadMeshConfig().meshes.find((m) => m.repoIdentity === repoIdentity);
2755
+ }
2756
+ function createMesh(opts) {
2757
+ const config2 = loadMeshConfig();
2758
+ if (config2.meshes.length >= 20) {
2759
+ throw new Error("Maximum 20 meshes allowed");
2760
+ }
2761
+ const repoIdentity = opts.repoIdentity || (opts.repoRemoteUrl ? normalizeRepoIdentity(opts.repoRemoteUrl) : "");
2762
+ if (!repoIdentity) throw new Error("Either repoRemoteUrl or repoIdentity is required");
2763
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2764
+ const mesh = {
2765
+ id: `mesh_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
2766
+ name: opts.name.trim().slice(0, 100),
2767
+ repoIdentity,
2768
+ repoRemoteUrl: opts.repoRemoteUrl,
2769
+ defaultBranch: opts.defaultBranch,
2770
+ policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
2771
+ coordinator: opts.coordinator || {},
2772
+ nodes: [],
2773
+ createdAt: now,
2774
+ updatedAt: now
2775
+ };
2776
+ config2.meshes.push(mesh);
2777
+ saveMeshConfig(config2);
2778
+ return mesh;
2779
+ }
2780
+ function updateMesh(meshId, opts) {
2781
+ const config2 = loadMeshConfig();
2782
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2783
+ if (!mesh) return void 0;
2784
+ if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
2785
+ if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
2786
+ if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
2787
+ if (opts.coordinator) mesh.coordinator = opts.coordinator;
2788
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2789
+ saveMeshConfig(config2);
2790
+ return mesh;
2791
+ }
2792
+ function deleteMesh(meshId) {
2793
+ const config2 = loadMeshConfig();
2794
+ const idx = config2.meshes.findIndex((m) => m.id === meshId);
2795
+ if (idx === -1) return false;
2796
+ config2.meshes.splice(idx, 1);
2797
+ saveMeshConfig(config2);
2798
+ return true;
2799
+ }
2800
+ function addNode(meshId, opts) {
2801
+ const config2 = loadMeshConfig();
2802
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2803
+ if (!mesh) return void 0;
2804
+ if (mesh.nodes.length >= 10) {
2805
+ throw new Error("Maximum 10 nodes per mesh");
2806
+ }
2807
+ if (mesh.nodes.some((n) => n.workspace === opts.workspace)) {
2808
+ throw new Error("This workspace is already in the mesh");
2809
+ }
2810
+ const node = {
2811
+ id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
2812
+ workspace: opts.workspace.trim(),
2813
+ repoRoot: opts.repoRoot,
2814
+ userOverrides: opts.userOverrides || {},
2815
+ policy: opts.policy || {},
2816
+ isLocalWorktree: opts.isLocalWorktree
2817
+ };
2818
+ mesh.nodes.push(node);
2819
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2820
+ saveMeshConfig(config2);
2821
+ return node;
2822
+ }
2823
+ function removeNode(meshId, nodeId) {
2824
+ const config2 = loadMeshConfig();
2825
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2826
+ if (!mesh) return false;
2827
+ const idx = mesh.nodes.findIndex((n) => n.id === nodeId);
2828
+ if (idx === -1) return false;
2829
+ mesh.nodes.splice(idx, 1);
2830
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2831
+ saveMeshConfig(config2);
2832
+ return true;
2833
+ }
2834
+ function updateNode(meshId, nodeId, opts) {
2835
+ const config2 = loadMeshConfig();
2836
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2837
+ if (!mesh) return void 0;
2838
+ const node = mesh.nodes.find((n) => n.id === nodeId);
2839
+ if (!node) return void 0;
2840
+ if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
2841
+ if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
2842
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2843
+ saveMeshConfig(config2);
2844
+ return node;
2845
+ }
2846
+ var import_fs2, import_path2, import_crypto3;
2847
+ var init_mesh_config = __esm({
2848
+ "../../oss/packages/daemon-core/src/config/mesh-config.ts"() {
2849
+ "use strict";
2850
+ import_fs2 = require("fs");
2851
+ import_path2 = require("path");
2852
+ import_crypto3 = require("crypto");
2853
+ init_config();
2854
+ init_repo_mesh_types();
2855
+ }
2856
+ });
2857
+
2858
+ // ../../oss/packages/daemon-core/src/mesh/coordinator-prompt.ts
2859
+ var coordinator_prompt_exports = {};
2860
+ __export(coordinator_prompt_exports, {
2861
+ buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
2862
+ });
2863
+ function buildCoordinatorSystemPrompt(ctx) {
2864
+ const { mesh, status, userInstruction } = ctx;
2865
+ const sections = [];
2866
+ sections.push(`You are a **Repo Mesh Coordinator** \u2014 a technical team lead who orchestrates work across multiple agent sessions on a shared Git repository.
2867
+
2868
+ Your mesh: **${mesh.name}**
2869
+ Repository: \`${mesh.repoIdentity}\`${mesh.defaultBranch ? `
2870
+ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
2871
+ if (status?.nodes?.length) {
2872
+ sections.push(buildNodeStatusSection(status.nodes));
2873
+ } else if (mesh.nodes.length) {
2874
+ sections.push(buildNodeConfigSection(mesh));
2875
+ } else {
2876
+ sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
2877
+ }
2878
+ sections.push(buildPolicySection(mesh.policy));
2879
+ sections.push(TOOLS_SECTION);
2880
+ sections.push(WORKFLOW_SECTION);
2881
+ sections.push(RULES_SECTION);
2882
+ if (userInstruction) {
2883
+ sections.push(`## Additional Context
2884
+ ${userInstruction}`);
2885
+ }
2886
+ if (mesh.coordinator.systemPromptSuffix) {
2887
+ sections.push(mesh.coordinator.systemPromptSuffix);
2888
+ }
2889
+ return sections.join("\n\n");
2890
+ }
2891
+ function buildNodeStatusSection(nodes) {
2892
+ const lines = ["## Current Node Status", ""];
2893
+ for (const n of nodes) {
2894
+ const healthIcon = n.health === "online" ? "\u{1F7E2}" : n.health === "dirty" ? "\u{1F7E1}" : n.health === "offline" ? "\u26AB" : "\u{1F534}";
2895
+ const sessions = n.activeSessions.length > 0 ? `sessions: ${n.activeSessions.join(", ")}` : "no active sessions";
2896
+ const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : "";
2897
+ lines.push(`- ${healthIcon} **${n.machineLabel}** (${n.nodeId})`);
2898
+ lines.push(` workspace: \`${n.workspace}\` | ${branch} | ${sessions}`);
2899
+ if (n.error) lines.push(` \u26A0\uFE0F ${n.error}`);
2900
+ }
2901
+ return lines.join("\n");
2902
+ }
2903
+ function buildNodeConfigSection(mesh) {
2904
+ const lines = ["## Configured Nodes", ""];
2905
+ for (const n of mesh.nodes) {
2906
+ const labels = [];
2907
+ if (n.isLocalWorktree) labels.push("worktree");
2908
+ if (n.policy.readOnly) labels.push("read-only");
2909
+ const suffix = labels.length ? ` [${labels.join(", ")}]` : "";
2910
+ lines.push(`- **${n.workspace}** (${n.id})${suffix}`);
2911
+ }
2912
+ lines.push("", "_Use `mesh_status` to probe live health before delegating work._");
2913
+ return lines.join("\n");
2914
+ }
2915
+ function buildPolicySection(policy) {
2916
+ const rules = [];
2917
+ if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
2918
+ if (policy.requirePostTaskCheckpoint) rules.push("- Create a git checkpoint **after** each task completes");
2919
+ if (policy.requireApprovalForPush) rules.push("- **Ask for user approval** before pushing to remote");
2920
+ if (policy.requireApprovalForDestructiveGit) rules.push("- **Ask for user approval** before destructive git operations (force push, reset, etc.)");
2921
+ const dirtyBehavior = {
2922
+ block: "- **Do not** send tasks to nodes with dirty workspaces",
2923
+ warn: "- Warn the user if a node has uncommitted changes before sending a task",
2924
+ checkpoint_then_continue: "- Auto-checkpoint dirty nodes before sending tasks"
2925
+ }[policy.dirtyWorkspaceBehavior] || "";
2926
+ if (dirtyBehavior) rules.push(dirtyBehavior);
2927
+ rules.push(`- Maximum **${policy.maxParallelTasks}** tasks running in parallel`);
2928
+ return `## Policy
2929
+ ${rules.join("\n")}`;
2930
+ }
2931
+ var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
2932
+ var init_coordinator_prompt = __esm({
2933
+ "../../oss/packages/daemon-core/src/mesh/coordinator-prompt.ts"() {
2934
+ "use strict";
2935
+ TOOLS_SECTION = `## Available Tools
2936
+
2937
+ | Tool | Purpose |
2938
+ |------|---------|
2939
+ | \`mesh_status\` | Check all nodes' health, git state, and active sessions |
2940
+ | \`mesh_list_nodes\` | List nodes with workspace paths |
2941
+ | \`mesh_launch_session\` | Start a new agent session on a node |
2942
+ | \`mesh_send_task\` | Send a task (natural language) to a running agent |
2943
+ | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
2944
+ | \`mesh_git_status\` | Check git status on a specific node |
2945
+ | \`mesh_checkpoint\` | Create a git checkpoint on a node |
2946
+ | \`mesh_approve\` | Approve/reject a pending agent action |`;
2947
+ WORKFLOW_SECTION = `## Orchestration Workflow
2948
+
2949
+ 1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
2950
+ 2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
2951
+ 3. **Delegate** \u2014 For each task:
2952
+ a. Pick the best node (consider: health, dirty state, current workload).
2953
+ b. If no session exists, call \`mesh_launch_session\` to start one.
2954
+ c. Call \`mesh_send_task\` with a clear, self-contained natural-language instruction.
2955
+ 4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
2956
+ 5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
2957
+ 6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
2958
+ 7. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
2959
+ RULES_SECTION = `## Rules
2960
+
2961
+ - **Be conversational.** Delegate work the way a tech lead would \u2014 clear, specific instructions in natural language.
2962
+ - **Don't inspect code.** Trust the agent's output. Verify via git diff/status, not by reading source files.
2963
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
2964
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
2965
+ - **Keep the user informed.** Report progress after each delegation round.
2966
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
2967
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
2968
+ }
2969
+ });
2970
+
2971
+ // ../../oss/packages/daemon-core/src/mesh/mesh-sync.ts
2972
+ async function syncMeshes(transport) {
2973
+ const result = { pushed: 0, pulled: 0, deleted: 0, errors: [] };
2974
+ let remoteMeshes;
2975
+ try {
2976
+ const res = await transport.listRemoteMeshes();
2977
+ remoteMeshes = res.meshes;
2978
+ } catch (e) {
2979
+ result.errors.push(`Failed to list remote meshes: ${e.message}`);
2980
+ return result;
2981
+ }
2982
+ const localMeshes = listMeshes();
2983
+ const remoteByIdentity = new Map(remoteMeshes.map((m) => [m.repo_identity, m]));
2984
+ const localByIdentity = new Map(localMeshes.map((m) => [m.repoIdentity, m]));
2985
+ for (const local of localMeshes) {
2986
+ if (!remoteByIdentity.has(local.repoIdentity)) {
2987
+ try {
2988
+ await transport.createRemoteMesh({
2989
+ name: local.name,
2990
+ repo_identity: local.repoIdentity,
2991
+ repo_remote_url: local.repoRemoteUrl,
2992
+ default_branch: local.defaultBranch,
2993
+ policy: JSON.stringify(local.policy)
2994
+ });
2995
+ result.pushed++;
2996
+ } catch (e) {
2997
+ result.errors.push(`Push failed for "${local.name}": ${e.message}`);
2998
+ }
2999
+ }
3000
+ }
3001
+ for (const remote of remoteMeshes) {
3002
+ if (!localByIdentity.has(remote.repo_identity)) {
3003
+ try {
3004
+ let policy;
3005
+ try {
3006
+ policy = JSON.parse(remote.policy);
3007
+ } catch {
3008
+ policy = void 0;
3009
+ }
3010
+ createMesh({
3011
+ name: remote.name,
3012
+ repoIdentity: remote.repo_identity,
3013
+ repoRemoteUrl: remote.repo_remote_url || void 0,
3014
+ defaultBranch: remote.default_branch || void 0,
3015
+ policy
3016
+ });
3017
+ result.pulled++;
3018
+ } catch (e) {
3019
+ result.errors.push(`Pull failed for "${remote.name}": ${e.message}`);
3020
+ }
3021
+ }
3022
+ }
3023
+ return result;
3024
+ }
3025
+ var init_mesh_sync = __esm({
3026
+ "../../oss/packages/daemon-core/src/mesh/mesh-sync.ts"() {
3027
+ "use strict";
3028
+ init_mesh_config();
3029
+ }
3030
+ });
3031
+
2685
3032
  // ../../oss/packages/daemon-core/src/config/state-store.ts
2686
3033
  function isPlainObject2(value) {
2687
3034
  return !!value && typeof value === "object" && !Array.isArray(value);
2688
3035
  }
2689
3036
  function getStatePath() {
2690
- return (0, import_path2.join)(getConfigDir(), "state.json");
3037
+ return (0, import_path3.join)(getConfigDir(), "state.json");
2691
3038
  }
2692
3039
  function normalizeState(raw) {
2693
3040
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -2723,11 +3070,11 @@ function normalizeState(raw) {
2723
3070
  }
2724
3071
  function loadState() {
2725
3072
  const statePath = getStatePath();
2726
- if (!(0, import_fs2.existsSync)(statePath)) {
3073
+ if (!(0, import_fs3.existsSync)(statePath)) {
2727
3074
  return { ...DEFAULT_STATE };
2728
3075
  }
2729
3076
  try {
2730
- const raw = (0, import_fs2.readFileSync)(statePath, "utf-8");
3077
+ const raw = (0, import_fs3.readFileSync)(statePath, "utf-8");
2731
3078
  return normalizeState(JSON.parse(raw));
2732
3079
  } catch {
2733
3080
  return { ...DEFAULT_STATE };
@@ -2736,17 +3083,17 @@ function loadState() {
2736
3083
  function saveState(state) {
2737
3084
  const statePath = getStatePath();
2738
3085
  const normalized = normalizeState(state);
2739
- (0, import_fs2.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
3086
+ (0, import_fs3.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
2740
3087
  }
2741
3088
  function resetState() {
2742
3089
  saveState({ ...DEFAULT_STATE });
2743
3090
  }
2744
- var import_fs2, import_path2, DEFAULT_STATE;
3091
+ var import_fs3, import_path3, DEFAULT_STATE;
2745
3092
  var init_state_store = __esm({
2746
3093
  "../../oss/packages/daemon-core/src/config/state-store.ts"() {
2747
3094
  "use strict";
2748
- import_fs2 = require("fs");
2749
- import_path2 = require("path");
3095
+ import_fs3 = require("fs");
3096
+ import_path3 = require("path");
2750
3097
  init_config();
2751
3098
  DEFAULT_STATE = {
2752
3099
  recentActivity: [],
@@ -2779,7 +3126,7 @@ function findCliCommand(command) {
2779
3126
  if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
2780
3127
  const candidate = trimmed.startsWith("~") ? path7.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
2781
3128
  const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
2782
- return (0, import_fs3.existsSync)(resolved) ? resolved : null;
3129
+ return (0, import_fs4.existsSync)(resolved) ? resolved : null;
2783
3130
  }
2784
3131
  try {
2785
3132
  const result = (0, import_child_process.execSync)(
@@ -2810,9 +3157,9 @@ function checkPathExists(paths) {
2810
3157
  if (normalized.includes("*")) {
2811
3158
  const username = home.split(/[\\/]/).pop() || "";
2812
3159
  const resolved = normalized.replace("*", username);
2813
- if ((0, import_fs3.existsSync)(resolved)) return resolved;
3160
+ if ((0, import_fs4.existsSync)(resolved)) return resolved;
2814
3161
  } else {
2815
- if ((0, import_fs3.existsSync)(normalized)) return normalized;
3162
+ if ((0, import_fs4.existsSync)(normalized)) return normalized;
2816
3163
  }
2817
3164
  }
2818
3165
  return null;
@@ -2826,7 +3173,7 @@ async function detectIDEs(providerLoader) {
2826
3173
  let resolvedCli = cliPath;
2827
3174
  if (!resolvedCli && appPath && os31 === "darwin") {
2828
3175
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
2829
- if ((0, import_fs3.existsSync)(bundledCli)) resolvedCli = bundledCli;
3176
+ if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
2830
3177
  }
2831
3178
  if (!resolvedCli && appPath && os31 === "win32") {
2832
3179
  const { dirname: dirname11 } = await import("path");
@@ -2839,7 +3186,7 @@ async function detectIDEs(providerLoader) {
2839
3186
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
2840
3187
  ];
2841
3188
  for (const c of candidates) {
2842
- if ((0, import_fs3.existsSync)(c)) {
3189
+ if ((0, import_fs4.existsSync)(c)) {
2843
3190
  resolvedCli = c;
2844
3191
  break;
2845
3192
  }
@@ -2860,12 +3207,12 @@ async function detectIDEs(providerLoader) {
2860
3207
  }
2861
3208
  return results;
2862
3209
  }
2863
- var import_child_process, import_fs3, import_os2, path7, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
3210
+ var import_child_process, import_fs4, import_os2, path7, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
2864
3211
  var init_ide_detector = __esm({
2865
3212
  "../../oss/packages/daemon-core/src/detection/ide-detector.ts"() {
2866
3213
  "use strict";
2867
3214
  import_child_process = require("child_process");
2868
- import_fs3 = require("fs");
3215
+ import_fs4 = require("fs");
2869
3216
  import_os2 = require("os");
2870
3217
  path7 = __toESM(require("path"));
2871
3218
  BUILTIN_IDE_DEFINITIONS = [];
@@ -2897,7 +3244,7 @@ function resolveCommandPath(command) {
2897
3244
  if (isExplicitCommandPath(trimmed)) {
2898
3245
  const expanded = expandHome(trimmed);
2899
3246
  const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
2900
- return (0, import_fs4.existsSync)(candidate) ? candidate : null;
3247
+ return (0, import_fs5.existsSync)(candidate) ? candidate : null;
2901
3248
  }
2902
3249
  return null;
2903
3250
  }
@@ -2997,14 +3344,14 @@ async function detectCLI(cliId, providerLoader, options) {
2997
3344
  const all = await detectCLIs(providerLoader, options);
2998
3345
  return all.find((c) => c.id === resolvedId && c.installed) || null;
2999
3346
  }
3000
- var import_child_process2, os3, path8, import_fs4;
3347
+ var import_child_process2, os3, path8, import_fs5;
3001
3348
  var init_cli_detector = __esm({
3002
3349
  "../../oss/packages/daemon-core/src/detection/cli-detector.ts"() {
3003
3350
  "use strict";
3004
3351
  import_child_process2 = require("child_process");
3005
3352
  os3 = __toESM(require("os"));
3006
3353
  path8 = __toESM(require("path"));
3007
- import_fs4 = require("fs");
3354
+ import_fs5 = require("fs");
3008
3355
  }
3009
3356
  });
3010
3357
 
@@ -13173,16 +13520,16 @@ function ensureNodePtySpawnHelperPermissions(logFn) {
13173
13520
  } catch {
13174
13521
  }
13175
13522
  }
13176
- var import_crypto3, path13, os10, path22, net, import_crypto4, os22, path32, __require, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, SessionRingBuffer, DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
13523
+ var import_crypto4, path13, os10, path22, net, import_crypto5, os22, path32, __require, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, SessionRingBuffer, DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
13177
13524
  var init_dist = __esm({
13178
13525
  "../../oss/packages/session-host-core/dist/index.mjs"() {
13179
13526
  "use strict";
13180
- import_crypto3 = require("crypto");
13527
+ import_crypto4 = require("crypto");
13181
13528
  path13 = __toESM(require("path"), 1);
13182
13529
  os10 = __toESM(require("os"), 1);
13183
13530
  path22 = __toESM(require("path"), 1);
13184
13531
  net = __toESM(require("net"), 1);
13185
- import_crypto4 = require("crypto");
13532
+ import_crypto5 = require("crypto");
13186
13533
  os22 = __toESM(require("os"), 1);
13187
13534
  path32 = __toESM(require("path"), 1);
13188
13535
  __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -13258,7 +13605,7 @@ var init_dist = __esm({
13258
13605
  SessionHostRegistry = class {
13259
13606
  sessions = /* @__PURE__ */ new Map();
13260
13607
  createSession(payload) {
13261
- const sessionId = payload.sessionId || (0, import_crypto3.randomUUID)();
13608
+ const sessionId = payload.sessionId || (0, import_crypto4.randomUUID)();
13262
13609
  if (this.sessions.has(sessionId)) {
13263
13610
  throw new Error(`Session already exists: ${sessionId}`);
13264
13611
  }
@@ -13529,7 +13876,7 @@ var init_dist = __esm({
13529
13876
  async request(request) {
13530
13877
  await this.connect();
13531
13878
  if (!this.socket) throw new Error("Session host socket unavailable");
13532
- const requestId = (0, import_crypto4.randomUUID)();
13879
+ const requestId = (0, import_crypto5.randomUUID)();
13533
13880
  const envelope = {
13534
13881
  kind: "request",
13535
13882
  requestId,
@@ -34565,7 +34912,7 @@ function commandExists(command) {
34565
34912
  const trimmed = command.trim();
34566
34913
  if (!trimmed) return false;
34567
34914
  if (isExplicitCommand(trimmed)) {
34568
- return (0, import_fs5.existsSync)(expandExecutable(trimmed));
34915
+ return (0, import_fs6.existsSync)(expandExecutable(trimmed));
34569
34916
  }
34570
34917
  try {
34571
34918
  (0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -34696,14 +35043,14 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
34696
35043
  launchMode: "new"
34697
35044
  };
34698
35045
  }
34699
- var os16, path17, crypto4, import_fs5, import_child_process6, chalkModule, chalkApi, DaemonCliManager;
35046
+ var os16, path17, crypto4, import_fs6, import_child_process6, chalkModule, chalkApi, DaemonCliManager;
34700
35047
  var init_cli_manager = __esm({
34701
35048
  "../../oss/packages/daemon-core/src/commands/cli-manager.ts"() {
34702
35049
  "use strict";
34703
35050
  os16 = __toESM(require("os"));
34704
35051
  path17 = __toESM(require("path"));
34705
35052
  crypto4 = __toESM(require("crypto"));
34706
- import_fs5 = require("fs");
35053
+ import_fs6 = require("fs");
34707
35054
  import_child_process6 = require("child_process");
34708
35055
  init_source2();
34709
35056
  init_provider_cli_adapter();
@@ -38271,7 +38618,7 @@ var init_provider_loader = __esm({
38271
38618
  return { updated: false };
38272
38619
  }
38273
38620
  const https = require("https");
38274
- const { execSync: execSync8 } = require("child_process");
38621
+ const { execSync: execSync9 } = require("child_process");
38275
38622
  const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
38276
38623
  let prevEtag = "";
38277
38624
  let prevTimestamp = 0;
@@ -38336,7 +38683,7 @@ var init_provider_loader = __esm({
38336
38683
  const tmpExtract = path18.join(os17.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
38337
38684
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
38338
38685
  fs7.mkdirSync(tmpExtract, { recursive: true });
38339
- execSync8(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
38686
+ execSync9(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
38340
38687
  const extracted = fs7.readdirSync(tmpExtract);
38341
38688
  const rootDir = extracted.find(
38342
38689
  (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
@@ -40921,6 +41268,142 @@ var init_router = __esm({
40921
41268
  updateConfig({ machineNickname: nickname || null });
40922
41269
  return { success: true };
40923
41270
  }
41271
+ // ─── Mesh CRUD (local meshes.json) ───
41272
+ case "list_meshes": {
41273
+ try {
41274
+ const { listMeshes: listMeshes2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41275
+ return { success: true, meshes: listMeshes2() };
41276
+ } catch (e) {
41277
+ return { success: false, error: e.message };
41278
+ }
41279
+ }
41280
+ case "get_mesh": {
41281
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
41282
+ if (!meshId) return { success: false, error: "meshId required" };
41283
+ try {
41284
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41285
+ const mesh = getMesh3(meshId);
41286
+ if (!mesh) return { success: false, error: "Mesh not found" };
41287
+ return { success: true, mesh };
41288
+ } catch (e) {
41289
+ return { success: false, error: e.message };
41290
+ }
41291
+ }
41292
+ case "create_mesh": {
41293
+ const name = typeof args?.name === "string" ? args.name.trim() : "";
41294
+ const repoIdentity = typeof args?.repoIdentity === "string" ? args.repoIdentity.trim() : "";
41295
+ const repoRemoteUrl = typeof args?.repoRemoteUrl === "string" ? args.repoRemoteUrl.trim() : void 0;
41296
+ const defaultBranch = typeof args?.defaultBranch === "string" ? args.defaultBranch.trim() : void 0;
41297
+ if (!name) return { success: false, error: "name required" };
41298
+ try {
41299
+ const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41300
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
41301
+ return { success: true, mesh };
41302
+ } catch (e) {
41303
+ return { success: false, error: e.message };
41304
+ }
41305
+ }
41306
+ case "delete_mesh": {
41307
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
41308
+ if (!meshId) return { success: false, error: "meshId required" };
41309
+ try {
41310
+ const { deleteMesh: deleteMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41311
+ const deleted = deleteMesh3(meshId);
41312
+ return { success: true, deleted };
41313
+ } catch (e) {
41314
+ return { success: false, error: e.message };
41315
+ }
41316
+ }
41317
+ case "add_mesh_node": {
41318
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
41319
+ const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
41320
+ if (!meshId) return { success: false, error: "meshId required" };
41321
+ if (!workspace) return { success: false, error: "workspace required" };
41322
+ try {
41323
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41324
+ const node = addNode3(meshId, { workspace });
41325
+ if (!node) return { success: false, error: "Mesh not found" };
41326
+ return { success: true, node };
41327
+ } catch (e) {
41328
+ return { success: false, error: e.message };
41329
+ }
41330
+ }
41331
+ case "remove_mesh_node": {
41332
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
41333
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
41334
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
41335
+ try {
41336
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41337
+ const removed = removeNode3(meshId, nodeId);
41338
+ return { success: true, removed };
41339
+ } catch (e) {
41340
+ return { success: false, error: e.message };
41341
+ }
41342
+ }
41343
+ // ─── Mesh Coordinator Launch ───
41344
+ case "launch_mesh_coordinator": {
41345
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
41346
+ const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
41347
+ if (!meshId) return { success: false, error: "meshId required" };
41348
+ try {
41349
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
41350
+ const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
41351
+ const mesh = getMesh3(meshId);
41352
+ if (!mesh) return { success: false, error: "Mesh not found" };
41353
+ if (mesh.nodes.length === 0) return { success: false, error: "No nodes in mesh" };
41354
+ const workspace = mesh.nodes[0].workspace;
41355
+ const { existsSync: existsSync28, readFileSync: readFileSync21, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4 } = await import("fs");
41356
+ const { join: join35 } = await import("path");
41357
+ const mcpConfigPath = join35(workspace, ".mcp.json");
41358
+ const hadExistingMcpConfig = existsSync28(mcpConfigPath);
41359
+ let existingMcpConfig = {};
41360
+ if (hadExistingMcpConfig) {
41361
+ try {
41362
+ existingMcpConfig = JSON.parse(readFileSync21(mcpConfigPath, "utf-8"));
41363
+ copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
41364
+ } catch {
41365
+ }
41366
+ }
41367
+ const mcpConfig = {
41368
+ ...existingMcpConfig,
41369
+ mcpServers: {
41370
+ ...existingMcpConfig.mcpServers || {},
41371
+ "adhdev-mesh": {
41372
+ command: "adhdev-mcp",
41373
+ args: ["--repo-mesh", meshId]
41374
+ }
41375
+ }
41376
+ };
41377
+ writeFileSync15(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
41378
+ LOG.info("MeshCoordinator", `Wrote .mcp.json to ${workspace} with adhdev-mesh server`);
41379
+ let systemPrompt = "";
41380
+ try {
41381
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
41382
+ } catch {
41383
+ systemPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}". Use the adhdev-mesh MCP tools (mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, etc.) to orchestrate work across ${mesh.nodes.length} node(s).`;
41384
+ }
41385
+ const launchResult = await this.deps.cliManager.handleCliCommand("launch_cli", {
41386
+ cliType,
41387
+ dir: workspace,
41388
+ initialPrompt: systemPrompt
41389
+ });
41390
+ if (!launchResult?.success) {
41391
+ return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
41392
+ }
41393
+ LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
41394
+ return {
41395
+ success: true,
41396
+ meshId,
41397
+ cliType,
41398
+ workspace,
41399
+ sessionId: launchResult.sessionId || launchResult.id,
41400
+ mcpConfigWritten: true
41401
+ };
41402
+ } catch (e) {
41403
+ LOG.error("MeshCoordinator", `Failed: ${e.message}`);
41404
+ return { success: false, error: e.message };
41405
+ }
41406
+ }
40924
41407
  default:
40925
41408
  break;
40926
41409
  }
@@ -49059,6 +49542,7 @@ __export(src_exports, {
49059
49542
  DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
49060
49543
  DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
49061
49544
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
49545
+ DEFAULT_MESH_POLICY: () => DEFAULT_MESH_POLICY,
49062
49546
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
49063
49547
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
49064
49548
  DEFAULT_SESSION_HOST_READY_TIMEOUT_MS: () => DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
@@ -49092,11 +49576,13 @@ __export(src_exports, {
49092
49576
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory,
49093
49577
  TurnSnapshotTracker: () => TurnSnapshotTracker,
49094
49578
  VersionArchive: () => VersionArchive,
49579
+ addNode: () => addNode,
49095
49580
  appendRecentActivity: () => appendRecentActivity,
49096
49581
  buildAssistantChatMessage: () => buildAssistantChatMessage,
49097
49582
  buildChatMessage: () => buildChatMessage,
49098
49583
  buildChatMessageSignature: () => buildChatMessageSignature,
49099
49584
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
49585
+ buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
49100
49586
  buildMachineInfo: () => buildMachineInfo,
49101
49587
  buildPinnedGlobalInstallCommand: () => buildPinnedGlobalInstallCommand,
49102
49588
  buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
@@ -49119,6 +49605,8 @@ __export(src_exports, {
49119
49605
  createGitSnapshotStore: () => createGitSnapshotStore,
49120
49606
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
49121
49607
  createInteractionId: () => createInteractionId,
49608
+ createMesh: () => createMesh,
49609
+ deleteMesh: () => deleteMesh,
49122
49610
  detectAllVersions: () => detectAllVersions,
49123
49611
  detectCLIs: () => detectCLIs,
49124
49612
  detectIDEs: () => detectIDEs,
@@ -49137,6 +49625,8 @@ __export(src_exports, {
49137
49625
  getGitRepoStatus: () => getGitRepoStatus,
49138
49626
  getHostMemorySnapshot: () => getHostMemorySnapshot,
49139
49627
  getLogLevel: () => getLogLevel,
49628
+ getMesh: () => getMesh,
49629
+ getMeshByRepo: () => getMeshByRepo,
49140
49630
  getNpmExecOptions: () => getNpmExecOptions,
49141
49631
  getRecentActivity: () => getRecentActivity,
49142
49632
  getRecentCommands: () => getRecentCommands,
@@ -49167,6 +49657,7 @@ __export(src_exports, {
49167
49657
  launchIDE: () => launchIDE,
49168
49658
  launchWithCdp: () => launchWithCdp,
49169
49659
  listHostedCliRuntimes: () => listHostedCliRuntimes,
49660
+ listMeshes: () => listMeshes,
49170
49661
  loadConfig: () => loadConfig,
49171
49662
  loadState: () => loadState,
49172
49663
  logCommand: () => logCommand,
@@ -49182,6 +49673,7 @@ __export(src_exports, {
49182
49673
  normalizeInputEnvelope: () => normalizeInputEnvelope,
49183
49674
  normalizeManagedStatus: () => normalizeManagedStatus,
49184
49675
  normalizeMessageParts: () => normalizeMessageParts,
49676
+ normalizeRepoIdentity: () => normalizeRepoIdentity,
49185
49677
  normalizeSessionModalFields: () => normalizeSessionModalFields,
49186
49678
  parsePorcelainV2Status: () => parsePorcelainV2Status,
49187
49679
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
@@ -49193,6 +49685,7 @@ __export(src_exports, {
49193
49685
  readChatHistory: () => readChatHistory,
49194
49686
  recordDebugTrace: () => recordDebugTrace,
49195
49687
  registerExtensionProviders: () => registerExtensionProviders,
49688
+ removeNode: () => removeNode,
49196
49689
  resetConfig: () => resetConfig,
49197
49690
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
49198
49691
  resetState: () => resetState,
@@ -49215,17 +49708,24 @@ __export(src_exports, {
49215
49708
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
49216
49709
  startDaemonDevSupport: () => startDaemonDevSupport,
49217
49710
  summarizeGitStatus: () => summarizeGitStatus,
49711
+ syncMeshes: () => syncMeshes,
49218
49712
  updateConfig: () => updateConfig,
49713
+ updateMesh: () => updateMesh,
49714
+ updateNode: () => updateNode,
49219
49715
  upsertSavedProviderSession: () => upsertSavedProviderSession
49220
49716
  });
49221
49717
  var init_src = __esm({
49222
49718
  "../../oss/packages/daemon-core/src/index.ts"() {
49223
49719
  "use strict";
49720
+ init_repo_mesh_types();
49224
49721
  init_git();
49225
49722
  init_config();
49226
49723
  init_workspaces();
49227
49724
  init_recent_activity();
49228
49725
  init_saved_sessions();
49726
+ init_mesh_config();
49727
+ init_coordinator_prompt();
49728
+ init_mesh_sync();
49229
49729
  init_state_store();
49230
49730
  init_ide_detector();
49231
49731
  init_cli_detector();
@@ -64071,7 +64571,7 @@ var require_buffer_list = __commonJS({
64071
64571
  }
64072
64572
  }, {
64073
64573
  key: "join",
64074
- value: function join34(s) {
64574
+ value: function join35(s) {
64075
64575
  if (this.length === 0) return "";
64076
64576
  var p = this.head;
64077
64577
  var ret = "" + p.data;
@@ -78130,13 +78630,13 @@ function splitStringBySpace(str) {
78130
78630
  }
78131
78631
  return pieces;
78132
78632
  }
78133
- var import_chardet, import_child_process12, import_fs6, import_node_path2, import_node_os4, import_node_crypto2, import_iconv_lite, ExternalEditor;
78633
+ var import_chardet, import_child_process12, import_fs7, import_node_path2, import_node_os4, import_node_crypto2, import_iconv_lite, ExternalEditor;
78134
78634
  var init_esm2 = __esm({
78135
78635
  "../../node_modules/@inquirer/external-editor/dist/esm/index.js"() {
78136
78636
  "use strict";
78137
78637
  import_chardet = __toESM(require_lib(), 1);
78138
78638
  import_child_process12 = require("child_process");
78139
- import_fs6 = require("fs");
78639
+ import_fs7 = require("fs");
78140
78640
  import_node_path2 = __toESM(require("path"), 1);
78141
78641
  import_node_os4 = __toESM(require("os"), 1);
78142
78642
  import_node_crypto2 = require("crypto");
@@ -78212,14 +78712,14 @@ var init_esm2 = __esm({
78212
78712
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
78213
78713
  opt.mode = this.fileOptions.mode;
78214
78714
  }
78215
- (0, import_fs6.writeFileSync)(this.tempFile, this.text, opt);
78715
+ (0, import_fs7.writeFileSync)(this.tempFile, this.text, opt);
78216
78716
  } catch (createFileError) {
78217
78717
  throw new CreateFileError(createFileError);
78218
78718
  }
78219
78719
  }
78220
78720
  readTemporaryFile() {
78221
78721
  try {
78222
- const tempFileBuffer = (0, import_fs6.readFileSync)(this.tempFile);
78722
+ const tempFileBuffer = (0, import_fs7.readFileSync)(this.tempFile);
78223
78723
  if (tempFileBuffer.length === 0) {
78224
78724
  this.text = "";
78225
78725
  } else {
@@ -78235,7 +78735,7 @@ var init_esm2 = __esm({
78235
78735
  }
78236
78736
  removeTemporaryFile() {
78237
78737
  try {
78238
- (0, import_fs6.unlinkSync)(this.tempFile);
78738
+ (0, import_fs7.unlinkSync)(this.tempFile);
78239
78739
  } catch (removeFileError) {
78240
78740
  throw new RemoveFileError(removeFileError);
78241
78741
  }
@@ -79937,25 +80437,25 @@ function resolvePackageVersion(options) {
79937
80437
  const injectedVersion = options?.injectedVersion || "unknown";
79938
80438
  const dir = options?.dirname || __dirname;
79939
80439
  const possiblePaths = [
79940
- (0, import_path3.join)(dir, "..", "..", "package.json"),
79941
- (0, import_path3.join)(dir, "..", "package.json"),
79942
- (0, import_path3.join)(dir, "package.json")
80440
+ (0, import_path4.join)(dir, "..", "..", "package.json"),
80441
+ (0, import_path4.join)(dir, "..", "package.json"),
80442
+ (0, import_path4.join)(dir, "package.json")
79943
80443
  ];
79944
80444
  for (const p of possiblePaths) {
79945
80445
  try {
79946
- const data = JSON.parse((0, import_fs7.readFileSync)(p, "utf-8"));
80446
+ const data = JSON.parse((0, import_fs8.readFileSync)(p, "utf-8"));
79947
80447
  if (data.version) return data.version;
79948
80448
  } catch {
79949
80449
  }
79950
80450
  }
79951
80451
  return injectedVersion;
79952
80452
  }
79953
- var import_fs7, import_path3;
80453
+ var import_fs8, import_path4;
79954
80454
  var init_version = __esm({
79955
80455
  "src/version.ts"() {
79956
80456
  "use strict";
79957
- import_fs7 = require("fs");
79958
- import_path3 = require("path");
80457
+ import_fs8 = require("fs");
80458
+ import_path4 = require("path");
79959
80459
  }
79960
80460
  });
79961
80461
 
@@ -81873,7 +82373,7 @@ var require_filesystem = __commonJS({
81873
82373
  var LDD_PATH = "/usr/bin/ldd";
81874
82374
  var SELF_PATH = "/proc/self/exe";
81875
82375
  var MAX_LENGTH = 2048;
81876
- var readFileSync20 = (path40) => {
82376
+ var readFileSync21 = (path40) => {
81877
82377
  const fd = fs24.openSync(path40, "r");
81878
82378
  const buffer = Buffer.alloc(MAX_LENGTH);
81879
82379
  const bytesRead = fs24.readSync(fd, buffer, 0, MAX_LENGTH, 0);
@@ -81898,7 +82398,7 @@ var require_filesystem = __commonJS({
81898
82398
  module2.exports = {
81899
82399
  LDD_PATH,
81900
82400
  SELF_PATH,
81901
- readFileSync: readFileSync20,
82401
+ readFileSync: readFileSync21,
81902
82402
  readFile: readFile2
81903
82403
  };
81904
82404
  }
@@ -81947,7 +82447,7 @@ var require_detect_libc = __commonJS({
81947
82447
  "use strict";
81948
82448
  var childProcess = require("child_process");
81949
82449
  var { isLinux: isLinux2, getReport } = require_process();
81950
- var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync20 } = require_filesystem();
82450
+ var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync21 } = require_filesystem();
81951
82451
  var { interpreterPath } = require_elf();
81952
82452
  var cachedFamilyInterpreter;
81953
82453
  var cachedFamilyFilesystem;
@@ -82039,7 +82539,7 @@ var require_detect_libc = __commonJS({
82039
82539
  }
82040
82540
  cachedFamilyFilesystem = null;
82041
82541
  try {
82042
- const lddContent = readFileSync20(LDD_PATH);
82542
+ const lddContent = readFileSync21(LDD_PATH);
82043
82543
  cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
82044
82544
  } catch (e) {
82045
82545
  }
@@ -82064,7 +82564,7 @@ var require_detect_libc = __commonJS({
82064
82564
  }
82065
82565
  cachedFamilyInterpreter = null;
82066
82566
  try {
82067
- const selfContent = readFileSync20(SELF_PATH);
82567
+ const selfContent = readFileSync21(SELF_PATH);
82068
82568
  const path40 = interpreterPath(selfContent);
82069
82569
  cachedFamilyInterpreter = familyFromInterpreterPath(path40);
82070
82570
  } catch (e) {
@@ -82128,7 +82628,7 @@ var require_detect_libc = __commonJS({
82128
82628
  }
82129
82629
  cachedVersionFilesystem = null;
82130
82630
  try {
82131
- const lddContent = readFileSync20(LDD_PATH);
82631
+ const lddContent = readFileSync21(LDD_PATH);
82132
82632
  const versionMatch = lddContent.match(RE_GLIBC_VERSION);
82133
82633
  if (versionMatch) {
82134
82634
  cachedVersionFilesystem = versionMatch[1];
@@ -89392,7 +89892,7 @@ var init_adhdev_daemon = __esm({
89392
89892
  init_version();
89393
89893
  init_src();
89394
89894
  init_runtime_defaults();
89395
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.66" });
89895
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.68" });
89396
89896
  AdhdevDaemon = class _AdhdevDaemon {
89397
89897
  localHttpServer = null;
89398
89898
  localWss = null;
@@ -90884,20 +91384,20 @@ async function startDaemonFlow() {
90884
91384
  try {
90885
91385
  const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
90886
91386
  const daemon = new AdhdevDaemon2();
90887
- const { execSync: execSync8 } = await import("child_process");
91387
+ const { execSync: execSync9 } = await import("child_process");
90888
91388
  const { getCurrentDaemonLogPath: getCurrentDaemonLogPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
90889
91389
  const logPath = getCurrentDaemonLogPath2();
90890
91390
  const os31 = await import("os");
90891
91391
  const platform12 = os31.platform();
90892
91392
  try {
90893
91393
  if (platform12 === "win32") {
90894
- execSync8("start /B adhdev daemon >NUL 2>&1", {
91394
+ execSync9("start /B adhdev daemon >NUL 2>&1", {
90895
91395
  timeout: 3e3,
90896
91396
  stdio: "ignore",
90897
91397
  shell: "cmd.exe"
90898
91398
  });
90899
91399
  } else {
90900
- execSync8("nohup adhdev daemon >/dev/null 2>&1 &", {
91400
+ execSync9("nohup adhdev daemon >/dev/null 2>&1 &", {
90901
91401
  timeout: 3e3,
90902
91402
  stdio: "ignore"
90903
91403
  });
@@ -93336,7 +93836,7 @@ async function handleTraceCommand(options) {
93336
93836
  async function runDaemonUpgrade(options, pkgVersion3) {
93337
93837
  const { isDaemonRunning: isDaemonRunning2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
93338
93838
  const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
93339
- const { execSync: execSync8, spawn: spawn7 } = await import("child_process");
93839
+ const { execSync: execSync9, spawn: spawn7 } = await import("child_process");
93340
93840
  const fsMod = await import("fs");
93341
93841
  const pathMod = await import("path");
93342
93842
  console.log(source_default.bold("\n \u{1F504} ADHDev Upgrade\n"));
@@ -93356,10 +93856,10 @@ async function runDaemonUpgrade(options, pkgVersion3) {
93356
93856
  while (!fsMod.existsSync(pathMod.join(gitRoot, ".git")) && gitRoot !== "/") {
93357
93857
  gitRoot = pathMod.dirname(gitRoot);
93358
93858
  }
93359
- execSync8("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
93859
+ execSync9("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
93360
93860
  console.log(source_default.cyan("\n Building..."));
93361
- execSync8("npm run build", { cwd: launcherDir, stdio: "inherit" });
93362
- execSync8("npm link", { cwd: launcherDir, stdio: "inherit" });
93861
+ execSync9("npm run build", { cwd: launcherDir, stdio: "inherit" });
93862
+ execSync9("npm link", { cwd: launcherDir, stdio: "inherit" });
93363
93863
  console.log(source_default.green("\n \u2713 Build complete"));
93364
93864
  } catch (e) {
93365
93865
  console.log(source_default.red(`
@@ -93467,7 +93967,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
93467
93967
  }
93468
93968
  });
93469
93969
  program2.command("standalone").description("\u{1F5A5}\uFE0F Start ADHDev Standalone Server (Local Dashboard & Embedded Daemon)").option("-p, --port <port>", "Local HTTP/WS server port", "3847").option("--host <host>", "Bind to specific host (use 0.0.0.0 for LAN access)").option("--no-open", "Prevent opening browser automatically").option("--token <token>", "Require token authentication").option("--dev", "Enable Dev Mode").action(async (options) => {
93470
- const { spawn: spawn7, execSync: execSync8 } = await import("child_process");
93970
+ const { spawn: spawn7, execSync: execSync9 } = await import("child_process");
93471
93971
  const { DEFAULT_STANDALONE_SESSION_HOST_APP_NAME: DEFAULT_STANDALONE_SESSION_HOST_APP_NAME2, resolveSessionHostAppNameResolution: resolveSessionHostAppNameResolution2 } = await Promise.resolve().then(() => (init_src(), src_exports));
93472
93972
  console.log(source_default.cyan("\n Starting ADHDev Standalone Server..."));
93473
93973
  const args = [];
@@ -93485,7 +93985,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
93485
93985
  let bin = "npx";
93486
93986
  const npxArgs = ["-y", "@adhdev/daemon-standalone@latest", ...args];
93487
93987
  try {
93488
- execSync8("adhdev-standalone --help", { stdio: "ignore" });
93988
+ execSync9("adhdev-standalone --help", { stdio: "ignore" });
93489
93989
  bin = "adhdev-standalone";
93490
93990
  } catch {
93491
93991
  console.log(source_default.gray(" Standalone server package not found locally."));
@@ -95993,7 +96493,7 @@ var import_node_module3 = require("module");
95993
96493
  var path39 = __toESM(require("path"));
95994
96494
  init_source();
95995
96495
  function registerMcpCommands(program2) {
95996
- program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").addHelpText("after", `
96496
+ program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").option("--repo-mesh <mesh_id>", "Start in mesh mode (coordinator-scoped tools)").addHelpText("after", `
95997
96497
  Examples:
95998
96498
  adhdev mcp Local mode (requires: adhdev standalone)
95999
96499
  adhdev mcp --api-key adk_xxx Cloud mode (no local daemon needed)
@@ -96021,6 +96521,7 @@ Tools available (cloud): list_daemons, list_sessions, launch_session, stop_sess
96021
96521
  if (opts.port && opts.port !== "3847") args.push("--port", opts.port);
96022
96522
  if (opts.password) args.push("--password", opts.password);
96023
96523
  if (opts.baseUrl) args.push("--base-url", opts.baseUrl);
96524
+ if (opts.repoMesh) args.push("--repo-mesh", opts.repoMesh);
96024
96525
  const env3 = { ...process.env };
96025
96526
  if (opts.apiKey) env3.ADHDEV_API_KEY = opts.apiKey;
96026
96527
  if (opts.password) env3.ADHDEV_PASSWORD = opts.password;
@@ -96055,6 +96556,283 @@ function resolveMcpBin() {
96055
96556
  }
96056
96557
  }
96057
96558
 
96559
+ // src/cli/mesh-commands.ts
96560
+ init_source();
96561
+ var import_node_child_process4 = require("child_process");
96562
+ init_src();
96563
+ function registerMeshCommands(program2) {
96564
+ const mesh = program2.command("mesh").description("Manage Repo Meshes \u2014 repo-scoped execution environments");
96565
+ mesh.command("list").description("List all configured meshes").action(() => {
96566
+ const meshes = listMeshes();
96567
+ if (meshes.length === 0) {
96568
+ console.log(source_default.gray("No meshes configured. Create one with: adhdev mesh create <name>"));
96569
+ return;
96570
+ }
96571
+ console.log(source_default.bold(`
96572
+ Repo Meshes (${meshes.length})
96573
+ `));
96574
+ for (const m of meshes) {
96575
+ const nodeCount = m.nodes.length;
96576
+ const statusIcon = nodeCount > 0 ? source_default.green("\u25CF") : source_default.yellow("\u25CB");
96577
+ console.log(` ${statusIcon} ${source_default.bold(m.name)} ${source_default.gray(m.id)}`);
96578
+ console.log(` ${source_default.gray("repo:")} ${m.repoIdentity}`);
96579
+ console.log(` ${source_default.gray("nodes:")} ${nodeCount} ${source_default.gray("created:")} ${m.createdAt.split("T")[0]}`);
96580
+ console.log();
96581
+ }
96582
+ });
96583
+ mesh.command("create <name>").description("Create a new mesh for the current Git repository").option("--remote-url <url>", "Git remote URL (auto-detected from current directory)").option("--identity <identity>", "Repo identity override (e.g. github.com/user/repo)").option("--branch <branch>", "Default branch (e.g. main)").option("--add-current", "Also add current workspace as the first node", false).action(async (name, opts) => {
96584
+ let repoRemoteUrl = opts.remoteUrl;
96585
+ let repoIdentity = opts.identity;
96586
+ let defaultBranch = opts.branch;
96587
+ if (!repoRemoteUrl && !repoIdentity) {
96588
+ try {
96589
+ repoRemoteUrl = (0, import_node_child_process4.execSync)("git remote get-url origin", {
96590
+ encoding: "utf-8",
96591
+ stdio: ["pipe", "pipe", "pipe"]
96592
+ }).trim();
96593
+ console.log(source_default.gray(` Detected remote: ${repoRemoteUrl}`));
96594
+ } catch {
96595
+ console.error(source_default.red("\u2717 Could not detect Git remote. Use --remote-url or --identity."));
96596
+ process.exit(1);
96597
+ }
96598
+ }
96599
+ if (!defaultBranch) {
96600
+ try {
96601
+ defaultBranch = (0, import_node_child_process4.execSync)("git symbolic-ref refs/remotes/origin/HEAD", {
96602
+ encoding: "utf-8",
96603
+ stdio: ["pipe", "pipe", "pipe"]
96604
+ }).trim().replace("refs/remotes/origin/", "");
96605
+ } catch {
96606
+ try {
96607
+ defaultBranch = (0, import_node_child_process4.execSync)("git branch --show-current", {
96608
+ encoding: "utf-8",
96609
+ stdio: ["pipe", "pipe", "pipe"]
96610
+ }).trim();
96611
+ } catch {
96612
+ defaultBranch = "main";
96613
+ }
96614
+ }
96615
+ }
96616
+ try {
96617
+ const mesh2 = createMesh({
96618
+ name,
96619
+ repoRemoteUrl,
96620
+ repoIdentity,
96621
+ defaultBranch
96622
+ });
96623
+ console.log(source_default.green(`
96624
+ \u2713 Mesh created: ${source_default.bold(mesh2.name)}`));
96625
+ console.log(source_default.gray(` ID: ${mesh2.id}`));
96626
+ console.log(source_default.gray(` Repo: ${mesh2.repoIdentity}`));
96627
+ console.log(source_default.gray(` Branch: ${mesh2.defaultBranch || "auto"}`));
96628
+ if (opts.addCurrent) {
96629
+ const cwd = process.cwd();
96630
+ try {
96631
+ const node = addNode(mesh2.id, { workspace: cwd });
96632
+ if (node) {
96633
+ console.log(source_default.green(` \u2713 Added current workspace as node: ${source_default.gray(cwd)}`));
96634
+ console.log(source_default.gray(` Node ID: ${node.id}`));
96635
+ }
96636
+ } catch (e) {
96637
+ console.error(source_default.yellow(` \u26A0 Could not add current workspace: ${e.message}`));
96638
+ }
96639
+ }
96640
+ console.log();
96641
+ console.log(source_default.gray(" Next steps:"));
96642
+ console.log(source_default.gray(` adhdev mesh add-node ${mesh2.id} \u2014 Add a workspace to this mesh`));
96643
+ console.log(source_default.gray(` adhdev mcp --repo-mesh ${mesh2.id} \u2014 Start MCP server in mesh mode`));
96644
+ console.log();
96645
+ } catch (e) {
96646
+ console.error(source_default.red(`\u2717 ${e.message}`));
96647
+ process.exit(1);
96648
+ }
96649
+ });
96650
+ mesh.command("show <mesh_id>").description("Show mesh details and nodes").action((meshId) => {
96651
+ const m = getMesh(meshId);
96652
+ if (!m) {
96653
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96654
+ process.exit(1);
96655
+ }
96656
+ console.log(source_default.bold(`
96657
+ ${m.name} ${source_default.gray(m.id)}`));
96658
+ console.log(` ${source_default.gray("repo:")} ${m.repoIdentity}`);
96659
+ if (m.repoRemoteUrl) console.log(` ${source_default.gray("remote:")} ${m.repoRemoteUrl}`);
96660
+ if (m.defaultBranch) console.log(` ${source_default.gray("branch:")} ${m.defaultBranch}`);
96661
+ console.log(` ${source_default.gray("created:")} ${m.createdAt}`);
96662
+ console.log(` ${source_default.gray("updated:")} ${m.updatedAt}`);
96663
+ console.log(source_default.bold("\n Policy"));
96664
+ console.log(` ${source_default.gray("checkpoint after task:")} ${m.policy.requirePostTaskCheckpoint ? "yes" : "no"}`);
96665
+ console.log(` ${source_default.gray("push requires approval:")} ${m.policy.requireApprovalForPush ? "yes" : "no"}`);
96666
+ console.log(` ${source_default.gray("dirty workspace:")} ${m.policy.dirtyWorkspaceBehavior}`);
96667
+ console.log(` ${source_default.gray("max parallel tasks:")} ${m.policy.maxParallelTasks}`);
96668
+ console.log(source_default.bold(`
96669
+ Nodes (${m.nodes.length})`));
96670
+ if (m.nodes.length === 0) {
96671
+ console.log(source_default.gray(" No nodes. Add one with: adhdev mesh add-node " + meshId));
96672
+ } else {
96673
+ for (const n of m.nodes) {
96674
+ const label = n.isLocalWorktree ? source_default.cyan("[worktree]") : "";
96675
+ console.log(` ${source_default.gray("\u25CF")} ${n.workspace} ${label} ${source_default.gray(n.id)}`);
96676
+ if (n.policy.readOnly) console.log(` ${source_default.yellow("read-only")}`);
96677
+ if (Object.keys(n.userOverrides).length > 0) {
96678
+ console.log(` ${source_default.gray("overrides:")} ${JSON.stringify(n.userOverrides)}`);
96679
+ }
96680
+ }
96681
+ }
96682
+ console.log();
96683
+ });
96684
+ mesh.command("delete <mesh_id>").description("Delete a mesh").action((meshId) => {
96685
+ const m = getMesh(meshId);
96686
+ if (!m) {
96687
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96688
+ process.exit(1);
96689
+ }
96690
+ const ok = deleteMesh(meshId);
96691
+ if (ok) {
96692
+ console.log(source_default.green(` \u2713 Deleted mesh: ${m.name} (${meshId})`));
96693
+ } else {
96694
+ console.error(source_default.red(`\u2717 Failed to delete mesh: ${meshId}`));
96695
+ process.exit(1);
96696
+ }
96697
+ });
96698
+ mesh.command("add-node <mesh_id>").description("Add a workspace as a node to the mesh").option("--workspace <path>", "Workspace path (default: current directory)").option("--worktree", "Mark as a local Git worktree", false).option("--read-only", "Mark this node as read-only", false).action((meshId, opts) => {
96699
+ const m = getMesh(meshId);
96700
+ if (!m) {
96701
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96702
+ process.exit(1);
96703
+ }
96704
+ const workspace = opts.workspace || process.cwd();
96705
+ try {
96706
+ const node = addNode(meshId, {
96707
+ workspace,
96708
+ isLocalWorktree: opts.worktree,
96709
+ policy: opts.readOnly ? { readOnly: true } : {}
96710
+ });
96711
+ if (node) {
96712
+ console.log(source_default.green(` \u2713 Node added to ${m.name}`));
96713
+ console.log(source_default.gray(` ID: ${node.id}`));
96714
+ console.log(source_default.gray(` Workspace: ${workspace}`));
96715
+ if (opts.worktree) console.log(source_default.gray(` Type: local worktree`));
96716
+ if (opts.readOnly) console.log(source_default.gray(` Policy: read-only`));
96717
+ } else {
96718
+ console.error(source_default.red(`\u2717 Mesh not found`));
96719
+ process.exit(1);
96720
+ }
96721
+ } catch (e) {
96722
+ console.error(source_default.red(`\u2717 ${e.message}`));
96723
+ process.exit(1);
96724
+ }
96725
+ });
96726
+ mesh.command("remove-node <mesh_id> <node_id>").description("Remove a node from the mesh").action((meshId, nodeId) => {
96727
+ const ok = removeNode(meshId, nodeId);
96728
+ if (ok) {
96729
+ console.log(source_default.green(` \u2713 Node removed: ${nodeId}`));
96730
+ } else {
96731
+ console.error(source_default.red(`\u2717 Node or mesh not found`));
96732
+ process.exit(1);
96733
+ }
96734
+ });
96735
+ mesh.command("status <mesh_id>").description("Probe all mesh nodes and show health").action(async (meshId) => {
96736
+ const m = getMesh(meshId);
96737
+ if (!m) {
96738
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96739
+ process.exit(1);
96740
+ }
96741
+ console.log(source_default.bold(`
96742
+ ${m.name} \u2014 Node Status
96743
+ `));
96744
+ if (m.nodes.length === 0) {
96745
+ console.log(source_default.gray(" No nodes configured."));
96746
+ return;
96747
+ }
96748
+ for (const node of m.nodes) {
96749
+ let gitInfo = "";
96750
+ let healthIcon = source_default.gray("?");
96751
+ let health = "unknown";
96752
+ try {
96753
+ const branch = (0, import_node_child_process4.execSync)(`git -C "${node.workspace}" branch --show-current`, {
96754
+ encoding: "utf-8",
96755
+ stdio: ["pipe", "pipe", "pipe"]
96756
+ }).trim();
96757
+ const status = (0, import_node_child_process4.execSync)(`git -C "${node.workspace}" status --porcelain`, {
96758
+ encoding: "utf-8",
96759
+ stdio: ["pipe", "pipe", "pipe"]
96760
+ }).trim();
96761
+ const isDirty = status.length > 0;
96762
+ const changedFiles = isDirty ? status.split("\n").length : 0;
96763
+ if (isDirty) {
96764
+ health = "dirty";
96765
+ healthIcon = source_default.yellow("\u25CF");
96766
+ gitInfo = `${source_default.cyan(branch)} ${source_default.yellow(`(${changedFiles} changed)`)}`;
96767
+ } else {
96768
+ health = "clean";
96769
+ healthIcon = source_default.green("\u25CF");
96770
+ gitInfo = `${source_default.cyan(branch)} ${source_default.green("clean")}`;
96771
+ }
96772
+ } catch {
96773
+ health = "error";
96774
+ healthIcon = source_default.red("\u2717");
96775
+ gitInfo = source_default.red("git probe failed");
96776
+ }
96777
+ const label = node.isLocalWorktree ? source_default.gray(" [worktree]") : "";
96778
+ console.log(` ${healthIcon} ${node.workspace}${label} ${source_default.gray(node.id.slice(0, 12))}`);
96779
+ console.log(` ${gitInfo}`);
96780
+ if (node.policy.readOnly) console.log(` ${source_default.yellow("read-only")}`);
96781
+ console.log();
96782
+ }
96783
+ });
96784
+ mesh.command("sync").description("Sync local mesh config with cloud (push/pull)").action(async () => {
96785
+ try {
96786
+ const { syncMeshes: syncMeshes2, loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_src(), src_exports));
96787
+ const config2 = loadConfig2();
96788
+ const apiKey = process.env.ADHDEV_API_KEY;
96789
+ if (!apiKey) {
96790
+ console.error(source_default.red("\u2717 No API key set. Export ADHDEV_API_KEY or use: adhdev setup"));
96791
+ process.exit(1);
96792
+ }
96793
+ const baseUrl = config2.serverUrl || "https://api.adhf.dev";
96794
+ const transport = {
96795
+ async listRemoteMeshes() {
96796
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes`, {
96797
+ headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" }
96798
+ });
96799
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96800
+ return res.json();
96801
+ },
96802
+ async createRemoteMesh(data) {
96803
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes`, {
96804
+ method: "POST",
96805
+ headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" },
96806
+ body: JSON.stringify(data)
96807
+ });
96808
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96809
+ return res.json();
96810
+ },
96811
+ async deleteRemoteMesh(meshId) {
96812
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes/${meshId}`, {
96813
+ method: "DELETE",
96814
+ headers: { "Authorization": `Bearer ${apiKey}` }
96815
+ });
96816
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96817
+ }
96818
+ };
96819
+ console.log(source_default.gray(" Syncing with cloud..."));
96820
+ const result = await syncMeshes2(transport);
96821
+ if (result.pushed > 0) console.log(source_default.green(` \u2713 Pushed ${result.pushed} mesh${result.pushed > 1 ? "es" : ""} to cloud`));
96822
+ if (result.pulled > 0) console.log(source_default.green(` \u2713 Pulled ${result.pulled} mesh${result.pulled > 1 ? "es" : ""} from cloud`));
96823
+ if (result.pushed === 0 && result.pulled === 0 && result.errors.length === 0) {
96824
+ console.log(source_default.gray(" Already in sync."));
96825
+ }
96826
+ for (const err of result.errors) {
96827
+ console.error(source_default.yellow(` \u26A0 ${err}`));
96828
+ }
96829
+ } catch (e) {
96830
+ console.error(source_default.red(`\u2717 Sync failed: ${e.message}`));
96831
+ process.exit(1);
96832
+ }
96833
+ });
96834
+ }
96835
+
96058
96836
  // src/cli/index.ts
96059
96837
  init_version();
96060
96838
  var pkgVersion2 = resolvePackageVersion();
@@ -96075,6 +96853,7 @@ registerProviderCommands(program);
96075
96853
  registerCdpCommands(program);
96076
96854
  registerServiceCommands(program);
96077
96855
  registerMcpCommands(program);
96856
+ registerMeshCommands(program);
96078
96857
  void (async () => {
96079
96858
  const helperMode = await maybeRunDaemonUpgradeHelperFromEnv();
96080
96859
  if (helperMode) {
@@ -96102,6 +96881,8 @@ void (async () => {
96102
96881
  console.log(source_default.gray(" adhdev trace --category session_host \u2014 Inspect structured daemon trace"));
96103
96882
  console.log(source_default.gray(" adhdev service \u2014 Manage OS background auto-start service"));
96104
96883
  console.log(source_default.gray(" adhdev mcp \u2014 Start MCP server (expose agents to Claude Desktop, etc.)"));
96884
+ console.log(source_default.gray(" adhdev mesh list \u2014 List configured Repo Meshes"));
96885
+ console.log(source_default.gray(" adhdev mesh create myapp \u2014 Create a mesh for the current Git repo"));
96105
96886
  console.log(source_default.gray(" adhdev provider ... \u2014 Provider development commands"));
96106
96887
  console.log(source_default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
96107
96888
  console.log();