oh-my-copilot 4.13.21 → 4.13.45

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 (195) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +8 -0
  4. package/agents/code-reviewer.agent.md +24 -6
  5. package/agents/designer.agent.md +12 -0
  6. package/bridge/cli.cjs +1978 -1214
  7. package/bridge/mcp-server.cjs +678 -261
  8. package/bridge/runtime-cli.cjs +55 -8
  9. package/bridge/team.js +507 -38
  10. package/dist/__tests__/agent-registry.test.js +92 -1
  11. package/dist/__tests__/agent-registry.test.js.map +1 -1
  12. package/dist/__tests__/bedrock-model-routing.test.js +18 -17
  13. package/dist/__tests__/bedrock-model-routing.test.js.map +1 -1
  14. package/dist/__tests__/delegation-enforcer.test.js +46 -6
  15. package/dist/__tests__/delegation-enforcer.test.js.map +1 -1
  16. package/dist/__tests__/hooks/session-end-cleanup.test.d.ts +2 -0
  17. package/dist/__tests__/hooks/session-end-cleanup.test.d.ts.map +1 -0
  18. package/dist/__tests__/hooks/session-end-cleanup.test.js +93 -0
  19. package/dist/__tests__/hooks/session-end-cleanup.test.js.map +1 -0
  20. package/dist/__tests__/hud/stdin.test.d.ts +2 -0
  21. package/dist/__tests__/hud/stdin.test.d.ts.map +1 -0
  22. package/dist/__tests__/hud/stdin.test.js +556 -0
  23. package/dist/__tests__/hud/stdin.test.js.map +1 -0
  24. package/dist/__tests__/model-routing-override-three-site-sync.test.d.ts +2 -0
  25. package/dist/__tests__/model-routing-override-three-site-sync.test.d.ts.map +1 -0
  26. package/dist/__tests__/model-routing-override-three-site-sync.test.js +75 -0
  27. package/dist/__tests__/model-routing-override-three-site-sync.test.js.map +1 -0
  28. package/dist/__tests__/non-claude-provider-detection.test.js +37 -0
  29. package/dist/__tests__/non-claude-provider-detection.test.js.map +1 -1
  30. package/dist/__tests__/package-dir-resolution-regression.test.js +25 -0
  31. package/dist/__tests__/package-dir-resolution-regression.test.js.map +1 -1
  32. package/dist/__tests__/pre-tool-enforcer.test.js +51 -0
  33. package/dist/__tests__/pre-tool-enforcer.test.js.map +1 -1
  34. package/dist/__tests__/session-start-script-context.test.js +121 -0
  35. package/dist/__tests__/session-start-script-context.test.js.map +1 -1
  36. package/dist/__tests__/setup-claude-md-script.test.js +44 -1
  37. package/dist/__tests__/setup-claude-md-script.test.js.map +1 -1
  38. package/dist/agents/definitions.d.ts.map +1 -1
  39. package/dist/agents/definitions.js +2 -1
  40. package/dist/agents/definitions.js.map +1 -1
  41. package/dist/autoresearch/__tests__/decide-outcome.test.d.ts +2 -0
  42. package/dist/autoresearch/__tests__/decide-outcome.test.d.ts.map +1 -0
  43. package/dist/autoresearch/__tests__/decide-outcome.test.js +69 -0
  44. package/dist/autoresearch/__tests__/decide-outcome.test.js.map +1 -0
  45. package/dist/autoresearch/runtime.d.ts.map +1 -1
  46. package/dist/autoresearch/runtime.js +16 -2
  47. package/dist/autoresearch/runtime.js.map +1 -1
  48. package/dist/cli/__tests__/launch.test.js +23 -0
  49. package/dist/cli/__tests__/launch.test.js.map +1 -1
  50. package/dist/cli/__tests__/self-improve-paths.test.js +3 -2
  51. package/dist/cli/__tests__/self-improve-paths.test.js.map +1 -1
  52. package/dist/cli/__tests__/team.test.js +100 -0
  53. package/dist/cli/__tests__/team.test.js.map +1 -1
  54. package/dist/cli/commands/__tests__/team-role-shorthand.test.js +30 -0
  55. package/dist/cli/commands/__tests__/team-role-shorthand.test.js.map +1 -1
  56. package/dist/cli/commands/__tests__/team.test.js +48 -1
  57. package/dist/cli/commands/__tests__/team.test.js.map +1 -1
  58. package/dist/cli/commands/team.d.ts +2 -0
  59. package/dist/cli/commands/team.d.ts.map +1 -1
  60. package/dist/cli/commands/team.js +9 -2
  61. package/dist/cli/commands/team.js.map +1 -1
  62. package/dist/cli/launch.d.ts.map +1 -1
  63. package/dist/cli/launch.js +7 -0
  64. package/dist/cli/launch.js.map +1 -1
  65. package/dist/cli/team.d.ts.map +1 -1
  66. package/dist/cli/team.js +34 -3
  67. package/dist/cli/team.js.map +1 -1
  68. package/dist/config/__tests__/loader.test.js +35 -4
  69. package/dist/config/__tests__/loader.test.js.map +1 -1
  70. package/dist/config/__tests__/models.test.js +126 -3
  71. package/dist/config/__tests__/models.test.js.map +1 -1
  72. package/dist/config/models.d.ts +8 -0
  73. package/dist/config/models.d.ts.map +1 -1
  74. package/dist/config/models.js +119 -8
  75. package/dist/config/models.js.map +1 -1
  76. package/dist/features/delegation-enforcer.d.ts.map +1 -1
  77. package/dist/features/delegation-enforcer.js +10 -9
  78. package/dist/features/delegation-enforcer.js.map +1 -1
  79. package/dist/hooks/__tests__/bridge-routing.test.js +1 -0
  80. package/dist/hooks/__tests__/bridge-routing.test.js.map +1 -1
  81. package/dist/hooks/autopilot/enforcement.d.ts.map +1 -1
  82. package/dist/hooks/autopilot/enforcement.js +19 -0
  83. package/dist/hooks/autopilot/enforcement.js.map +1 -1
  84. package/dist/hooks/bridge.d.ts.map +1 -1
  85. package/dist/hooks/bridge.js +26 -4
  86. package/dist/hooks/bridge.js.map +1 -1
  87. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js +37 -1
  88. package/dist/hooks/persistent-mode/stop-hook-blocking.test.js.map +1 -1
  89. package/dist/hooks/session-end/index.d.ts +9 -2
  90. package/dist/hooks/session-end/index.d.ts.map +1 -1
  91. package/dist/hooks/session-end/index.js +90 -35
  92. package/dist/hooks/session-end/index.js.map +1 -1
  93. package/dist/hud/stdin.d.ts +12 -1
  94. package/dist/hud/stdin.d.ts.map +1 -1
  95. package/dist/hud/stdin.js +123 -18
  96. package/dist/hud/stdin.js.map +1 -1
  97. package/dist/hud/types.d.ts +1 -0
  98. package/dist/hud/types.d.ts.map +1 -1
  99. package/dist/hud/types.js.map +1 -1
  100. package/dist/installer/__tests__/session-start-template.test.d.ts +2 -0
  101. package/dist/installer/__tests__/session-start-template.test.d.ts.map +1 -0
  102. package/dist/installer/__tests__/session-start-template.test.js +174 -0
  103. package/dist/installer/__tests__/session-start-template.test.js.map +1 -0
  104. package/dist/lib/__tests__/mode-state-io.test.js +75 -12
  105. package/dist/lib/__tests__/mode-state-io.test.js.map +1 -1
  106. package/dist/lib/mode-state-io.d.ts +11 -0
  107. package/dist/lib/mode-state-io.d.ts.map +1 -1
  108. package/dist/lib/mode-state-io.js +64 -0
  109. package/dist/lib/mode-state-io.js.map +1 -1
  110. package/dist/lib/worktree-paths.d.ts +12 -0
  111. package/dist/lib/worktree-paths.d.ts.map +1 -1
  112. package/dist/lib/worktree-paths.js +75 -0
  113. package/dist/lib/worktree-paths.js.map +1 -1
  114. package/dist/planning/__tests__/artifacts.test.d.ts +2 -0
  115. package/dist/planning/__tests__/artifacts.test.d.ts.map +1 -0
  116. package/dist/planning/__tests__/artifacts.test.js +486 -0
  117. package/dist/planning/__tests__/artifacts.test.js.map +1 -0
  118. package/dist/planning/artifact-names.d.ts +13 -0
  119. package/dist/planning/artifact-names.d.ts.map +1 -0
  120. package/dist/planning/artifact-names.js +108 -0
  121. package/dist/planning/artifact-names.js.map +1 -0
  122. package/dist/planning/artifacts.d.ts +47 -0
  123. package/dist/planning/artifacts.d.ts.map +1 -0
  124. package/dist/planning/artifacts.js +221 -0
  125. package/dist/planning/artifacts.js.map +1 -0
  126. package/dist/team/__tests__/api-interop.compatibility.test.js +194 -5
  127. package/dist/team/__tests__/api-interop.compatibility.test.js.map +1 -1
  128. package/dist/team/__tests__/model-contract.test.js +92 -2
  129. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  130. package/dist/team/__tests__/runtime-v2.dispatch.test.js +30 -0
  131. package/dist/team/__tests__/runtime-v2.dispatch.test.js.map +1 -1
  132. package/dist/team/__tests__/scaling.test.js +39 -1
  133. package/dist/team/__tests__/scaling.test.js.map +1 -1
  134. package/dist/team/__tests__/worker-bootstrap.test.js +6 -0
  135. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  136. package/dist/team/api-interop.d.ts.map +1 -1
  137. package/dist/team/api-interop.js +89 -2
  138. package/dist/team/api-interop.js.map +1 -1
  139. package/dist/team/delegation-evidence.d.ts +5 -0
  140. package/dist/team/delegation-evidence.d.ts.map +1 -0
  141. package/dist/team/delegation-evidence.js +29 -0
  142. package/dist/team/delegation-evidence.js.map +1 -0
  143. package/dist/team/model-contract.d.ts +8 -0
  144. package/dist/team/model-contract.d.ts.map +1 -1
  145. package/dist/team/model-contract.js +13 -0
  146. package/dist/team/model-contract.js.map +1 -1
  147. package/dist/team/runtime-v2.d.ts +2 -1
  148. package/dist/team/runtime-v2.d.ts.map +1 -1
  149. package/dist/team/runtime-v2.js +3 -1
  150. package/dist/team/runtime-v2.js.map +1 -1
  151. package/dist/team/state/tasks.d.ts +4 -1
  152. package/dist/team/state/tasks.d.ts.map +1 -1
  153. package/dist/team/state/tasks.js +38 -1
  154. package/dist/team/state/tasks.js.map +1 -1
  155. package/dist/team/team-ops.d.ts +4 -1
  156. package/dist/team/team-ops.d.ts.map +1 -1
  157. package/dist/team/team-ops.js +2 -2
  158. package/dist/team/team-ops.js.map +1 -1
  159. package/dist/team/types.d.ts +22 -1
  160. package/dist/team/types.d.ts.map +1 -1
  161. package/dist/team/types.js.map +1 -1
  162. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  163. package/dist/team/worker-bootstrap.js +6 -1
  164. package/dist/team/worker-bootstrap.js.map +1 -1
  165. package/dist/tools/__tests__/state-tools.test.js +322 -5
  166. package/dist/tools/__tests__/state-tools.test.js.map +1 -1
  167. package/dist/tools/__tests__/wiki-tools-working-directory.test.d.ts +2 -0
  168. package/dist/tools/__tests__/wiki-tools-working-directory.test.d.ts.map +1 -0
  169. package/dist/tools/__tests__/wiki-tools-working-directory.test.js +66 -0
  170. package/dist/tools/__tests__/wiki-tools-working-directory.test.js.map +1 -0
  171. package/dist/tools/state-tools.d.ts +3 -10
  172. package/dist/tools/state-tools.d.ts.map +1 -1
  173. package/dist/tools/state-tools.js +393 -91
  174. package/dist/tools/state-tools.js.map +1 -1
  175. package/dist/tools/wiki-tools.js +8 -8
  176. package/dist/tools/wiki-tools.js.map +1 -1
  177. package/docs/GETTING-STARTED.md +7 -0
  178. package/docs/copilot-instructions.md +1 -1
  179. package/package.json +1 -1
  180. package/scripts/lib/model-routing-override-message.mjs +21 -0
  181. package/scripts/persistent-mode.cjs +36 -0
  182. package/scripts/persistent-mode.mjs +36 -0
  183. package/scripts/post-tool-verifier.mjs +1 -0
  184. package/scripts/pre-tool-enforcer.mjs +60 -0
  185. package/scripts/session-start.mjs +63 -0
  186. package/scripts/setup-copilot-instructions.sh +12 -2
  187. package/skills/configure-notifications/SKILL.md +3 -3
  188. package/skills/mcp-setup/SKILL.md +60 -45
  189. package/skills/omc-setup/SKILL.md +3 -3
  190. package/skills/omc-setup/phases/01-install-claude-md.md +1 -1
  191. package/skills/omc-setup/phases/04-welcome.md +8 -8
  192. package/skills/project-session-manager/SKILL.md +2 -2
  193. package/skills/project-session-manager/psm.sh +1 -1
  194. package/templates/hooks/lib/model-routing-override-message.mjs +21 -0
  195. package/templates/hooks/session-start.mjs +62 -0
@@ -31100,6 +31100,66 @@ function validateWorkingDirectory(workingDirectory) {
31100
31100
  }
31101
31101
  return trustedRoot;
31102
31102
  }
