oh-my-copilot 4.11.2 → 4.11.4

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.
Files changed (85) hide show
  1. package/.claude-plugin/marketplace.json +4 -4
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +1 -1
  4. package/bridge/cli.cjs +143 -52
  5. package/bridge/runtime-cli.cjs +9 -3
  6. package/bridge/team-bridge.cjs +9 -3
  7. package/bridge/team.js +70 -64
  8. package/dist/__tests__/config-dir.test.js +3 -3
  9. package/dist/__tests__/config-dir.test.js.map +1 -1
  10. package/dist/__tests__/hud/cwd.test.js +2 -2
  11. package/dist/__tests__/hud/cwd.test.js.map +1 -1
  12. package/dist/__tests__/purge-stale-cache.test.js +10 -10
  13. package/dist/__tests__/release-generation.test.js +13 -13
  14. package/dist/__tests__/release-generation.test.js.map +1 -1
  15. package/dist/__tests__/setup-claude-md-script.test.js +3 -2
  16. package/dist/__tests__/setup-claude-md-script.test.js.map +1 -1
  17. package/dist/__tests__/setup-progress-script.test.js +1 -1
  18. package/dist/__tests__/setup-progress-script.test.js.map +1 -1
  19. package/dist/autoresearch/contracts.d.ts.map +1 -1
  20. package/dist/autoresearch/contracts.js +7 -2
  21. package/dist/autoresearch/contracts.js.map +1 -1
  22. package/dist/cli/autoresearch-guided.d.ts.map +1 -1
  23. package/dist/cli/autoresearch-guided.js +14 -6
  24. package/dist/cli/autoresearch-guided.js.map +1 -1
  25. package/dist/hooks/bridge.d.ts.map +1 -1
  26. package/dist/hooks/bridge.js +32 -1
  27. package/dist/hooks/bridge.js.map +1 -1
  28. package/dist/hooks/learner/finder.js +1 -1
  29. package/dist/hooks/learner/finder.js.map +1 -1
  30. package/dist/hooks/persistent-mode/__tests__/idle-cooldown.test.js +1 -1
  31. package/dist/hooks/persistent-mode/__tests__/idle-cooldown.test.js.map +1 -1
  32. package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
  33. package/dist/hooks/persistent-mode/index.js +9 -2
  34. package/dist/hooks/persistent-mode/index.js.map +1 -1
  35. package/dist/hud/elements/agents.d.ts.map +1 -1
  36. package/dist/hud/elements/agents.js +7 -3
  37. package/dist/hud/elements/agents.js.map +1 -1
  38. package/dist/installer/index.d.ts +1 -0
  39. package/dist/installer/index.d.ts.map +1 -1
  40. package/dist/installer/index.js +63 -39
  41. package/dist/installer/index.js.map +1 -1
  42. package/dist/lib/plugin-dir.d.ts +12 -0
  43. package/dist/lib/plugin-dir.d.ts.map +1 -0
  44. package/dist/lib/plugin-dir.js +18 -0
  45. package/dist/lib/plugin-dir.js.map +1 -0
  46. package/dist/lib/version.d.ts.map +1 -1
  47. package/dist/lib/version.js +13 -0
  48. package/dist/lib/version.js.map +1 -1
  49. package/dist/lib/worktree-paths.d.ts.map +1 -1
  50. package/dist/lib/worktree-paths.js +12 -1
  51. package/dist/lib/worktree-paths.js.map +1 -1
  52. package/dist/team/__tests__/runtime-v2.dispatch.test.js +7 -7
  53. package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
  54. package/dist/team/fs-utils.d.ts.map +1 -1
  55. package/dist/team/fs-utils.js +14 -7
  56. package/dist/team/fs-utils.js.map +1 -1
  57. package/dist/tools/python-repl/__tests__/python-sandbox.test.js +29 -2
  58. package/dist/tools/python-repl/__tests__/python-sandbox.test.js.map +1 -1
  59. package/dist/utils/resolve-node.d.ts +5 -3
  60. package/dist/utils/resolve-node.d.ts.map +1 -1
  61. package/dist/utils/resolve-node.js +17 -9
  62. package/dist/utils/resolve-node.js.map +1 -1
  63. package/docs/copilot-instructions.md +1 -1
  64. package/package.json +1 -1
  65. package/scripts/build-bridge-entry.mjs +12 -3
  66. package/scripts/build-cli.mjs +17 -7
  67. package/scripts/build-mcp-server.mjs +12 -3
  68. package/scripts/build-runtime-cli.mjs +13 -3
  69. package/scripts/build-skill-bridge.mjs +12 -3
  70. package/scripts/persistent-mode.cjs +8 -0
  71. package/scripts/post-tool-verifier.mjs +74 -1
  72. package/scripts/setup-copilot-instructions.sh +1 -1
  73. package/skills/hud/SKILL.md +53 -10
  74. package/skills/mcp-setup/SKILL.md +30 -14
  75. package/skills/omc-setup/SKILL.md +19 -1
  76. package/skills/omc-setup/phases/01-install-copilot-instructions.md +29 -3
  77. package/skills/omc-setup/phases/03-integrations.md +16 -99
  78. package/skills/omc-setup/phases/04-welcome.md +33 -91
  79. package/skills/project-session-manager/SKILL.md +2 -2
  80. package/skills/project-session-manager/lib/config.sh +1 -1
  81. package/skills/project-session-manager/psm.sh +1 -1
  82. package/skills/project-session-manager/templates/projects.json +1 -1
  83. package/skills/release/SKILL.md +1 -1
  84. package/templates/hooks/post-tool-use.mjs +70 -0
  85. package/templates/hooks/pre-tool-use.mjs +1 -1