31103
+ function getGitCommonDir(cwd) {
31104
+ try {
31105
+ const commonDir = (0, import_child_process8.execSync)("git rev-parse --path-format=absolute --git-common-dir", {
31106
+ cwd,
31107
+ encoding: "utf-8",
31108
+ stdio: ["pipe", "pipe", "pipe"],
31109
+ timeout: 5e3
31110
+ }).trim();
31111
+ return (0, import_fs9.realpathSync)(commonDir);
31112
+ } catch {
31113
+ return null;
31114
+ }
31115
+ }
31116
+ function validateWorkingDirectoryOrLinkedWorktree(workingDirectory) {
31117
+ const trustedRoot = getWorktreeRoot(process.cwd()) || process.cwd();
31118
+ if (!workingDirectory) {
31119
+ return trustedRoot;
31120
+ }
31121
+ const resolved = (0, import_path11.resolve)(workingDirectory);
31122
+ let trustedRootReal;
31123
+ try {
31124
+ trustedRootReal = (0, import_fs9.realpathSync)(trustedRoot);
31125
+ } catch {
31126
+ trustedRootReal = trustedRoot;
31127
+ }
31128
+ const providedRoot = getWorktreeRoot(resolved);
31129
+ if (providedRoot) {
31130
+ let providedRootReal;
31131
+ try {
31132
+ providedRootReal = (0, import_fs9.realpathSync)(providedRoot);
31133
+ } catch {
31134
+ throw new Error(`workingDirectory '${workingDirectory}' does not exist or is not accessible.`);
31135
+ }
31136
+ if (providedRootReal === trustedRootReal) {
31137
+ return providedRoot;
31138
+ }
31139
+ const trustedCommonDir = getGitCommonDir(trustedRoot);
31140
+ const providedCommonDir = getGitCommonDir(providedRoot);
31141
+ if (trustedCommonDir && providedCommonDir && providedCommonDir === trustedCommonDir) {
31142
+ return providedRoot;
31143
+ }
31144
+ console.error("[worktree] workingDirectory resolved to different git worktree root, using trusted root", {
31145
+ workingDirectory: resolved,
31146
+ providedRoot: providedRootReal,
31147
+ trustedRoot: trustedRootReal
31148
+ });
31149
+ return trustedRoot;
31150
+ }
31151
+ let resolvedReal;
31152
+ try {
31153
+ resolvedReal = (0, import_fs9.realpathSync)(resolved);
31154
+ } catch {
31155
+ throw new Error(`workingDirectory '${workingDirectory}' does not exist or is not accessible.`);
31156
+ }
31157
+ const rel = (0, import_path11.relative)(trustedRootReal, resolvedReal);
31158
+ if (rel.startsWith("..") || (0, import_path11.isAbsolute)(rel)) {
31159
+ throw new Error(`workingDirectory '${workingDirectory}' is outside the trusted worktree root '${trustedRoot}'.`);
31160
+ }
31161
+ return trustedRoot;
31162
+ }
31103
31163
 
31104
31164
  // src/tools/ast-tools.ts
31105
31165
  var import_meta2 = {};
@@ -32450,7 +32510,8 @@ var pythonReplTool = {
32450
32510
  };
32451
32511
 
32452
32512
  // src/tools/state-tools.ts
32453
- var import_fs12 = require("fs");
32513
+ var import_fs13 = require("fs");
32514
+ var import_path15 = require("path");
32454
32515
 
32455
32516
  // src/lib/payload-limits.ts
32456
32517
  var DEFAULT_PAYLOAD_LIMITS = {
@@ -32509,9 +32570,84 @@ function validatePayload(payload, limits = {}) {
32509
32570
  return { valid: true };
32510
32571
  }
32511
32572
 
32512
- // src/hooks/mode-registry/index.ts
32573
+ // src/lib/mode-state-io.ts
32513
32574
  var import_fs11 = require("fs");
32514
32575
  var import_path13 = require("path");
32576
+ function getStateSessionOwner(state) {
32577
+ if (!state || typeof state !== "object") {
32578
+ return void 0;
32579
+ }
32580
+ const meta3 = state._meta;
32581
+ if (meta3 && typeof meta3 === "object") {
32582
+ const metaSessionId = meta3.sessionId;
32583
+ if (typeof metaSessionId === "string" && metaSessionId) {
32584
+ return metaSessionId;
32585
+ }
32586
+ }
32587
+ const topLevelSessionId = state.session_id;
32588
+ return typeof topLevelSessionId === "string" && topLevelSessionId ? topLevelSessionId : void 0;
32589
+ }
32590
+ function canClearStateForSession(state, sessionId) {
32591
+ const ownerSessionId = getStateSessionOwner(state);
32592
+ return !ownerSessionId || ownerSessionId === sessionId;
32593
+ }
32594
+ function resolveStateRoot(directory) {
32595
+ const baseDir = directory || process.cwd();
32596
+ return getWorktreeRoot(baseDir) || baseDir;
32597
+ }
32598
+ function hasSessionEndSummary(baseDir, sessionId) {
32599
+ return (0, import_fs11.existsSync)((0, import_path13.join)(getOmcRoot(baseDir), "sessions", `${sessionId}.json`));
32600
+ }
32601
+ function findSessionOwnedStateFiles(mode, sessionId, directory) {
32602
+ const matches = /* @__PURE__ */ new Set();
32603
+ const baseDir = resolveStateRoot(directory);
32604
+ const expectedPath = resolveSessionStatePath(mode, sessionId, baseDir);
32605
+ if ((0, import_fs11.existsSync)(expectedPath)) {
32606
+ matches.add(expectedPath);
32607
+ }
32608
+ for (const sid of listSessionIds(baseDir)) {
32609
+ const candidatePath = resolveSessionStatePath(mode, sid, baseDir);
32610
+ if (!(0, import_fs11.existsSync)(candidatePath)) {
32611
+ continue;
32612
+ }
32613
+ try {
32614
+ const raw = JSON.parse((0, import_fs11.readFileSync)(candidatePath, "utf-8"));
32615
+ if (getStateSessionOwner(raw) === sessionId) {
32616
+ matches.add(candidatePath);
32617
+ }
32618
+ } catch {
32619
+ }
32620
+ }
32621
+ return [...matches];
32622
+ }
32623
+ function findCompletedSessionStateFiles(mode, directory, requesterSessionId) {
32624
+ const matches = /* @__PURE__ */ new Set();
32625
+ const baseDir = resolveStateRoot(directory);
32626
+ for (const sid of listSessionIds(baseDir)) {
32627
+ if (requesterSessionId && sid === requesterSessionId) {
32628
+ continue;
32629
+ }
32630
+ if (!hasSessionEndSummary(baseDir, sid)) {
32631
+ continue;
32632
+ }
32633
+ const candidatePath = resolveSessionStatePath(mode, sid, baseDir);
32634
+ if (!(0, import_fs11.existsSync)(candidatePath)) {
32635
+ continue;
32636
+ }
32637
+ try {
32638
+ const raw = JSON.parse((0, import_fs11.readFileSync)(candidatePath, "utf-8"));
32639
+ if (raw.active === true) {
32640
+ matches.add(candidatePath);
32641
+ }
32642
+ } catch {
32643
+ }
32644
+ }
32645
+ return [...matches];
32646
+ }
32647
+
32648
+ // src/hooks/mode-registry/index.ts
32649
+ var import_fs12 = require("fs");
32650
+ var import_path14 = require("path");
32515
32651
 
32516
32652
  // src/lib/mode-names.ts
32517
32653
  var MODE_NAMES = {
@@ -32619,26 +32755,26 @@ var MODE_CONFIGS = {
32619
32755
  };
32620
32756
  var EXCLUSIVE_MODES = [MODE_NAMES.AUTOPILOT, MODE_NAMES.AUTORESEARCH];
32621
32757
  function getStateDir(cwd) {
32622
- return (0, import_path13.join)(getOmcRoot(cwd), "state");
32758
+ return (0, import_path14.join)(getOmcRoot(cwd), "state");
32623
32759
  }
32624
32760
  function getStateFilePath(cwd, mode, sessionId) {
32625
32761
  const config2 = MODE_CONFIGS[mode];
32626
32762
  if (sessionId) {
32627
32763
  return resolveSessionStatePath(mode, sessionId, cwd);
32628
32764
  }
32629
- return (0, import_path13.join)(getStateDir(cwd), config2.stateFile);
32765
+ return (0, import_path14.join)(getStateDir(cwd), config2.stateFile);
32630
32766
  }
32631
32767
  function getMarkerFilePath(cwd, mode) {
32632
32768
  const config2 = MODE_CONFIGS[mode];
32633
32769
  if (!config2.markerFile) return null;
32634
- return (0, import_path13.join)(getStateDir(cwd), config2.markerFile);
32770
+ return (0, import_path14.join)(getStateDir(cwd), config2.markerFile);
32635
32771
  }
32636
32772
  var WORKFLOW_SLOT_TOMBSTONE_TTL_MS = 24 * 60 * 60 * 1e3;
32637
32773
  function isWorkflowSlotTombstonedForMode(cwd, mode, sessionId, now = Date.now()) {
32638
32774
  try {
32639
- const ledgerPath = sessionId ? resolveSessionStatePath("skill-active", sessionId, cwd) : (0, import_path13.join)(getStateDir(cwd), "skill-active-state.json");
32640
- if (!(0, import_fs11.existsSync)(ledgerPath)) return false;
32641
- const raw = JSON.parse((0, import_fs11.readFileSync)(ledgerPath, "utf-8"));
32775
+ const ledgerPath = sessionId ? resolveSessionStatePath("skill-active", sessionId, cwd) : (0, import_path14.join)(getStateDir(cwd), "skill-active-state.json");
32776
+ if (!(0, import_fs12.existsSync)(ledgerPath)) return false;
32777
+ const raw = JSON.parse((0, import_fs12.readFileSync)(ledgerPath, "utf-8"));
32642
32778
  const slots = raw.active_skills;
32643
32779
  if (!slots || typeof slots !== "object") return false;
32644
32780
  const slot = slots[mode];
@@ -32661,7 +32797,7 @@ function isJsonModeActive(cwd, mode, sessionId) {
32661
32797
  }
32662
32798
  const sessionStateFile = resolveSessionStatePath(mode, sessionId, cwd);
32663
32799
  try {
32664
- const content = (0, import_fs11.readFileSync)(sessionStateFile, "utf-8");
32800
+ const content = (0, import_fs12.readFileSync)(sessionStateFile, "utf-8");
32665
32801
  const state = JSON.parse(content);
32666
32802
  if (state.session_id && state.session_id !== sessionId) {
32667
32803
  return false;
@@ -32679,7 +32815,7 @@ function isJsonModeActive(cwd, mode, sessionId) {
32679
32815
  }
32680
32816
  const stateFile = getStateFilePath(cwd, mode);
32681
32817
  try {
32682
- const content = (0, import_fs11.readFileSync)(stateFile, "utf-8");
32818
+ const content = (0, import_fs12.readFileSync)(stateFile, "utf-8");
32683
32819
  const state = JSON.parse(content);
32684
32820
  if (config2.activeProperty) {
32685
32821
  return state[config2.activeProperty] === true;
@@ -32719,7 +32855,7 @@ function clearModeState(mode, cwd, sessionId) {
32719
32855
  if (isSessionScopedClear && sessionId) {
32720
32856
  const sessionStateFile = resolveSessionStatePath(mode, sessionId, cwd);
32721
32857
  try {
32722
- (0, import_fs11.unlinkSync)(sessionStateFile);
32858
+ (0, import_fs12.unlinkSync)(sessionStateFile);
32723
32859
  } catch (err) {
32724
32860
  if (err.code !== "ENOENT") {
32725
32861
  success2 = false;
@@ -32733,7 +32869,7 @@ function clearModeState(mode, cwd, sessionId) {
32733
32869
  cwd
32734
32870
  );
32735
32871
  try {
32736
- (0, import_fs11.unlinkSync)(sessionMarkerFile);
32872
+ (0, import_fs12.unlinkSync)(sessionMarkerFile);
32737
32873
  } catch (err) {
32738
32874
  if (err.code !== "ENOENT") {
32739
32875
  success2 = false;
@@ -32742,11 +32878,11 @@ function clearModeState(mode, cwd, sessionId) {
32742
32878
  }
32743
32879
  if (markerFile) {
32744
32880
  try {
32745
- const markerRaw = JSON.parse((0, import_fs11.readFileSync)(markerFile, "utf-8"));
32881
+ const markerRaw = JSON.parse((0, import_fs12.readFileSync)(markerFile, "utf-8"));
32746
32882
  const markerSessionId = markerRaw.session_id ?? markerRaw.sessionId;
32747
32883
  if (!markerSessionId || markerSessionId === sessionId) {
32748
32884
  try {
32749
- (0, import_fs11.unlinkSync)(markerFile);
32885
+ (0, import_fs12.unlinkSync)(markerFile);
32750
32886
  } catch (err) {
32751
32887
  if (err.code !== "ENOENT") {
32752
32888
  success2 = false;
@@ -32755,7 +32891,7 @@ function clearModeState(mode, cwd, sessionId) {
32755
32891
  }
32756
32892
  } catch {
32757
32893
  try {
32758
- (0, import_fs11.unlinkSync)(markerFile);
32894
+ (0, import_fs12.unlinkSync)(markerFile);
32759
32895
  } catch (err) {
32760
32896
  if (err.code !== "ENOENT") {
32761
32897
  success2 = false;
@@ -32767,7 +32903,7 @@ function clearModeState(mode, cwd, sessionId) {
32767
32903
  const stateFile = getStateFilePath(cwd, mode);
32768
32904
  if (!isSessionScopedClear) {
32769
32905
  try {
32770
- (0, import_fs11.unlinkSync)(stateFile);
32906
+ (0, import_fs12.unlinkSync)(stateFile);
32771
32907
  } catch (err) {
32772
32908
  if (err.code !== "ENOENT") {
32773
32909
  success2 = false;
@@ -32777,11 +32913,11 @@ function clearModeState(mode, cwd, sessionId) {
32777
32913
  if (markerFile) {
32778
32914
  if (isSessionScopedClear) {
32779
32915
  try {
32780
- const markerRaw = JSON.parse((0, import_fs11.readFileSync)(markerFile, "utf-8"));
32916
+ const markerRaw = JSON.parse((0, import_fs12.readFileSync)(markerFile, "utf-8"));
32781
32917
  const markerSessionId = markerRaw.session_id ?? markerRaw.sessionId;
32782
32918
  if (!markerSessionId || markerSessionId === sessionId) {
32783
32919
  try {
32784
- (0, import_fs11.unlinkSync)(markerFile);
32920
+ (0, import_fs12.unlinkSync)(markerFile);
32785
32921
  } catch (err) {
32786
32922
  if (err.code !== "ENOENT") {
32787
32923
  success2 = false;
@@ -32790,7 +32926,7 @@ function clearModeState(mode, cwd, sessionId) {
32790
32926
  }
32791
32927
  } catch {
32792
32928
  try {
32793
- (0, import_fs11.unlinkSync)(markerFile);
32929
+ (0, import_fs12.unlinkSync)(markerFile);
32794
32930
  } catch (err) {
32795
32931
  if (err.code !== "ENOENT") {
32796
32932
  success2 = false;
@@ -32799,7 +32935,7 @@ function clearModeState(mode, cwd, sessionId) {
32799
32935
  }
32800
32936
  } else {
32801
32937
  try {
32802
- (0, import_fs11.unlinkSync)(markerFile);
32938
+ (0, import_fs12.unlinkSync)(markerFile);
32803
32939
  } catch (err) {
32804
32940
  if (err.code !== "ENOENT") {
32805
32941
  success2 = false;
@@ -32833,12 +32969,165 @@ var STATE_TOOL_MODES = [
32833
32969
  ];
32834
32970
  var EXTRA_STATE_ONLY_MODES = ["ralplan", "omc-teams", "skill-active"];
32835
32971
  var CANCEL_SIGNAL_TTL_MS = 3e4;
32972
+ function readTeamNamesFromStateFile(statePath) {
32973
+ if (!(0, import_fs13.existsSync)(statePath)) return [];
32974
+ try {
32975
+ const raw = JSON.parse((0, import_fs13.readFileSync)(statePath, "utf-8"));
32976
+ const teamName = typeof raw.team_name === "string" ? raw.team_name.trim() : typeof raw.teamName === "string" ? raw.teamName.trim() : "";
32977
+ return teamName ? [teamName] : [];
32978
+ } catch {
32979
+ return [];
32980
+ }
32981
+ }
32982
+ function pruneMissionBoardTeams(root, teamNames) {
32983
+ const missionStatePath = (0, import_path15.join)(getOmcRoot(root), "state", "mission-state.json");
32984
+ if (!(0, import_fs13.existsSync)(missionStatePath)) return 0;
32985
+ try {
32986
+ const parsed = JSON.parse((0, import_fs13.readFileSync)(missionStatePath, "utf-8"));
32987
+ if (!Array.isArray(parsed.missions)) return 0;
32988
+ const shouldRemoveAll = teamNames == null;
32989
+ const teamNameSet = new Set(teamNames ?? []);
32990
+ const remainingMissions = parsed.missions.filter((mission) => {
32991
+ if (mission.source !== "team") return true;
32992
+ if (shouldRemoveAll) return false;
32993
+ const missionTeamName = typeof mission.teamName === "string" ? mission.teamName.trim() : typeof mission.name === "string" ? mission.name.trim() : "";
32994
+ return !missionTeamName || !teamNameSet.has(missionTeamName);
32995
+ });
32996
+ const removed = parsed.missions.length - remainingMissions.length;
32997
+ if (removed > 0) {
32998
+ (0, import_fs13.writeFileSync)(missionStatePath, JSON.stringify({
32999
+ ...parsed,
33000
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
33001
+ missions: remainingMissions
33002
+ }, null, 2));
33003
+ }
33004
+ return removed;
33005
+ } catch {
33006
+ return 0;
33007
+ }
33008
+ }
33009
+ function cleanupTeamRuntimeState(root, teamNames) {
33010
+ const teamStateRoot = (0, import_path15.join)(getOmcRoot(root), "state", "team");
33011
+ if (!(0, import_fs13.existsSync)(teamStateRoot)) return 0;
33012
+ const shouldRemoveAll = teamNames == null;
33013
+ let removed = 0;
33014
+ if (shouldRemoveAll) {
33015
+ try {
33016
+ (0, import_fs13.rmSync)(teamStateRoot, { recursive: true, force: true });
33017
+ return 1;
33018
+ } catch {
33019
+ return 0;
33020
+ }
33021
+ }
33022
+ for (const teamName of teamNames ?? []) {
33023
+ if (!teamName) continue;
33024
+ try {
33025
+ (0, import_fs13.rmSync)((0, import_path15.join)(teamStateRoot, teamName), { recursive: true, force: true });
33026
+ removed += 1;
33027
+ } catch {
33028
+ }
33029
+ }
33030
+ return removed;
33031
+ }
32836
33032
  function getStatePath(mode, root) {
32837
33033
  if (MODE_CONFIGS[mode]) {
32838
33034
  return getStateFilePath(root, mode);
32839
33035
  }
32840
33036
  return resolveStatePath(mode, root);
32841
33037
  }
33038
+ function getLegacyStateFileCandidates(mode, root) {
33039
+ const normalizedName = mode.endsWith("-state") ? mode : `${mode}-state`;
33040
+ const candidates = [
33041
+ getStatePath(mode, root),
33042
+ (0, import_path15.join)(getOmcRoot(root), `${normalizedName}.json`)
33043
+ ];
33044
+ return [...new Set(candidates)];
33045
+ }
33046
+ function clearLegacyStateCandidates(mode, root, sessionId) {
33047
+ let cleared = 0;
33048
+ let hadFailure = false;
33049
+ for (const legacyPath of getLegacyStateFileCandidates(mode, root)) {
33050
+ if (!(0, import_fs13.existsSync)(legacyPath)) {
33051
+ continue;
33052
+ }
33053
+ try {
33054
+ if (sessionId) {
33055
+ const raw = JSON.parse((0, import_fs13.readFileSync)(legacyPath, "utf-8"));
33056
+ if (!canClearStateForSession(raw, sessionId)) {
33057
+ continue;
33058
+ }
33059
+ }
33060
+ (0, import_fs13.unlinkSync)(legacyPath);
33061
+ cleared++;
33062
+ } catch {
33063
+ hadFailure = true;
33064
+ }
33065
+ }
33066
+ return { cleared, hadFailure };
33067
+ }
33068
+ function clearSessionOwnedStateCandidates(mode, root, sessionId) {
33069
+ let cleared = 0;
33070
+ let hadFailure = false;
33071
+ const paths = findSessionOwnedStateFiles(mode, sessionId, root);
33072
+ for (const statePath of paths) {
33073
+ try {
33074
+ (0, import_fs13.unlinkSync)(statePath);
33075
+ cleared++;
33076
+ } catch {
33077
+ hadFailure = true;
33078
+ }
33079
+ }
33080
+ return { cleared, hadFailure, paths };
33081
+ }
33082
+ function clearCompletedSessionStateCandidates(mode, root, requesterSessionId) {
33083
+ let cleared = 0;
33084
+ let hadFailure = false;
33085
+ const paths = findCompletedSessionStateFiles(mode, root, requesterSessionId);
33086
+ for (const statePath of paths) {
33087
+ try {
33088
+ (0, import_fs13.unlinkSync)(statePath);
33089
+ cleared++;
33090
+ } catch {
33091
+ hadFailure = true;
33092
+ }
33093
+ }
33094
+ return { cleared, hadFailure, paths };
33095
+ }
33096
+ function getModeRuntimeArtifactNames(mode) {
33097
+ return [
33098
+ `${mode}-stop-breaker.json`,
33099
+ `${mode}-last-steer-at`,
33100
+ `${mode}-continue-steer.lock`
33101
+ ];
33102
+ }
33103
+ function clearModeRuntimeArtifacts(mode, root, sessionId) {
33104
+ let cleared = 0;
33105
+ let hadFailure = false;
33106
+ const stateRoot = (0, import_path15.join)(getOmcRoot(root), "state");
33107
+ const candidateDirs = /* @__PURE__ */ new Set([stateRoot]);
33108
+ if (sessionId) {
33109
+ candidateDirs.add((0, import_path15.join)(stateRoot, "sessions", sessionId));
33110
+ } else {
33111
+ for (const sid of listSessionIds(root)) {
33112
+ candidateDirs.add((0, import_path15.join)(stateRoot, "sessions", sid));
33113
+ }
33114
+ }
33115
+ for (const dir of candidateDirs) {
33116
+ for (const artifactName of getModeRuntimeArtifactNames(mode)) {
33117
+ const artifactPath = (0, import_path15.join)(dir, artifactName);
33118
+ if (!(0, import_fs13.existsSync)(artifactPath)) {
33119
+ continue;
33120
+ }
33121
+ try {
33122
+ (0, import_fs13.unlinkSync)(artifactPath);
33123
+ cleared++;
33124
+ } catch {
33125
+ hadFailure = true;
33126
+ }
33127
+ }
33128
+ }
33129
+ return { cleared, hadFailure };
33130
+ }
32842
33131
  function writeSessionCancelSignal(root, sessionId, mode) {
32843
33132
  const now = Date.now();
32844
33133
  const cancelSignalPath = resolveSessionStatePath("cancel-signal", sessionId, root);
@@ -32855,11 +33144,11 @@ function isSessionModeActive(mode, root, sessionId) {
32855
33144
  return isModeActive(mode, root, sessionId);
32856
33145
  }
32857
33146
  const statePath = resolveSessionStatePath(mode, sessionId, root);
32858
- if (!(0, import_fs12.existsSync)(statePath)) {
33147
+ if (!(0, import_fs13.existsSync)(statePath)) {
32859
33148
  return false;
32860
33149
  }
32861
33150
  try {
32862
- const state = JSON.parse((0, import_fs12.readFileSync)(statePath, "utf-8"));
33151
+ const state = JSON.parse((0, import_fs13.readFileSync)(statePath, "utf-8"));
32863
33152
  return state.active === true;
32864
33153
  } catch {
32865
33154
  return false;
@@ -32886,7 +33175,31 @@ var stateReadTool = {
32886
33175
  if (sessionId) {
32887
33176
  validateSessionId(sessionId);
32888
33177
  const statePath2 = MODE_CONFIGS[mode] ? getStateFilePath(root, mode, sessionId) : resolveSessionStatePath(mode, sessionId, root);
32889
- if (!(0, import_fs12.existsSync)(statePath2)) {
33178
+ if (!(0, import_fs13.existsSync)(statePath2)) {
33179
+ const completedSessionPaths = findCompletedSessionStateFiles(mode, root, sessionId);
33180
+ if (completedSessionPaths.length > 0) {
33181
+ const orphanList = completedSessionPaths.map((orphanPath) => {
33182
+ const sessionMarker = `${(0, import_path15.join)("state", "sessions")}/`;
33183
+ const markerIndex = orphanPath.indexOf(sessionMarker);
33184
+ if (markerIndex === -1) return `- ${orphanPath}`;
33185
+ const rest = orphanPath.slice(markerIndex + sessionMarker.length);
33186
+ const orphanSessionId = rest.split(/[\\/]/)[0] || "unknown";
33187
+ return `- session: ${orphanSessionId}
33188
+ path: ${orphanPath}`;
33189
+ }).join("\n");
33190
+ return {
33191
+ content: [{
33192
+ type: "text",
33193
+ text: `No state found for mode: ${mode} in session: ${sessionId}
33194
+ Expected path: ${statePath2}
33195
+
33196
+ Discovered ${completedSessionPaths.length} completed-session orphan state file${completedSessionPaths.length === 1 ? "" : "s"} for this mode:
33197
+ ${orphanList}
33198
+
33199
+ Run state_clear(mode="${mode}", session_id="${sessionId}") to clear the current session plus these completed-session orphan files.`
33200
+ }]
33201
+ };
33202
+ }
32890
33203
  return {
32891
33204
  content: [{
32892
33205
  type: "text",
@@ -32895,7 +33208,7 @@ Expected path: ${statePath2}`
32895
33208
  }]
32896
33209
  };
32897
33210
  }
32898
- const content = (0, import_fs12.readFileSync)(statePath2, "utf-8");
33211
+ const content = (0, import_fs13.readFileSync)(statePath2, "utf-8");
32899
33212
  const state = JSON.parse(content);
32900
33213
  return {
32901
33214
  content: [{
@@ -32911,12 +33224,12 @@ ${JSON.stringify(state, null, 2)}
32911
33224
  };
32912
33225
  }
32913
33226
  const statePath = getStatePath(mode, root);
32914
- const legacyExists = (0, import_fs12.existsSync)(statePath);
33227
+ const legacyExists = (0, import_fs13.existsSync)(statePath);
32915
33228
  const sessionIds = listSessionIds(root);
32916
33229
  const activeSessions = [];
32917
33230
  for (const sid of sessionIds) {
32918
33231
  const sessionStatePath = MODE_CONFIGS[mode] ? getStateFilePath(root, mode, sid) : resolveSessionStatePath(mode, sid, root);
32919
- if ((0, import_fs12.existsSync)(sessionStatePath)) {
33232
+ if ((0, import_fs13.existsSync)(sessionStatePath)) {
32920
33233
  activeSessions.push(sid);
32921
33234
  }
32922
33235
  }
@@ -32939,7 +33252,7 @@ Note: Reading from legacy/aggregate path (no session_id). This may include state
32939
33252
  `;
32940
33253
  if (legacyExists) {
32941
33254
  try {
32942
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33255
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
32943
33256
  const state = JSON.parse(content);
32944
33257
  output += `### Legacy Path (shared)
32945
33258
  Path: ${statePath}
@@ -32964,7 +33277,7 @@ Path: ${statePath}
32964
33277
  for (const sid of activeSessions) {
32965
33278
  const sessionStatePath = MODE_CONFIGS[mode] ? getStateFilePath(root, mode, sid) : resolveSessionStatePath(mode, sid, root);
32966
33279
  try {
32967
- const content = (0, import_fs12.readFileSync)(sessionStatePath, "utf-8");
33280
+ const content = (0, import_fs13.readFileSync)(sessionStatePath, "utf-8");
32968
33281
  const state = JSON.parse(content);
32969
33282
  output += `**Session: ${sid}**
32970
33283
  Path: ${sessionStatePath}
@@ -33120,124 +33433,209 @@ var stateClearTool = {
33120
33433
  session_id: external_exports3.string().optional().describe("Session ID for session-scoped state isolation. When provided, the tool operates only within that session. When omitted, the tool aggregates legacy state plus all session-scoped state (may include other sessions).")
33121
33434
  },
33122
33435
  handler: async (args) => {
33123
- const { mode, workingDirectory, session_id } = args;
33436
+ const { workingDirectory, session_id } = args;
33437
+ const mode = args.mode;
33124
33438
  try {
33125
33439
  const root = validateWorkingDirectory(workingDirectory);
33126
33440
  const sessionId = session_id;
33441
+ const cleanedTeamNames = /* @__PURE__ */ new Set();
33442
+ const collectTeamNamesForCleanup = (statePath) => {
33443
+ if (mode !== "team") return;
33444
+ for (const teamName of readTeamNamesFromStateFile(statePath)) {
33445
+ cleanedTeamNames.add(teamName);
33446
+ }
33447
+ };
33127
33448
  if (sessionId) {
33128
33449
  validateSessionId(sessionId);
33450
+ const requestedSessionOwnedPaths = findSessionOwnedStateFiles(mode, sessionId, root);
33451
+ for (const teamStatePath of findSessionOwnedStateFiles("team", sessionId, root)) {
33452
+ collectTeamNamesForCleanup(teamStatePath);
33453
+ }
33454
+ if (mode === "team") {
33455
+ for (const teamStatePath of findCompletedSessionStateFiles("team", root, sessionId)) {
33456
+ collectTeamNamesForCleanup(teamStatePath);
33457
+ }
33458
+ }
33459
+ const completedSessionCleanup = clearCompletedSessionStateCandidates(mode, root, sessionId);
33460
+ const runtimeCleanup2 = clearModeRuntimeArtifacts(mode, root, sessionId);
33129
33461
  writeSessionCancelSignal(root, sessionId, mode);
33130
33462
  if (MODE_CONFIGS[mode]) {
33131
- const requesterStatePath = getStateFilePath(root, mode, sessionId);
33132
- const hadRequesterState2 = (0, import_fs12.existsSync)(requesterStatePath);
33133
33463
  const success2 = clearModeState(mode, root, sessionId);
33134
- let ghostCleaned2 = false;
33135
- try {
33136
- const legacyPath = getStateFilePath(root, mode);
33137
- if ((0, import_fs12.existsSync)(legacyPath)) {
33138
- const raw = JSON.parse((0, import_fs12.readFileSync)(legacyPath, "utf-8"));
33139
- const meta3 = raw._meta;
33140
- if (!meta3 || meta3.sessionId === sessionId) {
33141
- (0, import_fs12.unlinkSync)(legacyPath);
33142
- ghostCleaned2 = true;
33143
- }
33144
- }
33145
- } catch {
33146
- }
33464
+ const sessionCleanup2 = clearSessionOwnedStateCandidates(mode, root, sessionId);
33465
+ const legacyCleanup2 = clearLegacyStateCandidates(mode, root, sessionId);
33147
33466
  let ownerSessionId2;
33148
- if (!hadRequesterState2 && !ghostCleaned2) {
33467
+ let ownerSessionCleanup2 = { cleared: 0, hadFailure: false, paths: [] };
33468
+ let ownerLegacyCleanup2 = { cleared: 0, hadFailure: false };
33469
+ if (requestedSessionOwnedPaths.length === 0 && completedSessionCleanup.cleared === 0 && sessionCleanup2.cleared === 0 && legacyCleanup2.cleared === 0) {
33149
33470
  ownerSessionId2 = findSingleOwningSessionForMode(mode, root, sessionId);
33150
33471
  if (ownerSessionId2) {
33472
+ if (mode === "team") {
33473
+ for (const teamStatePath of findSessionOwnedStateFiles("team", ownerSessionId2, root)) {
33474
+ collectTeamNamesForCleanup(teamStatePath);
33475
+ }
33476
+ }
33151
33477
  writeSessionCancelSignal(root, ownerSessionId2, mode);
33478
+ const ownerRuntimeCleanup = clearModeRuntimeArtifacts(mode, root, ownerSessionId2);
33479
+ runtimeCleanup2.cleared += ownerRuntimeCleanup.cleared;
33480
+ runtimeCleanup2.hadFailure ||= ownerRuntimeCleanup.hadFailure;
33152
33481
  clearModeState(mode, root, ownerSessionId2);
33482
+ ownerSessionCleanup2 = clearSessionOwnedStateCandidates(mode, root, ownerSessionId2);
33483
+ ownerLegacyCleanup2 = clearLegacyStateCandidates(mode, root, ownerSessionId2);
33153
33484
  }
33154
33485
  }
33155
- const ghostNote2 = ghostCleaned2 ? " (ghost legacy file also removed)" : "";
33156
- const ownerNote2 = ownerSessionId2 ? ` (cleared owning session: ${ownerSessionId2})` : "";
33157
- if (success2 || ownerSessionId2) {
33486
+ const ghostNoteParts2 = [];
33487
+ if (legacyCleanup2.cleared > 0) {
33488
+ ghostNoteParts2.push("ghost legacy file also removed");
33489
+ }
33490
+ if (completedSessionCleanup.cleared > 0) {
33491
+ ghostNoteParts2.push(`removed ${completedSessionCleanup.cleared} completed-session orphan file${completedSessionCleanup.cleared === 1 ? "" : "s"}`);
33492
+ }
33493
+ if (sessionCleanup2.cleared > 0) {
33494
+ ghostNoteParts2.push(`removed ${sessionCleanup2.cleared} recovered session file${sessionCleanup2.cleared === 1 ? "" : "s"}`);
33495
+ }
33496
+ if (runtimeCleanup2.cleared > 0) {
33497
+ ghostNoteParts2.push(`removed ${runtimeCleanup2.cleared} runtime artifact${runtimeCleanup2.cleared === 1 ? "" : "s"}`);
33498
+ }
33499
+ if (ownerSessionId2) {
33500
+ ghostNoteParts2.push(`cleared owning session: ${ownerSessionId2}`);
33501
+ }
33502
+ const ghostNote2 = ghostNoteParts2.length > 0 ? ` (${ghostNoteParts2.join(", ")})` : "";
33503
+ const runtimeCleanupNote2 = (() => {
33504
+ if (mode !== "team") return "";
33505
+ const teamNames = [...cleanedTeamNames];
33506
+ const removedRoots = cleanupTeamRuntimeState(root, teamNames);
33507
+ const prunedMissions = pruneMissionBoardTeams(root, teamNames);
33508
+ const details = [];
33509
+ if (removedRoots > 0) details.push(`removed ${removedRoots} team runtime root(s)`);
33510
+ if (prunedMissions > 0) details.push(`pruned ${prunedMissions} HUD mission entry(ies)`);
33511
+ return details.length > 0 ? ` (${details.join(", ")})` : "";
33512
+ })();
33513
+ if (success2 && !legacyCleanup2.hadFailure && !sessionCleanup2.hadFailure && !completedSessionCleanup.hadFailure && !ownerSessionCleanup2.hadFailure && !ownerLegacyCleanup2.hadFailure && !runtimeCleanup2.hadFailure) {
33158
33514
  return {
33159
33515
  content: [{
33160
33516
  type: "text",
33161
- text: `Successfully cleared state for mode: ${mode} in session: ${sessionId}${ghostNote2}${ownerNote2}`
33517
+ text: `Successfully cleared state for mode: ${mode} in session: ${sessionId}${ghostNote2}${runtimeCleanupNote2}`
33162
33518
  }]
33163
33519
  };
33164
33520
  } else {
33165
33521
  return {
33166
33522
  content: [{
33167
33523
  type: "text",
33168
- text: `Warning: Some files could not be removed for mode: ${mode} in session: ${sessionId}${ghostNote2}${ownerNote2}`
33524
+ text: `Warning: Some files could not be removed for mode: ${mode} in session: ${sessionId}${ghostNote2}${runtimeCleanupNote2}`
33169
33525
  }]
33170
33526
  };
33171
33527
  }
33172
33528
  }
33173
- const statePath = resolveSessionStatePath(mode, sessionId, root);
33174
- const hadRequesterState = (0, import_fs12.existsSync)(statePath);
33175
- if (hadRequesterState) {
33176
- (0, import_fs12.unlinkSync)(statePath);
33177
- }
33178
- let ghostCleaned = false;
33179
- try {
33180
- const legacyPath = resolveStatePath(mode, root);
33181
- if ((0, import_fs12.existsSync)(legacyPath)) {
33182
- const raw = JSON.parse((0, import_fs12.readFileSync)(legacyPath, "utf-8"));
33183
- const meta3 = raw._meta;
33184
- if (!meta3 || meta3.sessionId === sessionId) {
33185
- (0, import_fs12.unlinkSync)(legacyPath);
33186
- ghostCleaned = true;
33187
- }
33188
- }
33189
- } catch {
33190
- }
33529
+ const sessionCleanup = clearSessionOwnedStateCandidates(mode, root, sessionId);
33530
+ const legacyCleanup = clearLegacyStateCandidates(mode, root, sessionId);
33191
33531
  let ownerSessionId;
33192
- if (!hadRequesterState && !ghostCleaned) {
33532
+ let ownerSessionCleanup = { cleared: 0, hadFailure: false, paths: [] };
33533
+ let ownerLegacyCleanup = { cleared: 0, hadFailure: false };
33534
+ if (requestedSessionOwnedPaths.length === 0 && completedSessionCleanup.cleared === 0 && sessionCleanup.cleared === 0 && legacyCleanup.cleared === 0) {
33193
33535
  ownerSessionId = findSingleOwningSessionForMode(mode, root, sessionId);
33194
33536
  if (ownerSessionId) {
33195
- writeSessionCancelSignal(root, ownerSessionId, mode);
33196
- const ownerStatePath = resolveSessionStatePath(mode, ownerSessionId, root);
33197
- if ((0, import_fs12.existsSync)(ownerStatePath)) {
33198
- try {
33199
- (0, import_fs12.unlinkSync)(ownerStatePath);
33200
- } catch {
33537
+ if (mode === "team") {
33538
+ for (const teamStatePath of findSessionOwnedStateFiles("team", ownerSessionId, root)) {
33539
+ collectTeamNamesForCleanup(teamStatePath);
33201
33540
  }
33202
33541
  }
33542
+ writeSessionCancelSignal(root, ownerSessionId, mode);
33543
+ const ownerRuntimeCleanup = clearModeRuntimeArtifacts(mode, root, ownerSessionId);
33544
+ runtimeCleanup2.cleared += ownerRuntimeCleanup.cleared;
33545
+ runtimeCleanup2.hadFailure ||= ownerRuntimeCleanup.hadFailure;
33546
+ ownerSessionCleanup = clearSessionOwnedStateCandidates(mode, root, ownerSessionId);
33547
+ ownerLegacyCleanup = clearLegacyStateCandidates(mode, root, ownerSessionId);
33203
33548
  }
33204
33549
  }
33205
- const ghostNote = ghostCleaned ? " (ghost legacy file also removed)" : "";
33206
- const ownerNote = ownerSessionId ? ` (cleared owning session: ${ownerSessionId})` : "";
33550
+ const ghostNoteParts = [];
33551
+ if (legacyCleanup.cleared > 0) {
33552
+ ghostNoteParts.push("ghost legacy file also removed");
33553
+ }
33554
+ if (completedSessionCleanup.cleared > 0) {
33555
+ ghostNoteParts.push(`removed ${completedSessionCleanup.cleared} completed-session orphan file${completedSessionCleanup.cleared === 1 ? "" : "s"}`);
33556
+ }
33557
+ if (sessionCleanup.cleared > 0) {
33558
+ ghostNoteParts.push(`removed ${sessionCleanup.cleared} recovered session file${sessionCleanup.cleared === 1 ? "" : "s"}`);
33559
+ }
33560
+ if (runtimeCleanup2.cleared > 0) {
33561
+ ghostNoteParts.push(`removed ${runtimeCleanup2.cleared} runtime artifact${runtimeCleanup2.cleared === 1 ? "" : "s"}`);
33562
+ }
33563
+ if (ownerSessionId) {
33564
+ ghostNoteParts.push(`cleared owning session: ${ownerSessionId}`);
33565
+ }
33566
+ const ghostNote = ghostNoteParts.length > 0 ? ` (${ghostNoteParts.join(", ")})` : "";
33567
+ const runtimeCleanupNote = (() => {
33568
+ if (mode !== "team") return "";
33569
+ const teamNames = [...cleanedTeamNames];
33570
+ const removedRoots = cleanupTeamRuntimeState(root, teamNames);
33571
+ const prunedMissions = pruneMissionBoardTeams(root, teamNames);
33572
+ const details = [];
33573
+ if (removedRoots > 0) details.push(`removed ${removedRoots} team runtime root(s)`);
33574
+ if (prunedMissions > 0) details.push(`pruned ${prunedMissions} HUD mission entry(ies)`);
33575
+ return details.length > 0 ? ` (${details.join(", ")})` : "";
33576
+ })();
33207
33577
  return {
33208
33578
  content: [{
33209
33579
  type: "text",
33210
- text: `Successfully cleared state for mode: ${mode} in session: ${sessionId}${ghostNote}${ownerNote}`
33580
+ text: `${legacyCleanup.hadFailure || sessionCleanup.hadFailure || completedSessionCleanup.hadFailure || ownerSessionCleanup.hadFailure || ownerLegacyCleanup.hadFailure || runtimeCleanup2.hadFailure ? "Warning: Some files could not be removed" : "Successfully cleared state"} for mode: ${mode} in session: ${sessionId}${ghostNote}${runtimeCleanupNote}`
33211
33581
  }]
33212
33582
  };
33213
33583
  }
33584
+ {
33585
+ const now = Date.now();
33586
+ const cancelSignalPayload = {
33587
+ active: true,
33588
+ requested_at: new Date(now).toISOString(),
33589
+ expires_at: new Date(now + CANCEL_SIGNAL_TTL_MS).toISOString(),
33590
+ mode,
33591
+ source: "state_clear"
33592
+ };
33593
+ const legacySignalPath = (0, import_path15.join)(getOmcRoot(root), "state", "cancel-signal-state.json");
33594
+ try {
33595
+ atomicWriteJsonSync(legacySignalPath, cancelSignalPayload);
33596
+ } catch {
33597
+ }
33598
+ for (const sid of listSessionIds(root)) {
33599
+ try {
33600
+ const sessionSignalPath = resolveSessionStatePath("cancel-signal", sid, root);
33601
+ atomicWriteJsonSync(sessionSignalPath, cancelSignalPayload);
33602
+ } catch {
33603
+ }
33604
+ }
33605
+ }
33606
+ const runtimeCleanup = clearModeRuntimeArtifacts(mode, root);
33214
33607
  let clearedCount = 0;
33215
33608
  const errors = [];
33609
+ if (mode === "team") {
33610
+ collectTeamNamesForCleanup(getStateFilePath(root, "team"));
33611
+ }
33216
33612
  if (MODE_CONFIGS[mode]) {
33217
- const legacyStatePath = getStateFilePath(root, mode);
33218
- if ((0, import_fs12.existsSync)(legacyStatePath)) {
33613
+ const primaryLegacyStatePath = getStateFilePath(root, mode);
33614
+ if ((0, import_fs13.existsSync)(primaryLegacyStatePath)) {
33219
33615
  if (clearModeState(mode, root)) {
33220
33616
  clearedCount++;
33221
33617
  } else {
33222
33618
  errors.push("legacy path");
33223
33619
  }
33224
33620
  }
33225
- } else {
33226
- const statePath = getStatePath(mode, root);
33227
- if ((0, import_fs12.existsSync)(statePath)) {
33228
- try {
33229
- (0, import_fs12.unlinkSync)(statePath);
33230
- clearedCount++;
33231
- } catch {
33232
- errors.push("legacy path");
33233
- }
33234
- }
33621
+ }
33622
+ const extraLegacyCleanup = clearLegacyStateCandidates(mode, root);
33623
+ clearedCount += extraLegacyCleanup.cleared;
33624
+ if (extraLegacyCleanup.hadFailure) {
33625
+ errors.push("legacy path");
33626
+ }
33627
+ clearedCount += runtimeCleanup.cleared;
33628
+ if (runtimeCleanup.hadFailure) {
33629
+ errors.push("runtime artifacts");
33235
33630
  }
33236
33631
  const sessionIds = listSessionIds(root);
33237
33632
  for (const sid of sessionIds) {
33633
+ if (mode === "team") {
33634
+ collectTeamNamesForCleanup(resolveSessionStatePath("team", sid, root));
33635
+ }
33238
33636
  if (MODE_CONFIGS[mode]) {
33239
33637
  const sessionStatePath = getStateFilePath(root, mode, sid);
33240
- if ((0, import_fs12.existsSync)(sessionStatePath)) {
33638
+ if ((0, import_fs13.existsSync)(sessionStatePath)) {
33241
33639
  if (clearModeState(mode, root, sid)) {
33242
33640
  clearedCount++;
33243
33641
  } else {
@@ -33246,9 +33644,9 @@ var stateClearTool = {
33246
33644
  }
33247
33645
  } else {
33248
33646
  const statePath = resolveSessionStatePath(mode, sid, root);
33249
- if ((0, import_fs12.existsSync)(statePath)) {
33647
+ if ((0, import_fs13.existsSync)(statePath)) {
33250
33648
  try {
33251
- (0, import_fs12.unlinkSync)(statePath);
33649
+ (0, import_fs13.unlinkSync)(statePath);
33252
33650
  clearedCount++;
33253
33651
  } catch {
33254
33652
  errors.push(`session: ${sid}`);
@@ -33256,7 +33654,15 @@ var stateClearTool = {
33256
33654
  }
33257
33655
  }
33258
33656
  }
33259
- if (clearedCount === 0 && errors.length === 0) {
33657
+ let removedTeamRoots = 0;
33658
+ let prunedMissionEntries = 0;
33659
+ if (mode === "team") {
33660
+ const teamNames = [...cleanedTeamNames];
33661
+ const removeSelector = teamNames.length > 0 ? teamNames : void 0;
33662
+ removedTeamRoots = cleanupTeamRuntimeState(root, removeSelector);
33663
+ prunedMissionEntries = pruneMissionBoardTeams(root, removeSelector);
33664
+ }
33665
+ if (clearedCount === 0 && errors.length === 0 && removedTeamRoots === 0 && prunedMissionEntries === 0) {
33260
33666
  return {
33261
33667
  content: [{
33262
33668
  type: "text",
@@ -33270,6 +33676,16 @@ var stateClearTool = {
33270
33676
  message += `
33271
33677
  - Errors: ${errors.join(", ")}`;
33272
33678
  }
33679
+ if (mode === "team") {
33680
+ if (removedTeamRoots > 0) {
33681
+ message += `
33682
+ - Team runtime roots removed: ${removedTeamRoots}`;
33683
+ }
33684
+ if (prunedMissionEntries > 0) {
33685
+ message += `
33686
+ - HUD mission entries pruned: ${prunedMissionEntries}`;
33687
+ }
33688
+ }
33273
33689
  message += "\nWARNING: No session_id provided. Cleared legacy plus all session-scoped state; this is a broad operation that may affect other sessions.";
33274
33690
  return {
33275
33691
  content: [{
@@ -33307,8 +33723,8 @@ var stateListActiveTool = {
33307
33723
  for (const mode of EXTRA_STATE_ONLY_MODES) {
33308
33724
  try {
33309
33725
  const statePath = resolveSessionStatePath(mode, sessionId, root);
33310
- if ((0, import_fs12.existsSync)(statePath)) {
33311
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33726
+ if ((0, import_fs13.existsSync)(statePath)) {
33727
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33312
33728
  const state = JSON.parse(content);
33313
33729
  if (state.active) {
33314
33730
  activeModes.push(mode);
@@ -33341,9 +33757,9 @@ ${modeList}`
33341
33757
  const legacyActiveModes = [...getActiveModes(root)];
33342
33758
  for (const mode of EXTRA_STATE_ONLY_MODES) {
33343
33759
  const statePath = getStatePath(mode, root);
33344
- if ((0, import_fs12.existsSync)(statePath)) {
33760
+ if ((0, import_fs13.existsSync)(statePath)) {
33345
33761
  try {
33346
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33762
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33347
33763
  const state = JSON.parse(content);
33348
33764
  if (state.active) {
33349
33765
  legacyActiveModes.push(mode);
@@ -33364,8 +33780,8 @@ ${modeList}`
33364
33780
  for (const mode of EXTRA_STATE_ONLY_MODES) {
33365
33781
  try {
33366
33782
  const statePath = resolveSessionStatePath(mode, sid, root);
33367
- if ((0, import_fs12.existsSync)(statePath)) {
33368
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33783
+ if ((0, import_fs13.existsSync)(statePath)) {
33784
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33369
33785
  const state = JSON.parse(content);
33370
33786
  if (state.active) {
33371
33787
  sessionActiveModes.push(mode);
@@ -33421,7 +33837,8 @@ var stateGetStatusTool = {
33421
33837
  session_id: external_exports3.string().optional().describe("Session ID for session-scoped state isolation. When provided, the tool operates only within that session. When omitted, the tool aggregates legacy state plus all session-scoped state (may include other sessions).")
33422
33838
  },
33423
33839
  handler: async (args) => {
33424
- const { mode, workingDirectory, session_id } = args;
33840
+ const { workingDirectory, session_id } = args;
33841
+ const mode = args.mode;
33425
33842
  try {
33426
33843
  const root = validateWorkingDirectory(workingDirectory);
33427
33844
  const sessionId = session_id;
@@ -33431,9 +33848,9 @@ var stateGetStatusTool = {
33431
33848
  if (sessionId) {
33432
33849
  validateSessionId(sessionId);
33433
33850
  const statePath = MODE_CONFIGS[mode] ? getStateFilePath(root, mode, sessionId) : resolveSessionStatePath(mode, sessionId, root);
33434
- const active = MODE_CONFIGS[mode] ? isModeActive(mode, root, sessionId) : (0, import_fs12.existsSync)(statePath) && (() => {
33851
+ const active = MODE_CONFIGS[mode] ? isModeActive(mode, root, sessionId) : (0, import_fs13.existsSync)(statePath) && (() => {
33435
33852
  try {
33436
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33853
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33437
33854
  const state = JSON.parse(content);
33438
33855
  return state.active === true;
33439
33856
  } catch {
@@ -33441,9 +33858,9 @@ var stateGetStatusTool = {
33441
33858
  }
33442
33859
  })();
33443
33860
  let statePreview = "No state file";
33444
- if ((0, import_fs12.existsSync)(statePath)) {
33861
+ if ((0, import_fs13.existsSync)(statePath)) {
33445
33862
  try {
33446
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33863
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33447
33864
  const state = JSON.parse(content);
33448
33865
  statePreview = JSON.stringify(state, null, 2).slice(0, 500);
33449
33866
  if (statePreview.length >= 500) statePreview += "\n...(truncated)";
@@ -33454,7 +33871,7 @@ var stateGetStatusTool = {
33454
33871
  lines2.push(`### Session: ${sessionId}`);
33455
33872
  lines2.push(`- **Active:** ${active ? "Yes" : "No"}`);
33456
33873
  lines2.push(`- **State Path:** ${statePath}`);
33457
- lines2.push(`- **Exists:** ${(0, import_fs12.existsSync)(statePath) ? "Yes" : "No"}`);
33874
+ lines2.push(`- **Exists:** ${(0, import_fs13.existsSync)(statePath) ? "Yes" : "No"}`);
33458
33875
  lines2.push(`
33459
33876
  ### State Preview
33460
33877
  \`\`\`json
@@ -33468,9 +33885,9 @@ ${statePreview}
33468
33885
  };
33469
33886
  }
33470
33887
  const legacyPath = getStatePath(mode, root);
33471
- const legacyActive = MODE_CONFIGS[mode] ? isModeActive(mode, root) : (0, import_fs12.existsSync)(legacyPath) && (() => {
33888
+ const legacyActive = MODE_CONFIGS[mode] ? isModeActive(mode, root) : (0, import_fs13.existsSync)(legacyPath) && (() => {
33472
33889
  try {
33473
- const content = (0, import_fs12.readFileSync)(legacyPath, "utf-8");
33890
+ const content = (0, import_fs13.readFileSync)(legacyPath, "utf-8");
33474
33891
  const state = JSON.parse(content);
33475
33892
  return state.active === true;
33476
33893
  } catch {
@@ -33480,13 +33897,13 @@ ${statePreview}
33480
33897
  lines2.push(`### Legacy Path`);
33481
33898
  lines2.push(`- **Active:** ${legacyActive ? "Yes" : "No"}`);
33482
33899
  lines2.push(`- **State Path:** ${legacyPath}`);
33483
- lines2.push(`- **Exists:** ${(0, import_fs12.existsSync)(legacyPath) ? "Yes" : "No"}
33900
+ lines2.push(`- **Exists:** ${(0, import_fs13.existsSync)(legacyPath) ? "Yes" : "No"}
33484
33901
  `);
33485
33902
  const activeSessions = MODE_CONFIGS[mode] ? getActiveSessionsForMode(mode, root) : listSessionIds(root).filter((sid) => {
33486
33903
  try {
33487
33904
  const sessionPath = resolveSessionStatePath(mode, sid, root);
33488
- if ((0, import_fs12.existsSync)(sessionPath)) {
33489
- const content = (0, import_fs12.readFileSync)(sessionPath, "utf-8");
33905
+ if ((0, import_fs13.existsSync)(sessionPath)) {
33906
+ const content = (0, import_fs13.readFileSync)(sessionPath, "utf-8");
33490
33907
  const state = JSON.parse(content);
33491
33908
  return state.active === true;
33492
33909
  }
@@ -33528,9 +33945,9 @@ No active sessions for this mode.`);
33528
33945
  for (const mode2 of EXTRA_STATE_ONLY_MODES) {
33529
33946
  const statePath = sessionId ? resolveSessionStatePath(mode2, sessionId, root) : getStatePath(mode2, root);
33530
33947
  let active = false;
33531
- if ((0, import_fs12.existsSync)(statePath)) {
33948
+ if ((0, import_fs13.existsSync)(statePath)) {
33532
33949
  try {
33533
- const content = (0, import_fs12.readFileSync)(statePath, "utf-8");
33950
+ const content = (0, import_fs13.readFileSync)(statePath, "utf-8");
33534
33951
  const state = JSON.parse(content);
33535
33952
  active = state.active === true;
33536
33953
  } catch {
@@ -33566,21 +33983,21 @@ var stateTools = [
33566
33983
  ];
33567
33984
 
33568
33985
  // src/hooks/notepad/index.ts
33569
- var import_fs14 = require("fs");
33570
- var import_path14 = require("path");
33986
+ var import_fs15 = require("fs");
33987
+ var import_path16 = require("path");
33571
33988
 
33572
33989
  // src/lib/file-lock.ts
33573
- var import_fs13 = require("fs");
33990
+ var import_fs14 = require("fs");
33574
33991
  var path6 = __toESM(require("path"), 1);
33575
33992
  var DEFAULT_STALE_LOCK_MS = 3e4;
33576
33993
  var DEFAULT_RETRY_DELAY_MS = 50;
33577
33994
  function isLockStale(lockPath, staleLockMs) {
33578
33995
  try {
33579
- const stat = (0, import_fs13.statSync)(lockPath);
33996
+ const stat = (0, import_fs14.statSync)(lockPath);
33580
33997
  const ageMs = Date.now() - stat.mtimeMs;
33581
33998
  if (ageMs < staleLockMs) return false;
33582
33999
  try {
33583
- const raw = (0, import_fs13.readFileSync)(lockPath, "utf-8");
34000
+ const raw = (0, import_fs14.readFileSync)(lockPath, "utf-8");
33584
34001
  const payload = JSON.parse(raw);
33585
34002
  if (payload.pid && isProcessAlive(payload.pid)) return false;
33586
34003
  } catch {
@@ -33596,21 +34013,21 @@ function lockPathFor(filePath) {
33596
34013
  function tryAcquireSync(lockPath, staleLockMs) {
33597
34014
  ensureDirSync(path6.dirname(lockPath));
33598
34015
  try {
33599
- const fd = (0, import_fs13.openSync)(
34016
+ const fd = (0, import_fs14.openSync)(
33600
34017
  lockPath,
33601
- import_fs13.constants.O_CREAT | import_fs13.constants.O_EXCL | import_fs13.constants.O_WRONLY,
34018
+ import_fs14.constants.O_CREAT | import_fs14.constants.O_EXCL | import_fs14.constants.O_WRONLY,
33602
34019
  384
33603
34020
  );
33604
34021
  try {
33605
34022
  const payload = JSON.stringify({ pid: process.pid, timestamp: Date.now() });
33606
- (0, import_fs13.writeSync)(fd, payload, null, "utf-8");
34023
+ (0, import_fs14.writeSync)(fd, payload, null, "utf-8");
33607
34024
  } catch (writeErr) {
33608
34025
  try {
33609
- (0, import_fs13.closeSync)(fd);
34026
+ (0, import_fs14.closeSync)(fd);
33610
34027
  } catch {
33611
34028
  }
33612
34029
  try {
33613
- (0, import_fs13.unlinkSync)(lockPath);
34030
+ (0, import_fs14.unlinkSync)(lockPath);
33614
34031
  } catch {
33615
34032
  }
33616
34033
  throw writeErr;
@@ -33620,25 +34037,25 @@ function tryAcquireSync(lockPath, staleLockMs) {
33620
34037
  if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
33621
34038
  if (isLockStale(lockPath, staleLockMs)) {
33622
34039
  try {
33623
- (0, import_fs13.unlinkSync)(lockPath);
34040
+ (0, import_fs14.unlinkSync)(lockPath);
33624
34041
  } catch {
33625
34042
  }
33626
34043
  try {
33627
- const fd = (0, import_fs13.openSync)(
34044
+ const fd = (0, import_fs14.openSync)(
33628
34045
  lockPath,
33629
- import_fs13.constants.O_CREAT | import_fs13.constants.O_EXCL | import_fs13.constants.O_WRONLY,
34046
+ import_fs14.constants.O_CREAT | import_fs14.constants.O_EXCL | import_fs14.constants.O_WRONLY,
33630
34047
  384
33631
34048
  );
33632
34049
  try {
33633
34050
  const payload = JSON.stringify({ pid: process.pid, timestamp: Date.now() });
33634
- (0, import_fs13.writeSync)(fd, payload, null, "utf-8");
34051
+ (0, import_fs14.writeSync)(fd, payload, null, "utf-8");
33635
34052
  } catch (writeErr) {
33636
34053
  try {
33637
- (0, import_fs13.closeSync)(fd);
34054
+ (0, import_fs14.closeSync)(fd);
33638
34055
  } catch {
33639
34056
  }
33640
34057
  try {
33641
- (0, import_fs13.unlinkSync)(lockPath);
34058
+ (0, import_fs14.unlinkSync)(lockPath);
33642
34059
  } catch {
33643
34060
  }
33644
34061
  throw writeErr;
@@ -33678,11 +34095,11 @@ function acquireFileLockSync(lockPath, opts) {
33678
34095
  }
33679
34096
  function releaseFileLockSync(handle) {
33680
34097
  try {
33681
- (0, import_fs13.closeSync)(handle.fd);
34098
+ (0, import_fs14.closeSync)(handle.fd);
33682
34099
  } catch {
33683
34100
  }
33684
34101
  try {
33685
- (0, import_fs13.unlinkSync)(handle.path);
34102
+ (0, import_fs14.unlinkSync)(handle.path);
33686
34103
  } catch {
33687
34104
  }
33688
34105
  }
@@ -33756,19 +34173,19 @@ function getSectionRegexSet(header) {
33756
34173
  return SECTION_REGEXES[header] ?? createSectionRegexSet(header);
33757
34174
  }
33758
34175
  function getNotepadPath(directory) {
33759
- return (0, import_path14.join)(getSharedOmcRoot(directory), NOTEPAD_FILENAME);
34176
+ return (0, import_path16.join)(getSharedOmcRoot(directory), NOTEPAD_FILENAME);
33760
34177
  }
33761
34178
  function initNotepad(directory) {
33762
34179
  const omcDir = getSharedOmcRoot(directory);
33763
- if (!(0, import_fs14.existsSync)(omcDir)) {
34180
+ if (!(0, import_fs15.existsSync)(omcDir)) {
33764
34181
  try {
33765
- (0, import_fs14.mkdirSync)(omcDir, { recursive: true });
34182
+ (0, import_fs15.mkdirSync)(omcDir, { recursive: true });
33766
34183
  } catch {
33767
34184
  return false;
33768
34185
  }
33769
34186
  }
33770
34187
  const notepadPath = getNotepadPath(directory);
33771
- if ((0, import_fs14.existsSync)(notepadPath)) {
34188
+ if ((0, import_fs15.existsSync)(notepadPath)) {
33772
34189
  return true;
33773
34190
  }
33774
34191
  const content = `# Notepad
@@ -33793,11 +34210,11 @@ ${MANUAL_HEADER}
33793
34210
  }
33794
34211
  function readNotepad(directory) {
33795
34212
  const notepadPath = getNotepadPath(directory);
33796
- if (!(0, import_fs14.existsSync)(notepadPath)) {
34213
+ if (!(0, import_fs15.existsSync)(notepadPath)) {
33797
34214
  return null;
33798
34215
  }
33799
34216
  try {
33800
- return (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34217
+ return (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33801
34218
  } catch {
33802
34219
  return null;
33803
34220
  }
@@ -33841,7 +34258,7 @@ function getManualSection(directory) {
33841
34258
  return extractSection(content, MANUAL_HEADER);
33842
34259
  }
33843
34260
  function setPriorityContext(directory, content, config2 = DEFAULT_CONFIG) {
33844
- if (!(0, import_fs14.existsSync)(getNotepadPath(directory))) {
34261
+ if (!(0, import_fs15.existsSync)(getNotepadPath(directory))) {
33845
34262
  if (!initNotepad(directory)) {
33846
34263
  return { success: false };
33847
34264
  }
@@ -33849,7 +34266,7 @@ function setPriorityContext(directory, content, config2 = DEFAULT_CONFIG) {
33849
34266
  const notepadPath = getNotepadPath(directory);
33850
34267
  try {
33851
34268
  return withFileLockSync(lockPathFor(notepadPath), () => {
33852
- let notepadContent = (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34269
+ let notepadContent = (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33853
34270
  const warning = content.length > config2.priorityMaxChars ? `Priority Context exceeds ${config2.priorityMaxChars} chars (${content.length} chars). Consider condensing.` : void 0;
33854
34271
  notepadContent = replaceSection(notepadContent, PRIORITY_HEADER, content);
33855
34272
  atomicWriteFileSync(notepadPath, notepadContent);
@@ -33860,7 +34277,7 @@ function setPriorityContext(directory, content, config2 = DEFAULT_CONFIG) {
33860
34277
  }
33861
34278
  }
33862
34279
  function addWorkingMemoryEntry(directory, content) {
33863
- if (!(0, import_fs14.existsSync)(getNotepadPath(directory))) {
34280
+ if (!(0, import_fs15.existsSync)(getNotepadPath(directory))) {
33864
34281
  if (!initNotepad(directory)) {
33865
34282
  return false;
33866
34283
  }
@@ -33868,7 +34285,7 @@ function addWorkingMemoryEntry(directory, content) {
33868
34285
  const notepadPath = getNotepadPath(directory);
33869
34286
  try {
33870
34287
  return withFileLockSync(lockPathFor(notepadPath), () => {
33871
- let notepadContent = (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34288
+ let notepadContent = (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33872
34289
  const currentMemory = extractSection(notepadContent, WORKING_MEMORY_HEADER) || "";
33873
34290
  const now = /* @__PURE__ */ new Date();
33874
34291
  const timestamp = now.toISOString().slice(0, 16).replace("T", " ");
@@ -33889,7 +34306,7 @@ ${content}
33889
34306
  }
33890
34307
  }
33891
34308
  function addManualEntry(directory, content) {
33892
- if (!(0, import_fs14.existsSync)(getNotepadPath(directory))) {
34309
+ if (!(0, import_fs15.existsSync)(getNotepadPath(directory))) {
33893
34310
  if (!initNotepad(directory)) {
33894
34311
  return false;
33895
34312
  }
@@ -33897,7 +34314,7 @@ function addManualEntry(directory, content) {
33897
34314
  const notepadPath = getNotepadPath(directory);
33898
34315
  try {
33899
34316
  return withFileLockSync(lockPathFor(notepadPath), () => {
33900
- let notepadContent = (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34317
+ let notepadContent = (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33901
34318
  const currentManual = extractSection(notepadContent, MANUAL_HEADER) || "";
33902
34319
  const now = /* @__PURE__ */ new Date();
33903
34320
  const timestamp = now.toISOString().slice(0, 16).replace("T", " ");
@@ -33915,12 +34332,12 @@ ${content}
33915
34332
  }
33916
34333
  function pruneOldEntries(directory, daysOld = DEFAULT_CONFIG.workingMemoryDays) {
33917
34334
  const notepadPath = getNotepadPath(directory);
33918
- if (!(0, import_fs14.existsSync)(notepadPath)) {
34335
+ if (!(0, import_fs15.existsSync)(notepadPath)) {
33919
34336
  return { pruned: 0, remaining: 0 };
33920
34337
  }
33921
34338
  try {
33922
34339
  return withFileLockSync(lockPathFor(notepadPath), () => {
33923
- let notepadContent = (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34340
+ let notepadContent = (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33924
34341
  const workingMemory = extractSection(notepadContent, WORKING_MEMORY_HEADER);
33925
34342
  if (!workingMemory) {
33926
34343
  return { pruned: 0, remaining: 0 };
@@ -33958,7 +34375,7 @@ ${entry.content}`).join("\n\n");
33958
34375
  }
33959
34376
  function getNotepadStats(directory) {
33960
34377
  const notepadPath = getNotepadPath(directory);
33961
- if (!(0, import_fs14.existsSync)(notepadPath)) {
34378
+ if (!(0, import_fs15.existsSync)(notepadPath)) {
33962
34379
  return {
33963
34380
  exists: false,
33964
34381
  totalSize: 0,
@@ -33967,7 +34384,7 @@ function getNotepadStats(directory) {
33967
34384
  oldestEntry: null
33968
34385
  };
33969
34386
  }
33970
- const content = (0, import_fs14.readFileSync)(notepadPath, "utf-8");
34387
+ const content = (0, import_fs15.readFileSync)(notepadPath, "utf-8");
33971
34388
  const priorityContext = extractSection(content, PRIORITY_HEADER) || "";
33972
34389
  const workingMemory = extractSection(content, WORKING_MEMORY_HEADER) || "";
33973
34390
  const wmMatches = workingMemory.match(
@@ -34286,7 +34703,7 @@ var notepadTools = [
34286
34703
  ];
34287
34704
 
34288
34705
  // src/hooks/project-memory/index.ts
34289
- var import_path22 = __toESM(require("path"), 1);
34706
+ var import_path24 = __toESM(require("path"), 1);
34290
34707
 
34291
34708
  // src/features/context-injector/collector.ts
34292
34709
  var PRIORITY_ORDER = {
@@ -34396,18 +34813,18 @@ var ContextCollector = class {
34396
34813
  var contextCollector = new ContextCollector();
34397
34814
 
34398
34815
  // src/hooks/rules-injector/finder.ts
34399
- var import_fs15 = require("fs");
34400
- var import_path16 = require("path");
34816
+ var import_fs16 = require("fs");
34817
+ var import_path18 = require("path");
34401
34818
 
34402
34819
  // src/hooks/rules-injector/constants.ts
34403
- var import_path15 = require("path");
34820
+ var import_path17 = require("path");
34404
34821
  var import_os4 = require("os");
34405
- var OMC_STORAGE_DIR = (0, import_path15.join)((0, import_os4.homedir)(), ".omcp");
34406
- var RULES_INJECTOR_STORAGE = (0, import_path15.join)(OMC_STORAGE_DIR, "rules-injector");
34822
+ var OMC_STORAGE_DIR = (0, import_path17.join)((0, import_os4.homedir)(), ".omcp");
34823
+ var RULES_INJECTOR_STORAGE = (0, import_path17.join)(OMC_STORAGE_DIR, "rules-injector");
34407
34824
 
34408
34825
  // src/hooks/project-memory/storage.ts
34409
34826
  var import_promises = __toESM(require("fs/promises"), 1);
34410
- var import_path17 = __toESM(require("path"), 1);
34827
+ var import_path19 = __toESM(require("path"), 1);
34411
34828
 
34412
34829
  // src/hooks/project-memory/constants.ts
34413
34830
  var CACHE_EXPIRY_MS = 24 * 60 * 60 * 1e3;
@@ -34431,7 +34848,7 @@ async function loadProjectMemory(projectRoot) {
34431
34848
  }
34432
34849
  async function saveProjectMemory(projectRoot, memory) {
34433
34850
  const memoryPath = getMemoryPath(projectRoot);
34434
- const omcDir = import_path17.default.dirname(memoryPath);
34851
+ const omcDir = import_path19.default.dirname(memoryPath);
34435
34852
  try {
34436
34853
  await import_promises.default.mkdir(omcDir, { recursive: true });
34437
34854
  await atomicWriteJson(memoryPath, memory);
@@ -34447,17 +34864,17 @@ async function withProjectMemoryLock(projectRoot, fn) {
34447
34864
 
34448
34865
  // src/hooks/project-memory/detector.ts
34449
34866
  var import_promises3 = __toESM(require("fs/promises"), 1);
34450
- var import_path19 = __toESM(require("path"), 1);
34867
+ var import_path21 = __toESM(require("path"), 1);
34451
34868
 
34452
34869
  // src/hooks/project-memory/directory-mapper.ts
34453
34870
  var import_promises2 = __toESM(require("fs/promises"), 1);
34454
- var import_path18 = __toESM(require("path"), 1);
34871
+ var import_path20 = __toESM(require("path"), 1);
34455
34872
 
34456
34873
  // src/hooks/project-memory/formatter.ts
34457
- var import_path21 = __toESM(require("path"), 1);
34874
+ var import_path23 = __toESM(require("path"), 1);
34458
34875
 
34459
34876
  // src/hooks/project-memory/hot-path-tracker.ts
34460
- var import_path20 = __toESM(require("path"), 1);
34877
+ var import_path22 = __toESM(require("path"), 1);
34461
34878
 
34462
34879
  // src/hooks/project-memory/directive-detector.ts
34463
34880
  function addDirective(directives, newDirective) {
@@ -34842,27 +35259,27 @@ var memoryTools = [
34842
35259
  ];
34843
35260
 
34844
35261
  // src/tools/trace-tools.ts
34845
- var import_fs17 = require("fs");
34846
- var import_path24 = require("path");
35262
+ var import_fs18 = require("fs");
35263
+ var import_path26 = require("path");
34847
35264
 
34848
35265
  // src/hooks/subagent-tracker/session-replay.ts
34849
- var import_fs16 = require("fs");
34850
- var import_path23 = require("path");
35266
+ var import_fs17 = require("fs");
35267
+ var import_path25 = require("path");
34851
35268
  var REPLAY_PREFIX = "agent-replay-";
34852
35269
  var MAX_REPLAY_SIZE_BYTES = 5 * 1024 * 1024;
34853
35270
  function getReplayFilePath(directory, sessionId) {
34854
- const stateDir = (0, import_path23.join)(getOmcRoot(directory), "state");
34855
- if (!(0, import_fs16.existsSync)(stateDir)) {
34856
- (0, import_fs16.mkdirSync)(stateDir, { recursive: true });
35271
+ const stateDir = (0, import_path25.join)(getOmcRoot(directory), "state");
35272
+ if (!(0, import_fs17.existsSync)(stateDir)) {
35273
+ (0, import_fs17.mkdirSync)(stateDir, { recursive: true });
34857
35274
  }
34858
35275
  const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
34859
- return (0, import_path23.join)(stateDir, `${REPLAY_PREFIX}${safeId}.jsonl`);
35276
+ return (0, import_path25.join)(stateDir, `${REPLAY_PREFIX}${safeId}.jsonl`);
34860
35277
  }
34861
35278
  function readReplayEvents(directory, sessionId) {
34862
35279
  const filePath = getReplayFilePath(directory, sessionId);
34863
- if (!(0, import_fs16.existsSync)(filePath)) return [];
35280
+ if (!(0, import_fs17.existsSync)(filePath)) return [];
34864
35281
  try {
34865
- const content = (0, import_fs16.readFileSync)(filePath, "utf-8");
35282
+ const content = (0, import_fs17.readFileSync)(filePath, "utf-8");
34866
35283
  return content.split("\n").filter((line) => line.trim()).map((line) => {
34867
35284
  try {
34868
35285
  return JSON.parse(line);
@@ -35035,12 +35452,12 @@ function getReplaySummary(directory, sessionId) {
35035
35452
  // src/tools/trace-tools.ts
35036
35453
  var REPLAY_PREFIX2 = "agent-replay-";
35037
35454
  function findLatestSessionId(directory) {
35038
- const stateDir = (0, import_path24.join)(directory, ".omcp", "state");
35455
+ const stateDir = (0, import_path26.join)(directory, ".omcp", "state");
35039
35456
  try {
35040
- const files = (0, import_fs17.readdirSync)(stateDir).filter((f) => f.startsWith(REPLAY_PREFIX2) && f.endsWith(".jsonl")).map((f) => ({
35457
+ const files = (0, import_fs18.readdirSync)(stateDir).filter((f) => f.startsWith(REPLAY_PREFIX2) && f.endsWith(".jsonl")).map((f) => ({
35041
35458
  name: f,
35042
35459
  sessionId: f.slice(REPLAY_PREFIX2.length, -".jsonl".length),
35043
- mtime: (0, import_fs17.statSync)((0, import_path24.join)(stateDir, f)).mtimeMs
35460
+ mtime: (0, import_fs18.statSync)((0, import_path26.join)(stateDir, f)).mtimeMs
35044
35461
  })).sort((a, b) => b.mtime - a.mtime);
35045
35462
  return files.length > 0 ? files[0].sessionId : null;
35046
35463
  } catch {
@@ -35384,18 +35801,18 @@ No events recorded.`
35384
35801
  var traceTools = [traceTimelineTool, traceSummaryTool];
35385
35802
 
35386
35803
  // src/lib/shared-memory.ts
35387
- var import_fs18 = require("fs");
35388
- var import_path25 = require("path");
35804
+ var import_fs19 = require("fs");
35805
+ var import_path27 = require("path");
35389
35806
  var CONFIG_FILE_NAME = ".omc-config.json";
35390
35807
  function isSharedMemoryEnabled() {
35391
35808
  try {
35392
- const configPath = (0, import_path25.join)(
35809
+ const configPath = (0, import_path27.join)(
35393
35810
  process.env.HOME || process.env.USERPROFILE || "",
35394
35811
  ".copilot",
35395
35812
  CONFIG_FILE_NAME
35396
35813
  );
35397
- if (!(0, import_fs18.existsSync)(configPath)) return true;
35398
- const raw = JSON.parse((0, import_fs18.readFileSync)(configPath, "utf-8"));
35814
+ if (!(0, import_fs19.existsSync)(configPath)) return true;
35815
+ const raw = JSON.parse((0, import_fs19.readFileSync)(configPath, "utf-8"));
35399
35816
  const enabled = raw?.agents?.sharedMemory?.enabled;
35400
35817
  if (typeof enabled === "boolean") return enabled;
35401
35818
  return true;
@@ -35429,16 +35846,16 @@ function validateKey(key) {
35429
35846
  function getNamespaceDir(namespace, worktreeRoot) {
35430
35847
  validateNamespace(namespace);
35431
35848
  const omcRoot = getOmcRoot(worktreeRoot);
35432
- return (0, import_path25.join)(omcRoot, SHARED_MEMORY_DIR, namespace);
35849
+ return (0, import_path27.join)(omcRoot, SHARED_MEMORY_DIR, namespace);
35433
35850
  }
35434
35851
  function getEntryPath(namespace, key, worktreeRoot) {
35435
35852
  validateKey(key);
35436
- return (0, import_path25.join)(getNamespaceDir(namespace, worktreeRoot), `${key}.json`);
35853
+ return (0, import_path27.join)(getNamespaceDir(namespace, worktreeRoot), `${key}.json`);
35437
35854
  }
35438
35855
  function ensureNamespaceDir(namespace, worktreeRoot) {
35439
35856
  const dir = getNamespaceDir(namespace, worktreeRoot);
35440
- if (!(0, import_fs18.existsSync)(dir)) {
35441
- (0, import_fs18.mkdirSync)(dir, { recursive: true });
35857
+ if (!(0, import_fs19.existsSync)(dir)) {
35858
+ (0, import_fs19.mkdirSync)(dir, { recursive: true });
35442
35859
  }
35443
35860
  return dir;
35444
35861
  }
@@ -35453,9 +35870,9 @@ function writeEntry(namespace, key, value, ttl, worktreeRoot) {
35453
35870
  const lockPath = filePath + ".lock";
35454
35871
  const doWrite = () => {
35455
35872
  let existingCreatedAt = now;
35456
- if ((0, import_fs18.existsSync)(filePath)) {
35873
+ if ((0, import_fs19.existsSync)(filePath)) {
35457
35874
  try {
35458
- const existing = JSON.parse((0, import_fs18.readFileSync)(filePath, "utf-8"));
35875
+ const existing = JSON.parse((0, import_fs19.readFileSync)(filePath, "utf-8"));
35459
35876
  existingCreatedAt = existing.createdAt || now;
35460
35877
  } catch {
35461
35878
  }
@@ -35472,11 +35889,11 @@ function writeEntry(namespace, key, value, ttl, worktreeRoot) {
35472
35889
  entry.expiresAt = new Date(Date.now() + ttl * 1e3).toISOString();
35473
35890
  }
35474
35891
  const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
35475
- (0, import_fs18.writeFileSync)(tmpPath, JSON.stringify(entry, null, 2), "utf-8");
35476
- (0, import_fs18.renameSync)(tmpPath, filePath);
35892
+ (0, import_fs19.writeFileSync)(tmpPath, JSON.stringify(entry, null, 2), "utf-8");
35893
+ (0, import_fs19.renameSync)(tmpPath, filePath);
35477
35894
  try {
35478
35895
  const legacyTmp = filePath + ".tmp";
35479
- if ((0, import_fs18.existsSync)(legacyTmp)) (0, import_fs18.unlinkSync)(legacyTmp);
35896
+ if ((0, import_fs19.existsSync)(legacyTmp)) (0, import_fs19.unlinkSync)(legacyTmp);
35480
35897
  } catch {
35481
35898
  }
35482
35899
  return entry;
@@ -35491,12 +35908,12 @@ function readEntry(namespace, key, worktreeRoot) {
35491
35908
  validateNamespace(namespace);
35492
35909
  validateKey(key);
35493
35910
  const filePath = getEntryPath(namespace, key, worktreeRoot);
35494
- if (!(0, import_fs18.existsSync)(filePath)) return null;
35911
+ if (!(0, import_fs19.existsSync)(filePath)) return null;
35495
35912
  try {
35496
- const entry = JSON.parse((0, import_fs18.readFileSync)(filePath, "utf-8"));
35913
+ const entry = JSON.parse((0, import_fs19.readFileSync)(filePath, "utf-8"));
35497
35914
  if (isExpired(entry)) {
35498
35915
  try {
35499
- (0, import_fs18.unlinkSync)(filePath);
35916
+ (0, import_fs19.unlinkSync)(filePath);
35500
35917
  } catch {
35501
35918
  }
35502
35919
  return null;
@@ -35509,14 +35926,14 @@ function readEntry(namespace, key, worktreeRoot) {
35509
35926
  function listEntries(namespace, worktreeRoot) {
35510
35927
  validateNamespace(namespace);
35511
35928
  const dir = getNamespaceDir(namespace, worktreeRoot);
35512
- if (!(0, import_fs18.existsSync)(dir)) return [];
35929
+ if (!(0, import_fs19.existsSync)(dir)) return [];
35513
35930
  const items = [];
35514
35931
  try {
35515
- const files = (0, import_fs18.readdirSync)(dir).filter((f) => f.endsWith(".json"));
35932
+ const files = (0, import_fs19.readdirSync)(dir).filter((f) => f.endsWith(".json"));
35516
35933
  for (const file2 of files) {
35517
35934
  try {
35518
- const filePath = (0, import_path25.join)(dir, file2);
35519
- const entry = JSON.parse((0, import_fs18.readFileSync)(filePath, "utf-8"));
35935
+ const filePath = (0, import_path27.join)(dir, file2);
35936
+ const entry = JSON.parse((0, import_fs19.readFileSync)(filePath, "utf-8"));
35520
35937
  if (!isExpired(entry)) {
35521
35938
  items.push({
35522
35939
  key: entry.key,
@@ -35535,9 +35952,9 @@ function deleteEntry(namespace, key, worktreeRoot) {
35535
35952
  validateNamespace(namespace);
35536
35953
  validateKey(key);
35537
35954
  const filePath = getEntryPath(namespace, key, worktreeRoot);
35538
- if (!(0, import_fs18.existsSync)(filePath)) return false;
35955
+ if (!(0, import_fs19.existsSync)(filePath)) return false;
35539
35956
  try {
35540
- (0, import_fs18.unlinkSync)(filePath);
35957
+ (0, import_fs19.unlinkSync)(filePath);
35541
35958
  return true;
35542
35959
  } catch {
35543
35960
  return false;
@@ -35545,15 +35962,15 @@ function deleteEntry(namespace, key, worktreeRoot) {
35545
35962
  }
35546
35963
  function cleanupExpired(namespace, worktreeRoot) {
35547
35964
  const omcRoot = getOmcRoot(worktreeRoot);
35548
- const sharedMemDir = (0, import_path25.join)(omcRoot, SHARED_MEMORY_DIR);
35549
- if (!(0, import_fs18.existsSync)(sharedMemDir)) return { removed: 0, namespaces: [] };
35965
+ const sharedMemDir = (0, import_path27.join)(omcRoot, SHARED_MEMORY_DIR);
35966
+ if (!(0, import_fs19.existsSync)(sharedMemDir)) return { removed: 0, namespaces: [] };
35550
35967
  const namespacesToClean = [];
35551
35968
  if (namespace) {
35552
35969
  validateNamespace(namespace);
35553
35970
  namespacesToClean.push(namespace);
35554
35971
  } else {
35555
35972
  try {
35556
- const entries = (0, import_fs18.readdirSync)(sharedMemDir, { withFileTypes: true });
35973
+ const entries = (0, import_fs19.readdirSync)(sharedMemDir, { withFileTypes: true });
35557
35974
  for (const entry of entries) {
35558
35975
  if (entry.isDirectory()) {
35559
35976
  namespacesToClean.push(entry.name);
@@ -35566,17 +35983,17 @@ function cleanupExpired(namespace, worktreeRoot) {
35566
35983
  let removed = 0;
35567
35984
  const cleanedNamespaces = [];
35568
35985
  for (const ns of namespacesToClean) {
35569
- const nsDir = (0, import_path25.join)(sharedMemDir, ns);
35570
- if (!(0, import_fs18.existsSync)(nsDir)) continue;
35986
+ const nsDir = (0, import_path27.join)(sharedMemDir, ns);
35987
+ if (!(0, import_fs19.existsSync)(nsDir)) continue;
35571
35988
  let nsRemoved = 0;
35572
35989
  try {
35573
- const files = (0, import_fs18.readdirSync)(nsDir).filter((f) => f.endsWith(".json"));
35990
+ const files = (0, import_fs19.readdirSync)(nsDir).filter((f) => f.endsWith(".json"));
35574
35991
  for (const file2 of files) {
35575
35992
  try {
35576
- const filePath = (0, import_path25.join)(nsDir, file2);
35577
- const entry = JSON.parse((0, import_fs18.readFileSync)(filePath, "utf-8"));
35993
+ const filePath = (0, import_path27.join)(nsDir, file2);
35994
+ const entry = JSON.parse((0, import_fs19.readFileSync)(filePath, "utf-8"));
35578
35995
  if (isExpired(entry)) {
35579
- (0, import_fs18.unlinkSync)(filePath);
35996
+ (0, import_fs19.unlinkSync)(filePath);
35580
35997
  nsRemoved++;
35581
35998
  }
35582
35999
  } catch {
@@ -35593,10 +36010,10 @@ function cleanupExpired(namespace, worktreeRoot) {
35593
36010
  }
35594
36011
  function listNamespaces(worktreeRoot) {
35595
36012
  const omcRoot = getOmcRoot(worktreeRoot);
35596
- const sharedMemDir = (0, import_path25.join)(omcRoot, SHARED_MEMORY_DIR);
35597
- if (!(0, import_fs18.existsSync)(sharedMemDir)) return [];
36013
+ const sharedMemDir = (0, import_path27.join)(omcRoot, SHARED_MEMORY_DIR);
36014
+ if (!(0, import_fs19.existsSync)(sharedMemDir)) return [];
35598
36015
  try {
35599
- const entries = (0, import_fs18.readdirSync)(sharedMemDir, { withFileTypes: true });
36016
+ const entries = (0, import_fs19.readdirSync)(sharedMemDir, { withFileTypes: true });
35600
36017
  return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
35601
36018
  } catch {
35602
36019
  return [];
@@ -36152,28 +36569,28 @@ var DEFAULT_WIKI_CONFIG = {
36152
36569
  };
36153
36570
 
36154
36571
  // src/hooks/wiki/storage.ts
36155
- var import_fs19 = require("fs");
36156
- var import_path26 = require("path");
36572
+ var import_fs20 = require("fs");
36573
+ var import_path28 = require("path");
36157
36574
  var WIKI_DIR = "wiki";
36158
36575
  var INDEX_FILE = "index.md";
36159
36576
  var LOG_FILE = "log.md";
36160
36577
  var ENVIRONMENT_FILE = "environment.md";
36161
36578
  var RESERVED_FILES = /* @__PURE__ */ new Set([INDEX_FILE, LOG_FILE, ENVIRONMENT_FILE]);
36162
36579
  function getOmcDir(root) {
36163
- return (0, import_path26.join)(root, ".omcp");
36580
+ return (0, import_path28.join)(root, ".omcp");
36164
36581
  }
36165
36582
  function getWikiDir(root) {
36166
- return (0, import_path26.join)(getOmcDir(root), WIKI_DIR);
36583
+ return (0, import_path28.join)(getOmcDir(root), WIKI_DIR);
36167
36584
  }
36168
36585
  function ensureWikiDir(root) {
36169
36586
  const wikiDir = getWikiDir(root);
36170
- if (!(0, import_fs19.existsSync)(wikiDir)) {
36171
- (0, import_fs19.mkdirSync)(wikiDir, { recursive: true });
36587
+ if (!(0, import_fs20.existsSync)(wikiDir)) {
36588
+ (0, import_fs20.mkdirSync)(wikiDir, { recursive: true });
36172
36589
  }
36173
36590
  const omcRoot = getOmcDir(root);
36174
- const gitignorePath = (0, import_path26.join)(omcRoot, ".gitignore");
36175
- if ((0, import_fs19.existsSync)(gitignorePath)) {
36176
- const content = (0, import_fs19.readFileSync)(gitignorePath, "utf-8");
36591
+ const gitignorePath = (0, import_path28.join)(omcRoot, ".gitignore");
36592
+ if ((0, import_fs20.existsSync)(gitignorePath)) {
36593
+ const content = (0, import_fs20.readFileSync)(gitignorePath, "utf-8");
36177
36594
  if (!content.includes("wiki/")) {
36178
36595
  atomicWriteFileSync(gitignorePath, content.trimEnd() + "\nwiki/\n");
36179
36596
  }
@@ -36184,7 +36601,7 @@ function ensureWikiDir(root) {
36184
36601
  }
36185
36602
  function withWikiLock(root, fn) {
36186
36603
  const wikiDir = ensureWikiDir(root);
36187
- const lockPath = lockPathFor((0, import_path26.join)(wikiDir, ".wiki-lock"));
36604
+ const lockPath = lockPathFor((0, import_path28.join)(wikiDir, ".wiki-lock"));
36188
36605
  return withFileLockSync(lockPath, fn, { timeoutMs: 5e3, retryDelayMs: 50 });
36189
36606
  }
36190
36607
  function parseFrontmatter(raw) {
@@ -36266,9 +36683,9 @@ function safeWikiPath(wikiDir, filename) {
36266
36683
  if (filename.includes("/") || filename.includes("\\") || filename.includes("..")) {
36267
36684
  return null;
36268
36685
  }
36269
- const filePath = (0, import_path26.join)(wikiDir, filename);
36270
- const resolved = (0, import_path26.resolve)(filePath);
36271
- if (!resolved.startsWith((0, import_path26.resolve)(wikiDir) + import_path26.sep)) {
36686
+ const filePath = (0, import_path28.join)(wikiDir, filename);
36687
+ const resolved = (0, import_path28.resolve)(filePath);
36688
+ if (!resolved.startsWith((0, import_path28.resolve)(wikiDir) + import_path28.sep)) {
36272
36689
  return null;
36273
36690
  }
36274
36691
  return filePath;
@@ -36277,9 +36694,9 @@ function readPage(root, filename) {
36277
36694
  const wikiDir = getWikiDir(root);
36278
36695
  const filePath = safeWikiPath(wikiDir, filename);
36279
36696
  if (!filePath) return null;
36280
- if (!(0, import_fs19.existsSync)(filePath)) return null;
36697
+ if (!(0, import_fs20.existsSync)(filePath)) return null;
36281
36698
  try {
36282
- const raw = (0, import_fs19.readFileSync)(filePath, "utf-8");
36699
+ const raw = (0, import_fs20.readFileSync)(filePath, "utf-8");
36283
36700
  const parsed = parseFrontmatter(raw);
36284
36701
  if (!parsed) return null;
36285
36702
  return {
@@ -36293,16 +36710,16 @@ function readPage(root, filename) {
36293
36710
  }
36294
36711
  function listPages(root) {
36295
36712
  const wikiDir = getWikiDir(root);
36296
- if (!(0, import_fs19.existsSync)(wikiDir)) return [];
36297
- return (0, import_fs19.readdirSync)(wikiDir).filter((f) => f.endsWith(".md") && !RESERVED_FILES.has(f)).sort();
36713
+ if (!(0, import_fs20.existsSync)(wikiDir)) return [];
36714
+ return (0, import_fs20.readdirSync)(wikiDir).filter((f) => f.endsWith(".md") && !RESERVED_FILES.has(f)).sort();
36298
36715
  }
36299
36716
  function readAllPages(root) {
36300
36717
  return listPages(root).map((f) => readPage(root, f)).filter((p) => p !== null);
36301
36718
  }
36302
36719
  function readIndex(root) {
36303
- const indexPath = (0, import_path26.join)(getWikiDir(root), INDEX_FILE);
36304
- if (!(0, import_fs19.existsSync)(indexPath)) return null;
36305
- return (0, import_fs19.readFileSync)(indexPath, "utf-8");
36720
+ const indexPath = (0, import_path28.join)(getWikiDir(root), INDEX_FILE);
36721
+ if (!(0, import_fs20.existsSync)(indexPath)) return null;
36722
+ return (0, import_fs20.readFileSync)(indexPath, "utf-8");
36306
36723
  }
36307
36724
  function writePageUnsafe(root, page) {
36308
36725
  if (RESERVED_FILES.has(page.filename)) {
@@ -36317,8 +36734,8 @@ function deletePageUnsafe(root, filename) {
36317
36734
  const wikiDir = getWikiDir(root);
36318
36735
  const filePath = safeWikiPath(wikiDir, filename);
36319
36736
  if (!filePath) return false;
36320
- if (!(0, import_fs19.existsSync)(filePath)) return false;
36321
- (0, import_fs19.unlinkSync)(filePath);
36737
+ if (!(0, import_fs20.existsSync)(filePath)) return false;
36738
+ (0, import_fs20.unlinkSync)(filePath);
36322
36739
  return true;
36323
36740
  }
36324
36741
  function updateIndexUnsafe(root) {
@@ -36347,19 +36764,19 @@ function updateIndexUnsafe(root) {
36347
36764
  lines.push("");
36348
36765
  }
36349
36766
  const wikiDir = ensureWikiDir(root);
36350
- atomicWriteFileSync((0, import_path26.join)(wikiDir, INDEX_FILE), lines.join("\n"));
36767
+ atomicWriteFileSync((0, import_path28.join)(wikiDir, INDEX_FILE), lines.join("\n"));
36351
36768
  }
36352
36769
  function appendLogUnsafe(root, entry) {
36353
36770
  const wikiDir = ensureWikiDir(root);
36354
- const logPath = (0, import_path26.join)(wikiDir, LOG_FILE);
36771
+ const logPath = (0, import_path28.join)(wikiDir, LOG_FILE);
36355
36772
  const logLine = `## [${entry.timestamp}] ${entry.operation}
36356
36773
  - **Pages:** ${entry.pagesAffected.join(", ") || "none"}
36357
36774
  - **Summary:** ${entry.summary}
36358
36775
 
36359
36776
  `;
36360
36777
  let existing = "";
36361
- if ((0, import_fs19.existsSync)(logPath)) {
36362
- existing = (0, import_fs19.readFileSync)(logPath, "utf-8");
36778
+ if ((0, import_fs20.existsSync)(logPath)) {
36779
+ existing = (0, import_fs20.readFileSync)(logPath, "utf-8");
36363
36780
  } else {
36364
36781
  existing = "# Wiki Log\n\n";
36365
36782
  }
@@ -36691,7 +37108,7 @@ var wikiIngestTool = {
36691
37108
  },
36692
37109
  handler: async (args) => {
36693
37110
  try {
36694
- const root = validateWorkingDirectory(args.workingDirectory);
37111
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36695
37112
  const result = ingestKnowledge(root, {
36696
37113
  title: args.title,
36697
37114
  content: args.content,
@@ -36732,7 +37149,7 @@ var wikiQueryTool = {
36732
37149
  },
36733
37150
  handler: async (args) => {
36734
37151
  try {
36735
- const root = validateWorkingDirectory(args.workingDirectory);
37152
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36736
37153
  const matches = queryWiki(root, args.query, {
36737
37154
  tags: args.tags,
36738
37155
  category: args.category,
@@ -36781,7 +37198,7 @@ var wikiLintTool = {
36781
37198
  },
36782
37199
  handler: async (args) => {
36783
37200
  try {
36784
- const root = validateWorkingDirectory(args.workingDirectory);
37201
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36785
37202
  const report = lintWiki(root);
36786
37203
  if (report.issues.length === 0) {
36787
37204
  return {
@@ -36829,7 +37246,7 @@ var wikiAddTool = {
36829
37246
  },
36830
37247
  handler: async (args) => {
36831
37248
  try {
36832
- const root = validateWorkingDirectory(args.workingDirectory);
37249
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36833
37250
  const slug = titleToSlug(args.title);
36834
37251
  if (readPage(root, slug)) {
36835
37252
  return {
@@ -36872,7 +37289,7 @@ var wikiListTool = {
36872
37289
  },
36873
37290
  handler: async (args) => {
36874
37291
  try {
36875
- const root = validateWorkingDirectory(args.workingDirectory);
37292
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36876
37293
  const index = readIndex(root);
36877
37294
  if (!index) {
36878
37295
  const pages = listPages(root);
@@ -36918,7 +37335,7 @@ var wikiReadTool = {
36918
37335
  },
36919
37336
  handler: async (args) => {
36920
37337
  try {
36921
- const root = validateWorkingDirectory(args.workingDirectory);
37338
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36922
37339
  const filename = args.page.endsWith(".md") ? args.page : `${args.page}.md`;
36923
37340
  const page = readPage(root, filename);
36924
37341
  if (!page) {
@@ -36966,7 +37383,7 @@ var wikiDeleteTool = {
36966
37383
  },
36967
37384
  handler: async (args) => {
36968
37385
  try {
36969
- const root = validateWorkingDirectory(args.workingDirectory);
37386
+ const root = validateWorkingDirectoryOrLinkedWorktree(args.workingDirectory);
36970
37387
  const filename = args.page.endsWith(".md") ? args.page : `${args.page}.md`;
36971
37388
  const deleted = deletePage(root, filename);
36972
37389
  if (!deleted) {
@@ -37012,23 +37429,23 @@ var wikiTools = [
37012
37429
  ];
37013
37430
 
37014
37431
  // src/tools/skills-tools.ts
37015
- var import_path30 = require("path");
37432
+ var import_path32 = require("path");
37016
37433
  var import_os6 = require("os");
37017
37434
 
37018
37435
  // src/hooks/learner/loader.ts
37019
- var import_fs21 = require("fs");
37436
+ var import_fs22 = require("fs");
37020
37437
  var import_crypto3 = require("crypto");
37021
- var import_path29 = require("path");
37438
+ var import_path31 = require("path");
37022
37439
 
37023
37440
  // src/hooks/learner/finder.ts
37024
- var import_fs20 = require("fs");
37025
- var import_path28 = require("path");
37441
+ var import_fs21 = require("fs");
37442
+ var import_path30 = require("path");
37026
37443
 
37027
37444
  // src/hooks/learner/constants.ts
37028
- var import_path27 = require("path");
37445
+ var import_path29 = require("path");
37029
37446
  var import_os5 = require("os");
37030
- var USER_SKILLS_DIR = (0, import_path27.join)(getConfigDir(), "skills", "omc-learned");
37031
- var GLOBAL_SKILLS_DIR = (0, import_path27.join)((0, import_os5.homedir)(), ".omcp", "skills");
37447
+ var USER_SKILLS_DIR = (0, import_path29.join)(getConfigDir(), "skills", "omc-learned");
37448
+ var GLOBAL_SKILLS_DIR = (0, import_path29.join)((0, import_os5.homedir)(), ".omcp", "skills");
37032
37449
  var PROJECT_SKILLS_SUBDIR = OmgPaths.SKILLS;
37033
37450
  var MAX_RECURSION_DEPTH = 10;
37034
37451
  var SKILL_EXTENSION = ".md";
@@ -37036,12 +37453,12 @@ var DEBUG_ENABLED = process.env.OMC_DEBUG === "1";
37036
37453
 
37037
37454
  // src/hooks/learner/finder.ts
37038
37455
  function findSkillFilesRecursive(dir, results, depth = 0) {
37039
- if (!(0, import_fs20.existsSync)(dir)) return;
37456
+ if (!(0, import_fs21.existsSync)(dir)) return;
37040
37457
  if (depth > MAX_RECURSION_DEPTH) return;
37041
37458
  try {
37042
- const entries = (0, import_fs20.readdirSync)(dir, { withFileTypes: true });
37459
+ const entries = (0, import_fs21.readdirSync)(dir, { withFileTypes: true });
37043
37460
  for (const entry of entries) {
37044
- const fullPath = (0, import_path28.join)(dir, entry.name);
37461
+ const fullPath = (0, import_path30.join)(dir, entry.name);
37045
37462
  if (entry.isDirectory()) {
37046
37463
  findSkillFilesRecursive(fullPath, results, depth + 1);
37047
37464
  } else if (entry.isFile() && entry.name.endsWith(SKILL_EXTENSION)) {
@@ -37056,22 +37473,22 @@ function findSkillFilesRecursive(dir, results, depth = 0) {
37056
37473
  }
37057
37474
  function safeRealpathSync(filePath) {
37058
37475
  try {
37059
- return (0, import_fs20.realpathSync)(filePath);
37476
+ return (0, import_fs21.realpathSync)(filePath);
37060
37477
  } catch {
37061
37478
  return filePath;
37062
37479
  }
37063
37480
  }
37064
37481
  function isWithinBoundary(realPath, boundary) {
37065
- const normalizedReal = (0, import_path28.normalize)(realPath);
37066
- const normalizedBoundary = (0, import_path28.normalize)(safeRealpathSync(boundary));
37067
- return normalizedReal === normalizedBoundary || normalizedReal.startsWith(normalizedBoundary + import_path28.sep);
37482
+ const normalizedReal = (0, import_path30.normalize)(realPath);
37483
+ const normalizedBoundary = (0, import_path30.normalize)(safeRealpathSync(boundary));
37484
+ return normalizedReal === normalizedBoundary || normalizedReal.startsWith(normalizedBoundary + import_path30.sep);
37068
37485
  }
37069
37486
  function findSkillFiles(projectRoot, options) {
37070
37487
  const candidates = [];
37071
37488
  const seenRealPaths = /* @__PURE__ */ new Set();
37072
37489
  const scope = options?.scope ?? "all";
37073
37490
  if (projectRoot && (scope === "project" || scope === "all")) {
37074
- const projectSkillsDir = (0, import_path28.join)(projectRoot, PROJECT_SKILLS_SUBDIR);
37491
+ const projectSkillsDir = (0, import_path30.join)(projectRoot, PROJECT_SKILLS_SUBDIR);
37075
37492
  const projectFiles = [];
37076
37493
  findSkillFilesRecursive(projectSkillsDir, projectFiles);
37077
37494
  for (const filePath of projectFiles) {
@@ -37277,7 +37694,7 @@ function loadAllSkills(projectRoot) {
37277
37694
  const seenIds = /* @__PURE__ */ new Map();
37278
37695
  for (const candidate of candidates) {
37279
37696
  try {
37280
- const rawContent = (0, import_fs21.readFileSync)(candidate.path, "utf-8");
37697
+ const rawContent = (0, import_fs22.readFileSync)(candidate.path, "utf-8");
37281
37698
  const { metadata, content, valid, errors } = parseSkillFile(rawContent);
37282
37699
  if (!valid) {
37283
37700
  if (DEBUG_ENABLED) {
@@ -37286,7 +37703,7 @@ function loadAllSkills(projectRoot) {
37286
37703
  continue;
37287
37704
  }
37288
37705
  const skillId = metadata.id;
37289
- const relativePath = (0, import_path29.normalize)((0, import_path29.relative)(candidate.sourceDir, candidate.path));
37706
+ const relativePath = (0, import_path31.normalize)((0, import_path31.relative)(candidate.sourceDir, candidate.path));
37290
37707
  const skill = {
37291
37708
  path: candidate.path,
37292
37709
  relativePath,
@@ -37312,13 +37729,13 @@ function loadAllSkills(projectRoot) {
37312
37729
  // src/tools/skills-tools.ts
37313
37730
  var ALLOWED_BOUNDARIES = [process.cwd(), (0, import_os6.homedir)()];
37314
37731
  function validateProjectRoot(input) {
37315
- const normalized = (0, import_path30.normalize)((0, import_path30.resolve)(input));
37732
+ const normalized = (0, import_path32.normalize)((0, import_path32.resolve)(input));
37316
37733
  if (input.includes("..")) {
37317
37734
  throw new Error("Invalid project root: path traversal not allowed");
37318
37735
  }
37319
37736
  const isWithinAllowed = ALLOWED_BOUNDARIES.some((boundary) => {
37320
- const normalizedBoundary = (0, import_path30.normalize)(boundary);
37321
- return normalized === normalizedBoundary || normalized.startsWith(normalizedBoundary + import_path30.sep);
37737
+ const normalizedBoundary = (0, import_path32.normalize)(boundary);
37738
+ return normalized === normalizedBoundary || normalized.startsWith(normalizedBoundary + import_path32.sep);
37322
37739
  });
37323
37740
  if (!isWithinAllowed) {
37324
37741
  throw new Error("Invalid project root: path is outside allowed directories");