@@ -4,16 +4,16 @@
4
4
  "description": "Copilot CLI native multi-agent orchestration - intelligent model routing, 18 agents, 32 skills",
5
5
  "owner": {
6
6
  "name": "Robin Norberg",
7
- "email": "robin@norberg.dev"
7
+ "email": "github@platypus.se"
8
8
  },
9
9
  "plugins": [
10
10
  {
11
11
  "name": "oh-my-copilot",
12
12
  "description": "Copilot CLI native multi-agent orchestration with intelligent model routing, 18 agent variants, and 32 powerful skills. Zero learning curve. Maximum power.",
13
- "version": "4.11.2",
13
+ "version": "4.11.4",
14
14
  "author": {
15
15
  "name": "Robin Norberg",
16
- "email": "robin@norberg.dev"
16
+ "email": "github@platypus.se"
17
17
  },
18
18
  "source": "./",
19
19
  "category": "productivity",
@@ -27,5 +27,5 @@
27
27
  ]
28
28
  }
29
29
  ],
30
- "version": "4.11.2"
30
+ "version": "4.11.4"
31
31
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-copilot",
3
- "version": "4.11.2",
3
+ "version": "4.11.4",
4
4
  "description": "Multi-agent orchestration system for Copilot CLI",
5
5
  "author": {
6
6
  "name": "Robin Norberg and oh-my-copilot contributors"
package/README.md CHANGED
@@ -32,7 +32,7 @@
32
32
  ```bash
33
33
  # Step 1: Install
34
34
  /plugin marketplace add https://github.com/RobinNorberg/oh-my-copilot
35
- /plugin install oh-my-copilot
35
+ /plugin install oh-my-copilot@omg
36
36
  # or
37
37
  npm i -g oh-my-copilot@latest
38
38
 
package/bridge/cli.cjs CHANGED
@@ -4210,7 +4210,14 @@ function resolveTranscriptPath(transcriptPath, cwd2) {
4210
4210
  stdio: ["pipe", "pipe", "pipe"]
4211
4211
  }).trim();
4212
4212
  const absoluteCommonDir = (0, import_path17.resolve)(effectiveCwd, gitCommonDir);
4213
- const mainRepoRoot = (0, import_path17.dirname)(absoluteCommonDir);
4213
+ let mainRepoRoot = (0, import_path17.dirname)(absoluteCommonDir);
4214
+ if (mainRepoRoot.endsWith((0, import_path17.join)(".git", "worktrees"))) {
4215
+ mainRepoRoot = (0, import_path17.dirname)((0, import_path17.dirname)(mainRepoRoot));
4216
+ }
4217
+ try {
4218
+ mainRepoRoot = (0, import_fs11.realpathSync)(mainRepoRoot);
4219
+ } catch {
4220
+ }
4214
4221
  const worktreeTop = (0, import_child_process6.execSync)("git rev-parse --show-toplevel", {
4215
4222
  cwd: effectiveCwd,
4216
4223
  encoding: "utf-8",
@@ -5344,7 +5351,7 @@ function safeRealpathSync(filePath) {
5344
5351
  }
5345
5352
  function isWithinBoundary(realPath, boundary) {
5346
5353
  const normalizedReal = (0, import_path22.normalize)(realPath);
5347
- const normalizedBoundary = (0, import_path22.normalize)(boundary);
5354
+ const normalizedBoundary = (0, import_path22.normalize)(safeRealpathSync(boundary));
5348
5355
  return normalizedReal === normalizedBoundary || normalizedReal.startsWith(normalizedBoundary + import_path22.sep);
5349
5356
  }
5350
5357
  function findSkillFiles(projectRoot, options) {
@@ -6787,6 +6794,14 @@ function getRuntimePackageVersion() {
6787
6794
  }
6788
6795
  } catch {
6789
6796
  }
6797
+ try {
6798
+ const __filename5 = (0, import_url8.fileURLToPath)(importMetaUrl);
6799
+ const pathMatch = __filename5.match(/oh-my-copilot\/(\d+\.\d+\.\d+[^/]*)\//);
6800
+ if (pathMatch?.[1]) {
6801
+ return pathMatch[1];
6802
+ }
6803
+ } catch {
6804
+ }
6790
6805
  return "unknown";
6791
6806
  }
6792
6807
  var import_fs28, import_path40, import_url8;
@@ -6800,10 +6815,10 @@ var init_version = __esm({
6800
6815
  });
6801
6816
 
6802
6817
  // src/utils/resolve-node.ts
6818
+ function isKnownEphemeralNodePath(nodePath) {
6819
+ return EPHEMERAL_NODE_PATH_MARKERS.some((marker) => nodePath.includes(marker));
6820
+ }
6803
6821
  function resolveNodeBinary() {
6804
- if (process.execPath && (0, import_fs29.existsSync)(process.execPath)) {
6805
- return process.execPath;
6806
- }
6807
6822
  try {
6808
6823
  const cmd = process.platform === "win32" ? "where node" : "which node";
6809
6824
  const result = (0, import_child_process11.execSync)(cmd, { encoding: "utf-8", stdio: "pipe" }).trim().split("\n")[0].trim();
@@ -6812,6 +6827,9 @@ function resolveNodeBinary() {
6812
6827
  }
6813
6828
  } catch {
6814
6829
  }
6830
+ if (process.execPath && (0, import_fs29.existsSync)(process.execPath) && !isKnownEphemeralNodePath(process.execPath)) {
6831
+ return process.execPath;
6832
+ }
6815
6833
  if (process.platform === "win32") {
6816
6834
  return "node";
6817
6835
  }
@@ -6861,7 +6879,7 @@ function pickLatestVersion(versions) {
6861
6879
  return 0;
6862
6880
  })[0];
6863
6881
  }
6864
- var import_fs29, import_child_process11, import_path41, import_os9;
6882
+ var import_fs29, import_child_process11, import_path41, import_os9, EPHEMERAL_NODE_PATH_MARKERS;
6865
6883
  var init_resolve_node = __esm({
6866
6884
  "src/utils/resolve-node.ts"() {
6867
6885
  "use strict";
@@ -6869,6 +6887,7 @@ var init_resolve_node = __esm({
6869
6887
  import_child_process11 = require("child_process");
6870
6888
  import_path41 = require("path");
6871
6889
  import_os9 = require("os");
6890
+ EPHEMERAL_NODE_PATH_MARKERS = ["hostedtoolcache", "/runner/", "\\runner\\"];
6872
6891
  }
6873
6892
  });
6874
6893
 
@@ -7080,12 +7099,12 @@ function isHudEnabledInConfig() {
7080
7099
  function isOmcStatusLine(statusLine) {
7081
7100
  if (!statusLine) return false;
7082
7101
  if (typeof statusLine === "string") {
7083
- return statusLine.includes("omc-hud");
7102
+ return statusLine.includes("omc-hud") || statusLine.includes("copilot-hud.cmd") || statusLine.includes("oh-my-copilot");
7084
7103
  }
7085
7104
  if (typeof statusLine === "object") {
7086
7105
  const sl = statusLine;
7087
7106
  if (typeof sl.command === "string") {
7088
- return sl.command.includes("omc-hud");
7107
+ return sl.command.includes("omc-hud") || sl.command.includes("copilot-hud.cmd") || sl.command.includes("oh-my-copilot");
7089
7108
  }
7090
7109
  }
7091
7110
  return false;
@@ -7187,16 +7206,20 @@ function hasEnabledOmcPlugin() {
7187
7206
  }
7188
7207
  try {
7189
7208
  const settings = JSON.parse((0, import_fs30.readFileSync)(SETTINGS_FILE, "utf-8"));
7190
- const plugins = settings.plugins;
7191
- if (Array.isArray(plugins)) {
7192
- return plugins.some(
7193
- (plugin) => typeof plugin === "string" && plugin.toLowerCase().includes("oh-my-copilot")
7194
- );
7195
- }
7196
- if (plugins && typeof plugins === "object") {
7197
- return Object.entries(plugins).some(
7198
- ([pluginId, value]) => pluginId.toLowerCase().includes("oh-my-copilot") && value !== false
7199
- );
7209
+ for (const candidate of [settings.enabledPlugins, settings.plugins]) {
7210
+ if (Array.isArray(candidate)) {
7211
+ if (candidate.some(
7212
+ (plugin) => typeof plugin === "string" && plugin.toLowerCase().includes("oh-my-copilot")
7213
+ )) {
7214
+ return true;
7215
+ }
7216
+ } else if (candidate && typeof candidate === "object") {
7217
+ if (Object.entries(candidate).some(
7218
+ ([pluginId, value]) => pluginId.toLowerCase().includes("oh-my-copilot") && value !== false
7219
+ )) {
7220
+ return true;
7221
+ }
7222
+ }
7200
7223
  }
7201
7224
  } catch {
7202
7225
  }
@@ -7702,9 +7725,17 @@ function install(options = {}) {
7702
7725
  }
7703
7726
  if (hudScriptPath) {
7704
7727
  const nodeBin = resolveNodeBinary();
7705
- const absoluteCommand = '"' + nodeBin + '" "' + hudScriptPath.replace(/\\/g, "/") + '"';
7706
- let statusLineCommand = absoluteCommand;
7707
- if (!isWindows()) {
7728
+ let statusLineCommand;
7729
+ if (isWindows()) {
7730
+ const cmdWrapperPath = (0, import_path42.join)(COPILOT_CONFIG_DIR, "copilot-hud.cmd");
7731
+ const hudPathNormalized = hudScriptPath.replace(/\//g, "\\");
7732
+ const nodeBinNormalized = nodeBin.replace(/\//g, "\\");
7733
+ (0, import_fs30.writeFileSync)(cmdWrapperPath, `@echo off\r
7734
+ "${nodeBinNormalized}" "${hudPathNormalized}"\r
7735
+ `);
7736
+ statusLineCommand = cmdWrapperPath.replace(/\\/g, "/");
7737
+ log3(" Created Windows HUD wrapper: copilot-hud.cmd");
7738
+ } else {
7708
7739
  try {
7709
7740
  const findNodeSrc = (0, import_path42.join)(getPackageDir3(), "scripts", "find-node.sh");
7710
7741
  const findNodeDest = (0, import_path42.join)(HUD_DIR, "find-node.sh");
@@ -7715,23 +7746,33 @@ function install(options = {}) {
7715
7746
  statusLineCommand = "node ${COPILOT_CONFIG_DIR:-$HOME/.copilot}/hud/omc-hud.mjs";
7716
7747
  }
7717
7748
  }
7718
- const needsMigration = typeof existingSettings.statusLine === "string" && isOmcStatusLine(existingSettings.statusLine);
7719
- if (!existingSettings.statusLine || needsMigration) {
7720
- existingSettings.statusLine = {
7721
- type: "command",
7722
- command: statusLineCommand
7723
- };
7724
- log3(needsMigration ? " Migrated statusLine from legacy string to object format" : " Configured statusLine");
7725
- } else if (options.force && isOmcStatusLine(existingSettings.statusLine)) {
7726
- existingSettings.statusLine = {
7727
- type: "command",
7728
- command: statusLineCommand
7729
- };
7730
- log3(" Updated statusLine (--force)");
7731
- } else if (options.force) {
7732
- log3(" statusLine owned by another tool, preserving (use manual edit to override)");
7733
- } else {
7734
- log3(" statusLine already configured, skipping (use --force to override)");
7749
+ try {
7750
+ let copilotConfig = {};
7751
+ if ((0, import_fs30.existsSync)(COPILOT_CONFIG_FILE)) {
7752
+ copilotConfig = JSON.parse((0, import_fs30.readFileSync)(COPILOT_CONFIG_FILE, "utf-8"));
7753
+ }
7754
+ copilotConfig.experimental = true;
7755
+ const existingStatusLine = copilotConfig.statusLine;
7756
+ const needsMigration = typeof existingStatusLine === "string" && isOmcStatusLine(existingStatusLine);
7757
+ if (!existingStatusLine || needsMigration) {
7758
+ copilotConfig.statusLine = { type: "command", command: statusLineCommand };
7759
+ (0, import_fs30.writeFileSync)(COPILOT_CONFIG_FILE, JSON.stringify(copilotConfig, null, 2));
7760
+ log3(needsMigration ? " Migrated statusLine to config.json" : " Configured statusLine in config.json");
7761
+ } else if (options.force && isOmcStatusLine(existingStatusLine)) {
7762
+ copilotConfig.statusLine = { type: "command", command: statusLineCommand };
7763
+ (0, import_fs30.writeFileSync)(COPILOT_CONFIG_FILE, JSON.stringify(copilotConfig, null, 2));
7764
+ log3(" Updated statusLine in config.json (--force)");
7765
+ } else if (options.force) {
7766
+ log3(" statusLine owned by another tool, preserving (use manual edit to override)");
7767
+ } else {
7768
+ log3(" statusLine already configured in config.json, skipping");
7769
+ }
7770
+ } catch (error2) {
7771
+ log3(` Warning: Could not update config.json: ${error2 instanceof Error ? error2.message : error2}`);
7772
+ }
7773
+ if (existingSettings.statusLine && isOmcStatusLine(existingSettings.statusLine)) {
7774
+ delete existingSettings.statusLine;
7775
+ log3(" Removed legacy statusLine from settings.json");
7735
7776
  }
7736
7777
  }
7737
7778
  try {
@@ -7823,7 +7864,7 @@ function getInstallInfo() {
7823
7864
  return null;
7824
7865
  }
7825
7866
  }
7826
- var import_fs30, import_path42, import_url9, import_os10, import_child_process12, COPILOT_CONFIG_DIR, AGENTS_DIR, COMMANDS_DIR, SKILLS_DIR, HOOKS_DIR, HUD_DIR, SETTINGS_FILE, VERSION_FILE, CORE_COMMANDS, VERSION, OMC_VERSION_MARKER_PATTERN, CC_NATIVE_COMMANDS, SKININTHEGAMEBROS_ONLY_SKILLS, OMC_HOOK_FILENAMES;
7867
+ var import_fs30, import_path42, import_url9, import_os10, import_child_process12, COPILOT_CONFIG_DIR, AGENTS_DIR, COMMANDS_DIR, SKILLS_DIR, HOOKS_DIR, HUD_DIR, SETTINGS_FILE, COPILOT_CONFIG_FILE, VERSION_FILE, CORE_COMMANDS, VERSION, OMC_VERSION_MARKER_PATTERN, CC_NATIVE_COMMANDS, SKININTHEGAMEBROS_ONLY_SKILLS, OMC_HOOK_FILENAMES;
7827
7868
  var init_installer = __esm({
7828
7869
  "src/installer/index.ts"() {
7829
7870
  "use strict";
@@ -7846,6 +7887,7 @@ var init_installer = __esm({
7846
7887
  HOOKS_DIR = (0, import_path42.join)(COPILOT_CONFIG_DIR, "hooks");
7847
7888
  HUD_DIR = (0, import_path42.join)(COPILOT_CONFIG_DIR, "hud");
7848
7889
  SETTINGS_FILE = (0, import_path42.join)(COPILOT_CONFIG_DIR, "settings.json");
7890
+ COPILOT_CONFIG_FILE = (0, import_path42.join)(COPILOT_CONFIG_DIR, "config.json");
7849
7891
  VERSION_FILE = (0, import_path42.join)(COPILOT_CONFIG_DIR, ".omc-version.json");
7850
7892
  CORE_COMMANDS = [];
7851
7893
  VERSION = getRuntimePackageVersion();
@@ -15963,9 +16005,13 @@ async function checkRalplan(sessionId, directory, cancelInProgress) {
15963
16005
  const breakerCount = readStopBreaker(workingDir, "ralplan", sessionId, RALPLAN_STOP_BLOCKER_TTL_MS) + 1;
15964
16006
  if (breakerCount > RALPLAN_STOP_BLOCKER_MAX) {
15965
16007
  writeStopBreaker(workingDir, "ralplan", 0, sessionId);
16008
+ state.active = false;
16009
+ state.deactivated_reason = "stop_breaker_exhausted";
16010
+ state.completed_at = (/* @__PURE__ */ new Date()).toISOString();
16011
+ writeModeState("ralplan", state, workingDir, sessionId);
15966
16012
  return {
15967
16013
  shouldBlock: false,
15968
- message: `[RALPLAN CIRCUIT BREAKER] Stop enforcement exceeded ${RALPLAN_STOP_BLOCKER_MAX} reinforcements. Allowing stop to prevent infinite blocking.`,
16014
+ message: `[RALPLAN CIRCUIT BREAKER] Stop enforcement exceeded ${RALPLAN_STOP_BLOCKER_MAX} reinforcements. Allowing stop and deactivating stale ralplan state to prevent infinite restart loops.`,
15969
16015
  mode: "ralplan"
15970
16016
  };
15971
16017
  }
@@ -23247,10 +23293,16 @@ function safeRealpath(p) {
23247
23293
  try {
23248
23294
  return (0, import_fs58.realpathSync)(p);
23249
23295
  } catch {
23250
- const parent = (0, import_path75.dirname)(p);
23251
- const name = (0, import_path75.basename)(p);
23296
+ const segments = [];
23297
+ let current = (0, import_path75.resolve)(p);
23298
+ while (!(0, import_fs58.existsSync)(current)) {
23299
+ segments.unshift((0, import_path75.basename)(current));
23300
+ const parent = (0, import_path75.dirname)(current);
23301
+ if (parent === current) break;
23302
+ current = parent;
23303
+ }
23252
23304
  try {
23253
- return (0, import_path75.resolve)((0, import_fs58.realpathSync)(parent), name);
23305
+ return (0, import_path75.join)((0, import_fs58.realpathSync)(current), ...segments);
23254
23306
  } catch {
23255
23307
  return (0, import_path75.resolve)(p);
23256
23308
  }
@@ -34733,10 +34785,11 @@ function renderAgentsMultiLine(agents, maxLines = 5) {
34733
34785
  const durationMs = now - a.startTime.getTime();
34734
34786
  const duration3 = formatDurationPadded(durationMs);
34735
34787
  const durationColor = getDurationColor(durationMs);
34788
+ const modelLabel = a.model ? a.model.charAt(0).toUpperCase() + a.model.slice(1).toLowerCase() : "Default";
34736
34789
  const desc = a.description || "...";
34737
- const truncatedDesc = truncateToWidth(desc, 45);
34790
+ const truncatedDesc = truncateToWidth(desc, 40);
34738
34791
  detailLines.push(
34739
- `${dim(prefix)} ${color}${code}${RESET} ${dim(shortName)}${durationColor}${duration3}${RESET} ${truncatedDesc}`
34792
+ `${dim(prefix)} ${color}${code}${RESET} ${dim(shortName)}${durationColor}${duration3}${RESET} ${dim(`(${modelLabel})`)} ${truncatedDesc}`
34740
34793
  );
34741
34794
  });
34742
34795
  if (running.length > maxLines) {
@@ -70711,6 +70764,33 @@ function isConsensusPlanningSkillInvocation(skillName, toolInput) {
70711
70764
  }
70712
70765
  return getSkillInvocationArgs(toolInput).toLowerCase().includes("--consensus");
70713
70766
  }
70767
+ function deactivateRalplanState(directory, sessionId) {
70768
+ const state = readModeState("ralplan", directory, sessionId);
70769
+ if (!state) {
70770
+ return;
70771
+ }
70772
+ const currentPhase = typeof state.current_phase === "string" ? state.current_phase : void 0;
70773
+ const terminalPhases = /* @__PURE__ */ new Set([
70774
+ "complete",
70775
+ "completed",
70776
+ "failed",
70777
+ "cancelled",
70778
+ "done"
70779
+ ]);
70780
+ const completedAt = typeof state.completed_at === "string" ? state.completed_at : (/* @__PURE__ */ new Date()).toISOString();
70781
+ writeModeState(
70782
+ "ralplan",
70783
+ {
70784
+ ...state,
70785
+ active: false,
70786
+ current_phase: currentPhase && terminalPhases.has(currentPhase.toLowerCase()) ? currentPhase : "complete",
70787
+ completed_at: completedAt,
70788
+ deactivated_reason: typeof state.deactivated_reason === "string" ? state.deactivated_reason : "skill_completed"
70789
+ },
70790
+ directory,
70791
+ sessionId
70792
+ );
70793
+ }
70714
70794
  function activateRalplanState(directory, sessionId) {
70715
70795
  writeModeState(
70716
70796
  "ralplan",
@@ -71651,6 +71731,9 @@ async function processPostToolUse(input) {
71651
71731
  if (!currentState || !currentState.active || currentState.skill_name === completingSkill) {
71652
71732
  clearSkillActiveState2(directory, input.sessionId);
71653
71733
  }
71734
+ if (isConsensusPlanningSkillInvocation(skillName, input.toolInput)) {
71735
+ deactivateRalplanState(directory, input.sessionId);
71736
+ }
71654
71737
  }
71655
71738
  const orchestratorResult = processOrchestratorPostTool(
71656
71739
  {
@@ -77947,10 +78030,14 @@ function parseEvaluatorResult(raw) {
77947
78030
  return result.score === void 0 ? { pass: result.pass } : { pass: result.pass, score: result.score };
77948
78031
  }
77949
78032
  async function loadAutoresearchMissionContract(missionDirArg) {
77950
- const missionDir = (0, import_path109.resolve)(missionDirArg);
78033
+ let missionDir = (0, import_path109.resolve)(missionDirArg);
77951
78034
  if (!(0, import_fs91.existsSync)(missionDir)) {
77952
78035
  throw contractError(`mission-dir does not exist: ${missionDir}`);
77953
78036
  }
78037
+ try {
78038
+ missionDir = (0, import_fs91.realpathSync)(missionDir);
78039
+ } catch {
78040
+ }
77954
78041
  const repoRoot = readGit(missionDir, ["rev-parse", "--show-toplevel"]);
77955
78042
  ensurePathInside(repoRoot, missionDir);
77956
78043
  const missionFile = (0, import_path109.join)(missionDir, "mission.md");
@@ -79345,9 +79432,13 @@ function resolveMissionRepoRoot(missionDir) {
79345
79432
  stdio: ["ignore", "pipe", "pipe"]
79346
79433
  }).trim();
79347
79434
  }
79435
+ function tmuxEnv() {
79436
+ const { TMUX: _, ...env2 } = process.env;
79437
+ return env2;
79438
+ }
79348
79439
  function assertTmuxSessionAvailable(sessionName2) {
79349
79440
  try {
79350
- (0, import_child_process40.execFileSync)("tmux", ["has-session", "-t", sessionName2], { stdio: "ignore" });
79441
+ (0, import_child_process40.execFileSync)("tmux", ["has-session", "-t", sessionName2], { stdio: "ignore", env: tmuxEnv() });
79351
79442
  } catch {
79352
79443
  throw new Error(
79353
79444
  `tmux session "${sessionName2}" did not stay available after launch. Check the mission command, login-shell environment, and tmux logs, then try again.`
@@ -79360,7 +79451,7 @@ function spawnAutoresearchTmux(missionDir, slug) {
79360
79451
  }
79361
79452
  const sessionName2 = `omc-autoresearch-${slug}`;
79362
79453
  try {
79363
- (0, import_child_process40.execFileSync)("tmux", ["has-session", "-t", sessionName2], { stdio: "ignore" });
79454
+ (0, import_child_process40.execFileSync)("tmux", ["has-session", "-t", sessionName2], { stdio: "ignore", env: tmuxEnv() });
79364
79455
  throw new Error(
79365
79456
  `tmux session "${sessionName2}" already exists.
79366
79457
  Attach: tmux attach -t ${sessionName2}
@@ -79376,7 +79467,7 @@ function spawnAutoresearchTmux(missionDir, slug) {
79376
79467
  const omcPath = (0, import_path112.resolve)((0, import_path112.join)(__dirname, "..", "..", "bin", "omc.js"));
79377
79468
  const command = buildTmuxShellCommand(process.execPath, [omcPath, "autoresearch", missionDir]);
79378
79469
  const wrappedCommand = wrapWithLoginShell(command);
79379
- (0, import_child_process40.execFileSync)("tmux", ["new-session", "-d", "-s", sessionName2, "-c", repoRoot, wrappedCommand], { stdio: "ignore" });
79470
+ (0, import_child_process40.execFileSync)("tmux", ["new-session", "-d", "-s", sessionName2, "-c", repoRoot, wrappedCommand], { stdio: "ignore", env: tmuxEnv() });
79380
79471
  assertTmuxSessionAvailable(sessionName2);
79381
79472
  console.log("\nAutoresearch launched in background tmux session.");
79382
79473
  console.log(` Session: ${sessionName2}`);
@@ -79426,12 +79517,12 @@ function spawnAutoresearchSetupTmux(repoRoot) {
79426
79517
  const paneId = (0, import_child_process40.execFileSync)(
79427
79518
  "tmux",
79428
79519
  ["new-session", "-d", "-P", "-F", "#{pane_id}", "-s", sessionName2, "-c", repoRoot, wrappedClaudeCommand],
79429
- { encoding: "utf-8" }
79520
+ { encoding: "utf-8", env: tmuxEnv() }
79430
79521
  ).trim();
79431
79522
  assertTmuxSessionAvailable(sessionName2);
79432
79523
  if (paneId) {
79433
- (0, import_child_process40.execFileSync)("tmux", ["send-keys", "-t", paneId, "-l", buildAutoresearchSetupSlashCommand()], { stdio: "ignore" });
79434
- (0, import_child_process40.execFileSync)("tmux", ["send-keys", "-t", paneId, "Enter"], { stdio: "ignore" });
79524
+ (0, import_child_process40.execFileSync)("tmux", ["send-keys", "-t", paneId, "-l", buildAutoresearchSetupSlashCommand()], { stdio: "ignore", env: tmuxEnv() });
79525
+ (0, import_child_process40.execFileSync)("tmux", ["send-keys", "-t", paneId, "Enter"], { stdio: "ignore", env: tmuxEnv() });
79435
79526
  }
79436
79527
  console.log("\nAutoresearch setup launched in background Claude session.");
79437
79528
  console.log(` Session: ${sessionName2}`);
@@ -1931,10 +1931,16 @@ function safeRealpath(p) {
1931
1931
  try {
1932
1932
  return (0, import_fs7.realpathSync)(p);
1933
1933
  } catch {
1934
- const parent = (0, import_path10.dirname)(p);
1935
- const name = (0, import_path10.basename)(p);
1934
+ const segments = [];
1935
+ let current = (0, import_path10.resolve)(p);
1936
+ while (!(0, import_fs7.existsSync)(current)) {
1937
+ segments.unshift((0, import_path10.basename)(current));
1938
+ const parent = (0, import_path10.dirname)(current);
1939
+ if (parent === current) break;
1940
+ current = parent;
1941
+ }
1936
1942
  try {
1937
- return (0, import_path10.resolve)((0, import_fs7.realpathSync)(parent), name);
1943
+ return (0, import_path10.join)((0, import_fs7.realpathSync)(current), ...segments);
1938
1944
  } catch {
1939
1945
  return (0, import_path10.resolve)(p);
1940
1946
  }
@@ -103,10 +103,16 @@ function safeRealpath(p) {
103
103
  try {
104
104
  return (0, import_fs.realpathSync)(p);
105
105
  } catch {
106
- const parent = (0, import_path.dirname)(p);
107
- const name = (0, import_path.basename)(p);
106
+ const segments = [];
107
+ let current = (0, import_path.resolve)(p);
108
+ while (!(0, import_fs.existsSync)(current)) {
109
+ segments.unshift((0, import_path.basename)(current));
110
+ const parent = (0, import_path.dirname)(current);
111
+ if (parent === current) break;
112
+ current = parent;
113
+ }
108
114
  try {
109
- return (0, import_path.resolve)((0, import_fs.realpathSync)(parent), name);
115
+ return (0, import_path.join)((0, import_fs.realpathSync)(current), ...segments);
110
116
  } catch {
111
117
  return (0, import_path.resolve)(p);
112
118
  }