@intutic/sync-daemon 2.1.0 → 2.3.0

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 (288) hide show
  1. package/README.md +1 -1
  2. package/dist/agentReporter.d.ts +24 -11
  3. package/dist/agentReporter.d.ts.map +1 -1
  4. package/dist/agentReporter.js +20 -13
  5. package/dist/agentReporter.js.map +1 -1
  6. package/dist/configReader.d.ts +45 -25
  7. package/dist/configReader.d.ts.map +1 -1
  8. package/dist/configReader.js +70 -46
  9. package/dist/configReader.js.map +1 -1
  10. package/dist/configWriter.d.ts +32 -45
  11. package/dist/configWriter.d.ts.map +1 -1
  12. package/dist/configWriter.js +52 -686
  13. package/dist/configWriter.js.map +1 -1
  14. package/dist/disconnect/harnesses.d.ts +29 -0
  15. package/dist/disconnect/harnesses.d.ts.map +1 -0
  16. package/dist/disconnect/harnesses.js +805 -0
  17. package/dist/disconnect/harnesses.js.map +1 -0
  18. package/dist/disconnect/index.d.ts +25 -0
  19. package/dist/disconnect/index.d.ts.map +1 -0
  20. package/dist/disconnect/index.js +92 -0
  21. package/dist/disconnect/index.js.map +1 -0
  22. package/dist/disconnect/mcp.d.ts +81 -0
  23. package/dist/disconnect/mcp.d.ts.map +1 -0
  24. package/dist/disconnect/mcp.js +354 -0
  25. package/dist/disconnect/mcp.js.map +1 -0
  26. package/dist/disconnect/originals.d.ts +88 -0
  27. package/dist/disconnect/originals.d.ts.map +1 -0
  28. package/dist/disconnect/originals.js +257 -0
  29. package/dist/disconnect/originals.js.map +1 -0
  30. package/dist/disconnect/plan.d.ts +175 -0
  31. package/dist/disconnect/plan.d.ts.map +1 -0
  32. package/dist/disconnect/plan.js +580 -0
  33. package/dist/disconnect/plan.js.map +1 -0
  34. package/dist/disconnect/recognise.d.ts +43 -0
  35. package/dist/disconnect/recognise.d.ts.map +1 -0
  36. package/dist/disconnect/recognise.js +108 -0
  37. package/dist/disconnect/recognise.js.map +1 -0
  38. package/dist/disconnect/tomlLines.d.ts +39 -0
  39. package/dist/disconnect/tomlLines.d.ts.map +1 -0
  40. package/dist/disconnect/tomlLines.js +105 -0
  41. package/dist/disconnect/tomlLines.js.map +1 -0
  42. package/dist/harness/aiderConfigMerger.d.ts +29 -8
  43. package/dist/harness/aiderConfigMerger.d.ts.map +1 -1
  44. package/dist/harness/aiderConfigMerger.js +63 -12
  45. package/dist/harness/aiderConfigMerger.js.map +1 -1
  46. package/dist/harness/antigravityCliHooks.d.ts +61 -0
  47. package/dist/harness/antigravityCliHooks.d.ts.map +1 -0
  48. package/dist/harness/antigravityCliHooks.js +207 -0
  49. package/dist/harness/antigravityCliHooks.js.map +1 -0
  50. package/dist/harness/antigravityHooks.d.ts +12 -2
  51. package/dist/harness/antigravityHooks.d.ts.map +1 -1
  52. package/dist/harness/antigravityHooks.js +38 -16
  53. package/dist/harness/antigravityHooks.js.map +1 -1
  54. package/dist/harness/antigravityProducts.d.ts +40 -0
  55. package/dist/harness/antigravityProducts.d.ts.map +1 -0
  56. package/dist/harness/antigravityProducts.js +109 -0
  57. package/dist/harness/antigravityProducts.js.map +1 -0
  58. package/dist/harness/claudeAgentsMd.d.ts +29 -0
  59. package/dist/harness/claudeAgentsMd.d.ts.map +1 -0
  60. package/dist/harness/claudeAgentsMd.js +80 -0
  61. package/dist/harness/claudeAgentsMd.js.map +1 -0
  62. package/dist/harness/claudeCodeHooks.d.ts +6 -6
  63. package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
  64. package/dist/harness/claudeCodeHooks.js +115 -28
  65. package/dist/harness/claudeCodeHooks.js.map +1 -1
  66. package/dist/harness/claudeProjectApproval.d.ts +53 -0
  67. package/dist/harness/claudeProjectApproval.d.ts.map +1 -0
  68. package/dist/harness/claudeProjectApproval.js +159 -0
  69. package/dist/harness/claudeProjectApproval.js.map +1 -0
  70. package/dist/harness/clineHooks.d.ts +0 -1
  71. package/dist/harness/clineHooks.d.ts.map +1 -1
  72. package/dist/harness/clineHooks.js +13 -4
  73. package/dist/harness/clineHooks.js.map +1 -1
  74. package/dist/harness/codexConfigMerger.d.ts.map +1 -1
  75. package/dist/harness/codexConfigMerger.js +4 -0
  76. package/dist/harness/codexConfigMerger.js.map +1 -1
  77. package/dist/harness/codexHooks.d.ts +2 -0
  78. package/dist/harness/codexHooks.d.ts.map +1 -1
  79. package/dist/harness/codexHooks.js +15 -4
  80. package/dist/harness/codexHooks.js.map +1 -1
  81. package/dist/harness/continueConfigMerger.d.ts.map +1 -1
  82. package/dist/harness/continueConfigMerger.js +4 -0
  83. package/dist/harness/continueConfigMerger.js.map +1 -1
  84. package/dist/harness/cursorHooks.d.ts +5 -2
  85. package/dist/harness/cursorHooks.d.ts.map +1 -1
  86. package/dist/harness/cursorHooks.js +12 -3
  87. package/dist/harness/cursorHooks.js.map +1 -1
  88. package/dist/harness/dshHooks.d.ts +5 -5
  89. package/dist/harness/dshHooks.d.ts.map +1 -1
  90. package/dist/harness/dshHooks.js +12 -5
  91. package/dist/harness/dshHooks.js.map +1 -1
  92. package/dist/harness/gateArtifacts.d.ts +35 -0
  93. package/dist/harness/gateArtifacts.d.ts.map +1 -0
  94. package/dist/harness/gateArtifacts.js +88 -0
  95. package/dist/harness/gateArtifacts.js.map +1 -0
  96. package/dist/harness/gateBody.d.ts +195 -69
  97. package/dist/harness/gateBody.d.ts.map +1 -1
  98. package/dist/harness/gateBody.js +847 -182
  99. package/dist/harness/gateBody.js.map +1 -1
  100. package/dist/harness/gateSightings.d.ts +47 -0
  101. package/dist/harness/gateSightings.d.ts.map +1 -0
  102. package/dist/harness/gateSightings.js +159 -0
  103. package/dist/harness/gateSightings.js.map +1 -0
  104. package/dist/harness/githubCopilotHooks.d.ts.map +1 -1
  105. package/dist/harness/githubCopilotHooks.js +11 -10
  106. package/dist/harness/githubCopilotHooks.js.map +1 -1
  107. package/dist/harness/gooseHardener.d.ts +0 -1
  108. package/dist/harness/gooseHardener.d.ts.map +1 -1
  109. package/dist/harness/gooseHardener.js +1 -1
  110. package/dist/harness/gooseHardener.js.map +1 -1
  111. package/dist/harness/gooseHooks.d.ts +29 -1
  112. package/dist/harness/gooseHooks.d.ts.map +1 -1
  113. package/dist/harness/gooseHooks.js +107 -69
  114. package/dist/harness/gooseHooks.js.map +1 -1
  115. package/dist/harness/grokHooks.d.ts +2 -2
  116. package/dist/harness/grokHooks.d.ts.map +1 -1
  117. package/dist/harness/grokHooks.js +20 -18
  118. package/dist/harness/grokHooks.js.map +1 -1
  119. package/dist/harness/hermesHooks.d.ts +18 -8
  120. package/dist/harness/hermesHooks.d.ts.map +1 -1
  121. package/dist/harness/hermesHooks.js +55 -19
  122. package/dist/harness/hermesHooks.js.map +1 -1
  123. package/dist/harness/holdRedaction.d.ts +4 -1
  124. package/dist/harness/holdRedaction.d.ts.map +1 -1
  125. package/dist/harness/holdRedaction.js +32 -8
  126. package/dist/harness/holdRedaction.js.map +1 -1
  127. package/dist/harness/jetbrainsXmlConfig.d.ts +20 -0
  128. package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -1
  129. package/dist/harness/jetbrainsXmlConfig.js +39 -18
  130. package/dist/harness/jetbrainsXmlConfig.js.map +1 -1
  131. package/dist/harness/mcpAutoWrite.d.ts +62 -25
  132. package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
  133. package/dist/harness/mcpAutoWrite.js +406 -95
  134. package/dist/harness/mcpAutoWrite.js.map +1 -1
  135. package/dist/harness/museHooks.d.ts +3 -3
  136. package/dist/harness/museHooks.d.ts.map +1 -1
  137. package/dist/harness/museHooks.js +15 -7
  138. package/dist/harness/museHooks.js.map +1 -1
  139. package/dist/harness/n8nHooks.d.ts +0 -1
  140. package/dist/harness/n8nHooks.d.ts.map +1 -1
  141. package/dist/harness/n8nHooks.js +4 -1
  142. package/dist/harness/n8nHooks.js.map +1 -1
  143. package/dist/harness/openCodeHooks.d.ts +2 -2
  144. package/dist/harness/openCodeHooks.d.ts.map +1 -1
  145. package/dist/harness/openCodeHooks.js +9 -8
  146. package/dist/harness/openCodeHooks.js.map +1 -1
  147. package/dist/harness/openWebuiHooks.d.ts +0 -1
  148. package/dist/harness/openWebuiHooks.d.ts.map +1 -1
  149. package/dist/harness/openWebuiHooks.js +11 -3
  150. package/dist/harness/openWebuiHooks.js.map +1 -1
  151. package/dist/harness/openclawHooks.d.ts +75 -18
  152. package/dist/harness/openclawHooks.d.ts.map +1 -1
  153. package/dist/harness/openclawHooks.js +214 -160
  154. package/dist/harness/openclawHooks.js.map +1 -1
  155. package/dist/harness/openhandsHooks.d.ts +37 -11
  156. package/dist/harness/openhandsHooks.d.ts.map +1 -1
  157. package/dist/harness/openhandsHooks.js +148 -97
  158. package/dist/harness/openhandsHooks.js.map +1 -1
  159. package/dist/harness/piHooks.d.ts +52 -17
  160. package/dist/harness/piHooks.d.ts.map +1 -1
  161. package/dist/harness/piHooks.js +177 -163
  162. package/dist/harness/piHooks.js.map +1 -1
  163. package/dist/harness/protectedPaths.d.ts +107 -25
  164. package/dist/harness/protectedPaths.d.ts.map +1 -1
  165. package/dist/harness/protectedPaths.js +342 -48
  166. package/dist/harness/protectedPaths.js.map +1 -1
  167. package/dist/harness/rulesSection.d.ts +62 -0
  168. package/dist/harness/rulesSection.d.ts.map +1 -0
  169. package/dist/harness/rulesSection.js +145 -0
  170. package/dist/harness/rulesSection.js.map +1 -0
  171. package/dist/harness/windsurfHooks.d.ts +18 -3
  172. package/dist/harness/windsurfHooks.d.ts.map +1 -1
  173. package/dist/harness/windsurfHooks.js +41 -8
  174. package/dist/harness/windsurfHooks.js.map +1 -1
  175. package/dist/harness/windsurfJetBrainsProxy.d.ts +1 -1
  176. package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -1
  177. package/dist/harness/windsurfJetBrainsProxy.js +5 -1
  178. package/dist/harness/windsurfJetBrainsProxy.js.map +1 -1
  179. package/dist/index.d.ts +21 -20
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +19 -19
  182. package/dist/index.js.map +1 -1
  183. package/dist/inventory.d.ts +53 -0
  184. package/dist/inventory.d.ts.map +1 -0
  185. package/dist/inventory.js +133 -0
  186. package/dist/inventory.js.map +1 -0
  187. package/dist/lib/complianceProbes.d.ts +2 -1
  188. package/dist/lib/complianceProbes.d.ts.map +1 -1
  189. package/dist/lib/complianceProbes.js +1 -1
  190. package/dist/lib/complianceProbes.js.map +1 -1
  191. package/dist/lib/decisionsDigest.d.ts +35 -17
  192. package/dist/lib/decisionsDigest.d.ts.map +1 -1
  193. package/dist/lib/decisionsDigest.js +106 -47
  194. package/dist/lib/decisionsDigest.js.map +1 -1
  195. package/dist/lib/egressPolicy.d.ts +2 -2
  196. package/dist/lib/egressPolicy.js +2 -2
  197. package/dist/lib/mcpRegistryPy.d.ts +11 -0
  198. package/dist/lib/mcpRegistryPy.d.ts.map +1 -0
  199. package/dist/lib/mcpRegistryPy.js +173 -0
  200. package/dist/lib/mcpRegistryPy.js.map +1 -0
  201. package/dist/lib/phrasesPy.d.ts +11 -0
  202. package/dist/lib/phrasesPy.d.ts.map +1 -0
  203. package/dist/lib/phrasesPy.js +351 -0
  204. package/dist/lib/phrasesPy.js.map +1 -0
  205. package/dist/lib/policySnapshot.d.ts +63 -9
  206. package/dist/lib/policySnapshot.d.ts.map +1 -1
  207. package/dist/lib/policySnapshot.js +269 -45
  208. package/dist/lib/policySnapshot.js.map +1 -1
  209. package/dist/lib/processPoller.d.ts.map +1 -1
  210. package/dist/lib/processPoller.js +9 -2
  211. package/dist/lib/processPoller.js.map +1 -1
  212. package/dist/lib/regexLinearity.d.ts +43 -0
  213. package/dist/lib/regexLinearity.d.ts.map +1 -0
  214. package/dist/lib/regexLinearity.js +275 -0
  215. package/dist/lib/regexLinearity.js.map +1 -0
  216. package/dist/lib/runtimeEnv.d.ts +1 -3
  217. package/dist/lib/runtimeEnv.d.ts.map +1 -1
  218. package/dist/lib/runtimeEnv.js +0 -2
  219. package/dist/lib/runtimeEnv.js.map +1 -1
  220. package/dist/lib/sequencePy.d.ts +10 -0
  221. package/dist/lib/sequencePy.d.ts.map +1 -0
  222. package/dist/lib/sequencePy.js +102 -0
  223. package/dist/lib/sequencePy.js.map +1 -0
  224. package/dist/sessionReporter.d.ts +18 -12
  225. package/dist/sessionReporter.d.ts.map +1 -1
  226. package/dist/sessionReporter.js +37 -24
  227. package/dist/sessionReporter.js.map +1 -1
  228. package/dist/skillWriter.d.ts +23 -5
  229. package/dist/skillWriter.d.ts.map +1 -1
  230. package/dist/skillWriter.js +159 -16
  231. package/dist/skillWriter.js.map +1 -1
  232. package/dist/syncCycle.d.ts +142 -0
  233. package/dist/syncCycle.d.ts.map +1 -0
  234. package/dist/syncCycle.js +327 -0
  235. package/dist/syncCycle.js.map +1 -0
  236. package/dist/trajectoryMonitor.d.ts +2 -4
  237. package/dist/trajectoryMonitor.d.ts.map +1 -1
  238. package/dist/trajectoryMonitor.js +2 -5
  239. package/dist/trajectoryMonitor.js.map +1 -1
  240. package/dist/watcher/driftWatcher.d.ts +0 -1
  241. package/dist/watcher/driftWatcher.d.ts.map +1 -1
  242. package/dist/watcher/driftWatcher.js +1 -2
  243. package/dist/watcher/driftWatcher.js.map +1 -1
  244. package/dist/watcher/settingsGuard.d.ts +36 -7
  245. package/dist/watcher/settingsGuard.d.ts.map +1 -1
  246. package/dist/watcher/settingsGuard.js +397 -60
  247. package/dist/watcher/settingsGuard.js.map +1 -1
  248. package/dist/watcher/vscodeHookSettings.d.ts +30 -0
  249. package/dist/watcher/vscodeHookSettings.d.ts.map +1 -0
  250. package/dist/watcher/vscodeHookSettings.js +170 -0
  251. package/dist/watcher/vscodeHookSettings.js.map +1 -0
  252. package/dist/wsClient.d.ts +0 -1
  253. package/dist/wsClient.d.ts.map +1 -1
  254. package/dist/wsClient.js +0 -1
  255. package/dist/wsClient.js.map +1 -1
  256. package/package.json +5 -5
  257. package/dist/harness/claudeDesktopHooks.d.ts +0 -30
  258. package/dist/harness/claudeDesktopHooks.d.ts.map +0 -1
  259. package/dist/harness/claudeDesktopHooks.js +0 -254
  260. package/dist/harness/claudeDesktopHooks.js.map +0 -1
  261. package/dist/harness/continueHooks.d.ts +0 -63
  262. package/dist/harness/continueHooks.d.ts.map +0 -1
  263. package/dist/harness/continueHooks.js +0 -247
  264. package/dist/harness/continueHooks.js.map +0 -1
  265. package/dist/harness/gateKind.d.ts +0 -164
  266. package/dist/harness/gateKind.d.ts.map +0 -1
  267. package/dist/harness/gateKind.js +0 -144
  268. package/dist/harness/gateKind.js.map +0 -1
  269. package/dist/harness/rooCodeHooks.d.ts +0 -31
  270. package/dist/harness/rooCodeHooks.d.ts.map +0 -1
  271. package/dist/harness/rooCodeHooks.js +0 -286
  272. package/dist/harness/rooCodeHooks.js.map +0 -1
  273. package/dist/hashReporter.d.ts +0 -33
  274. package/dist/hashReporter.d.ts.map +0 -1
  275. package/dist/hashReporter.js +0 -69
  276. package/dist/hashReporter.js.map +0 -1
  277. package/dist/integrityStore.d.ts +0 -35
  278. package/dist/integrityStore.d.ts.map +0 -1
  279. package/dist/integrityStore.js +0 -71
  280. package/dist/integrityStore.js.map +0 -1
  281. package/dist/lib/gitWorktrees.d.ts +0 -140
  282. package/dist/lib/gitWorktrees.d.ts.map +0 -1
  283. package/dist/lib/gitWorktrees.js +0 -191
  284. package/dist/lib/gitWorktrees.js.map +0 -1
  285. package/dist/syncLoop.d.ts +0 -172
  286. package/dist/syncLoop.d.ts.map +0 -1
  287. package/dist/syncLoop.js +0 -878
  288. package/dist/syncLoop.js.map +0 -1
@@ -1,33 +0,0 @@
1
- /**
2
- * hashReporter.ts — SHA-256 hash computation + integrity comparison.
3
- *
4
- * Computes SHA-256 hashes of local harness config files and compares
5
- * them against canonical hashes from the control plane. This enables
6
- * SOP drift detection: if a developer manually edits a governed file,
7
- * the daemon flags it as drifted in the next sync report.
8
- *
9
- * HLD §3.14 — SOP Integrity Verification
10
- * LLD #8 — Sync Daemon / CLI
11
- *
12
- * @module
13
- */
14
- import type { HarnessType, SopFileHash } from '@intutic/shared-types';
15
- /**
16
- * Compute SHA-256 hashes for all harness config files and compare
17
- * against canonical hashes from the control plane.
18
- *
19
- * @param workspaceRoot - Absolute path to the workspace root.
20
- * @param harnesses - Harness types detected in the workspace.
21
- * @param canonicalHashes - Expected hashes from last sync (filePath → SHA-256).
22
- * @returns Array of SopFileHash entries with drift detection flags.
23
- */
24
- export declare function computeFileHashes(workspaceRoot: string, harnesses: HarnessType[], canonicalHashes: Record<string, string>): Promise<SopFileHash[]>;
25
- /**
26
- * Compute the SHA-256 hex digest of a file's contents.
27
- *
28
- * @param filePath - Absolute path to the file.
29
- * @returns 64-character lowercase hex SHA-256 hash.
30
- * @throws If the file does not exist or is not readable.
31
- */
32
- export declare function hashFile(filePath: string): Promise<string>;
33
- //# sourceMappingURL=hashReporter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hashReporter.d.ts","sourceRoot":"","sources":["../src/hashReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAGrE;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,WAAW,EAAE,EACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,OAAO,CAAC,WAAW,EAAE,CAAC,CAiCxB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE"}
@@ -1,69 +0,0 @@
1
- /**
2
- * hashReporter.ts — SHA-256 hash computation + integrity comparison.
3
- *
4
- * Computes SHA-256 hashes of local harness config files and compares
5
- * them against canonical hashes from the control plane. This enables
6
- * SOP drift detection: if a developer manually edits a governed file,
7
- * the daemon flags it as drifted in the next sync report.
8
- *
9
- * HLD §3.14 — SOP Integrity Verification
10
- * LLD #8 — Sync Daemon / CLI
11
- *
12
- * @module
13
- */
14
- import { createHash } from 'node:crypto';
15
- import * as node_fs from 'node:fs/promises';
16
- import * as node_path from 'node:path';
17
- import { HARNESS_FILES } from './configWriter.js';
18
- /**
19
- * Compute SHA-256 hashes for all harness config files and compare
20
- * against canonical hashes from the control plane.
21
- *
22
- * @param workspaceRoot - Absolute path to the workspace root.
23
- * @param harnesses - Harness types detected in the workspace.
24
- * @param canonicalHashes - Expected hashes from last sync (filePath → SHA-256).
25
- * @returns Array of SopFileHash entries with drift detection flags.
26
- */
27
- export async function computeFileHashes(workspaceRoot, harnesses, canonicalHashes) {
28
- const results = [];
29
- for (const harness of harnesses) {
30
- const filename = HARNESS_FILES[harness];
31
- if (!filename)
32
- continue; // Phase 2 deferred
33
- const configPath = node_path.join(workspaceRoot, filename);
34
- const relativePath = filename;
35
- try {
36
- const localHash = await hashFile(configPath);
37
- const canonical = canonicalHashes[relativePath] ?? '';
38
- const drifted = canonical !== '' && localHash !== canonical;
39
- results.push({
40
- filePath: relativePath,
41
- localHash,
42
- canonicalHash: canonical,
43
- drifted,
44
- });
45
- }
46
- catch {
47
- // File doesn't exist or isn't readable — report empty hash, not drifted
48
- results.push({
49
- filePath: relativePath,
50
- localHash: '',
51
- canonicalHash: canonicalHashes[relativePath] ?? '',
52
- drifted: false,
53
- });
54
- }
55
- }
56
- return results;
57
- }
58
- /**
59
- * Compute the SHA-256 hex digest of a file's contents.
60
- *
61
- * @param filePath - Absolute path to the file.
62
- * @returns 64-character lowercase hex SHA-256 hash.
63
- * @throws If the file does not exist or is not readable.
64
- */
65
- export async function hashFile(filePath) {
66
- const content = await node_fs.readFile(filePath, 'utf-8');
67
- return createHash('sha256').update(content, 'utf-8').digest('hex');
68
- }
69
- //# sourceMappingURL=hashReporter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hashReporter.js","sourceRoot":"","sources":["../src/hashReporter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,aAAqB,EACrB,SAAwB,EACxB,eAAuC;IAEvC,MAAM,OAAO,GAAkB,EAAE,CAAA;IAEjC,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAA;QACvC,IAAI,CAAC,QAAQ;YAAE,SAAQ,CAAC,mBAAmB;QAE3C,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;QAC1D,MAAM,YAAY,GAAG,QAAQ,CAAA;QAE7B,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAA;YAC5C,MAAM,SAAS,GAAG,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE,CAAA;YACrD,MAAM,OAAO,GAAG,SAAS,KAAK,EAAE,IAAI,SAAS,KAAK,SAAS,CAAA;YAE3D,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,YAAY;gBACtB,SAAS;gBACT,aAAa,EAAE,SAAS;gBACxB,OAAO;aACR,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,OAAO,CAAC,IAAI,CAAC;gBACX,QAAQ,EAAE,YAAY;gBACtB,SAAS,EAAE,EAAE;gBACb,aAAa,EAAE,eAAe,CAAC,YAAY,CAAC,IAAI,EAAE;gBAClD,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IACzD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACpE,CAAC"}
@@ -1,35 +0,0 @@
1
- /**
2
- * integrityStore.ts — Local .intutic/integrity.json manager.
3
- *
4
- * Maintains a per-workspace integrity store that tracks the last sync
5
- * timestamp, config version, and canonical file hashes. This allows
6
- * the daemon to skip redundant syncs when the config version hasn't
7
- * changed and to detect local drift between sync cycles.
8
- *
9
- * HLD §3.14 — Real-Time State Mirroring
10
- * LLD #8 — Sync Daemon / CLI
11
- *
12
- * @module
13
- */
14
- import type { IntegrityStore } from '@intutic/shared-types';
15
- /**
16
- * Load the local integrity store from `.intutic/integrity.json`.
17
- *
18
- * Returns `null` if the file doesn't exist (first sync) or is
19
- * corrupted (will be overwritten on next save).
20
- *
21
- * @param workspaceRoot - Absolute path to the workspace root.
22
- * @returns The parsed IntegrityStore, or null if not found.
23
- */
24
- export declare function loadIntegrity(workspaceRoot: string): Promise<IntegrityStore | null>;
25
- /**
26
- * Save the integrity store to `.intutic/integrity.json`.
27
- *
28
- * Creates the `.intutic/` directory if it doesn't exist.
29
- * Uses atomic write (tmp → rename) to prevent corruption.
30
- *
31
- * @param workspaceRoot - Absolute path to the workspace root.
32
- * @param store - The IntegrityStore to persist.
33
- */
34
- export declare function saveIntegrity(workspaceRoot: string, store: IntegrityStore): Promise<void>;
35
- //# sourceMappingURL=integrityStore.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integrityStore.d.ts","sourceRoot":"","sources":["../src/integrityStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAQ3D;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAqBhC;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -1,71 +0,0 @@
1
- /**
2
- * integrityStore.ts — Local .intutic/integrity.json manager.
3
- *
4
- * Maintains a per-workspace integrity store that tracks the last sync
5
- * timestamp, config version, and canonical file hashes. This allows
6
- * the daemon to skip redundant syncs when the config version hasn't
7
- * changed and to detect local drift between sync cycles.
8
- *
9
- * HLD §3.14 — Real-Time State Mirroring
10
- * LLD #8 — Sync Daemon / CLI
11
- *
12
- * @module
13
- */
14
- import * as node_fs from 'node:fs/promises';
15
- import * as node_path from 'node:path';
16
- /** Filename for the integrity store within the `.intutic/` directory. */
17
- const INTEGRITY_FILE = 'integrity.json';
18
- /** Directory name for Intutic local state. */
19
- const INTUTIC_DIR = '.intutic';
20
- /**
21
- * Load the local integrity store from `.intutic/integrity.json`.
22
- *
23
- * Returns `null` if the file doesn't exist (first sync) or is
24
- * corrupted (will be overwritten on next save).
25
- *
26
- * @param workspaceRoot - Absolute path to the workspace root.
27
- * @returns The parsed IntegrityStore, or null if not found.
28
- */
29
- export async function loadIntegrity(workspaceRoot) {
30
- const filePath = node_path.join(workspaceRoot, INTUTIC_DIR, INTEGRITY_FILE);
31
- try {
32
- const raw = await node_fs.readFile(filePath, 'utf-8');
33
- const parsed = JSON.parse(raw);
34
- // Basic shape validation
35
- if (typeof parsed.lastSyncAt !== 'string' ||
36
- typeof parsed.configVersion !== 'number' ||
37
- typeof parsed.files !== 'object') {
38
- return null;
39
- }
40
- return parsed;
41
- }
42
- catch {
43
- // File doesn't exist or is corrupted
44
- return null;
45
- }
46
- }
47
- /**
48
- * Save the integrity store to `.intutic/integrity.json`.
49
- *
50
- * Creates the `.intutic/` directory if it doesn't exist.
51
- * Uses atomic write (tmp → rename) to prevent corruption.
52
- *
53
- * @param workspaceRoot - Absolute path to the workspace root.
54
- * @param store - The IntegrityStore to persist.
55
- */
56
- export async function saveIntegrity(workspaceRoot, store) {
57
- const dir = node_path.join(workspaceRoot, INTUTIC_DIR);
58
- await node_fs.mkdir(dir, { recursive: true });
59
- const filePath = node_path.join(dir, INTEGRITY_FILE);
60
- const tmpPath = `${filePath}.tmp`;
61
- const content = JSON.stringify(store, null, 2) + '\n';
62
- await node_fs.writeFile(tmpPath, content, 'utf-8');
63
- await node_fs.rename(tmpPath, filePath);
64
- }
65
- // `loadContextIntegrity` / `saveContextIntegrity` were removed on 2026-07-30. They
66
- // had no callers in either repo — not even tests — while
67
- // `.intutic/context_integrity.json` sat in three harness hook denylists as a
68
- // protected path. The file was never created, so those hooks guarded nothing. The
69
- // config integrity store above already hashes every governed file `syncLoop` writes,
70
- // which is what the second store would have duplicated.
71
- //# sourceMappingURL=integrityStore.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"integrityStore.js","sourceRoot":"","sources":["../src/integrityStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,SAAS,MAAM,WAAW,CAAA;AAGtC,yEAAyE;AACzE,MAAM,cAAc,GAAG,gBAAgB,CAAA;AAEvC,8CAA8C;AAC9C,MAAM,WAAW,GAAG,UAAU,CAAA;AAE9B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,aAAqB;IAErB,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,cAAc,CAAC,CAAA;IAE3E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAA;QAEhD,yBAAyB;QACzB,IACE,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ;YACrC,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;YACxC,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAChC,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,qCAAqC;QACrC,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,aAAqB,EACrB,KAAqB;IAErB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAA;IACtD,MAAM,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE7C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IACpD,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAA;IACjC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAA;IAErD,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAClD,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AACzC,CAAC;AAGD,mFAAmF;AACnF,yDAAyD;AACzD,6EAA6E;AAC7E,kFAAkF;AAClF,qFAAqF;AACrF,wDAAwD"}
@@ -1,140 +0,0 @@
1
- /**
2
- * gitWorktrees.ts — discovers every `git worktree` checkout of a repo the
3
- * sync daemon is watching, so project-tier governance files can be written
4
- * into each one, not just the main checkout.
5
- *
6
- * # The gap this closes
7
- *
8
- * `git worktree add <path>` creates a second, fully independent WORKING
9
- * TREE that shares the main checkout's `.git` object store (via a `.git`
10
- * FILE pointing back at `<main>/.git/worktrees/<name>`) but has its own
11
- * untracked files. Every project-tier governance file this product writes
12
- * — `.claude/settings.json`, `.cursor/hooks.json`, `.intutic/hooks/*`,
13
- * `AGENTS.md`'s sibling hook registrations, the wrapped `.mcp.json` entries,
14
- * etc. — is untracked by convention (SOP content is workspace-specific and
15
- * synced from the control plane, not committed). That means none of it
16
- * exists in a worktree's working tree by default: `writeConfigFiles`/
17
- * `injectMcpServer` running against only the main checkout's `workspaceRoot`
18
- * leaves every OTHER worktree of that same repo completely ungoverned,
19
- * regardless of what the main checkout has configured.
20
- *
21
- * This was already true for any hand-rolled `git worktree` workflow before
22
- * this module existed — Xirp (an orchestrator that spawns CLI agents each
23
- * inside its own tmux session + git worktree, see `tools/cli/src/harness/
24
- * xirp.ts`) is what surfaced it, but the fix here is general: it benefits
25
- * ANY worktree-based workflow, Xirp-managed or not. See TD-390.
26
- *
27
- * # Verifying the mechanics for real
28
- *
29
- * Confirmed against a real throwaway repo during this module's development
30
- * (not asserted from memory of git's docs): an untracked file written into
31
- * a main checkout is NOT visible from a `git worktree add`-created sibling
32
- * checkout's directory. `git worktree list --porcelain`'s block format,
33
- * including `locked`/`prunable`/`bare`/`detached` fields, was captured from
34
- * a real `git worktree list --porcelain` run (this module's own test suite
35
- * builds the same kind of fixture, in an isolated temp directory, rather
36
- * than relying on this description alone).
37
- *
38
- * @module
39
- */
40
- /** One block of `git worktree list --porcelain` output, parsed. */
41
- export interface WorktreeInfo {
42
- /** Absolute path to this worktree's working directory. */
43
- path: string;
44
- /** Commit the worktree's HEAD points at, or null if not reported (bare). */
45
- head: string | null;
46
- /** Branch ref this worktree has checked out (e.g. `refs/heads/main`), or
47
- * null when detached or bare. */
48
- branch: string | null;
49
- /** True if this worktree's HEAD is detached (no branch checked out). */
50
- detached: boolean;
51
- /** True for the bare-repository worktree entry — the repo root itself
52
- * when it has no working tree of its own files (only ever the first
53
- * entry, and only for a bare repo). */
54
- bare: boolean;
55
- /** True if this worktree is locked (`git worktree lock`) — git will not
56
- * prune it even if its directory looks gone. Locking does not restrict
57
- * reading or writing ordinary files in it, so this does not by itself
58
- * change whether `discoverWorktrees` includes the path. */
59
- locked: boolean;
60
- /** Reason string passed to `git worktree lock --reason`, if any. */
61
- lockedReason: string | null;
62
- /** True if git has flagged this worktree's directory as missing/invalid
63
- * and a candidate for `git worktree prune`. */
64
- prunable: boolean;
65
- /** Reason string git reports for why this worktree is prunable, if any. */
66
- prunableReason: string | null;
67
- }
68
- /**
69
- * Parses `git worktree list --porcelain` output.
70
- *
71
- * Real format (verified against a live `git worktree list --porcelain` run,
72
- * git 2.x): one block per worktree, separated by a blank line, each line a
73
- * bare keyword or `<keyword> <value>`:
74
- *
75
- * ```
76
- * worktree /path/to/main
77
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
78
- * branch refs/heads/master
79
- *
80
- * worktree /path/to/locked-wt
81
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
82
- * branch refs/heads/feature2
83
- * locked testing lock
84
- *
85
- * worktree /path/to/detached-wt
86
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
87
- * detached
88
- * ```
89
- *
90
- * Deliberately implemented with plain string methods (`startsWith`/`slice`)
91
- * rather than a line-matching regex — this parses `git`-controlled, not
92
- * attacker-controlled, input, but a sibling Wave 1 phase shipped a
93
- * CodeQL-flagged polynomial-regex bug from exactly this kind of "just trim
94
- * a path" text handling, so the same class of construct is avoided here on
95
- * principle even though the input source differs.
96
- */
97
- export declare function parseWorktreeListPorcelain(output: string): WorktreeInfo[];
98
- /**
99
- * Discovers every worktree of the git repository containing `repoRoot`,
100
- * returning the absolute paths that should be treated as additional
101
- * project-tier workspace roots.
102
- *
103
- * Filtering decisions, made explicit rather than left implicit:
104
- *
105
- * - **The main checkout is included.** `git worktree list` always lists it
106
- * first (confirmed against a live run) — it needs no special-casing by
107
- * callers; a caller that already writes to `repoRoot` directly can simply
108
- * skip a returned path equal to `repoRoot` if it wants to avoid a
109
- * redundant duplicate write, but the list is uniformly correct either way.
110
- * - **Locked worktrees are included.** `git worktree lock` only prevents
111
- * git's own pruning of a worktree it cannot otherwise verify still
112
- * exists (e.g. on removable storage) — it says nothing about whether the
113
- * directory is currently present and writable, which it normally is.
114
- * Excluding locked worktrees would silently under-cover a workflow (like
115
- * Xirp's) that locks worktrees deliberately to protect them from being
116
- * pruned out from under a long-running session — exactly the worktrees
117
- * most worth covering.
118
- * - **Prunable worktrees are EXCLUDED.** `prunable` means git itself has
119
- * flagged the worktree's directory as missing or otherwise administratively
120
- * invalid. Writing into that path would either fail or (via this
121
- * codebase's `mkdir(dir, { recursive: true })` write convention) silently
122
- * RECREATE a directory git considers gone — resurrecting a deleted
123
- * worktree's folder with governance files nobody asked for. Skipping it
124
- * is what "don't write into a directory git says isn't really there"
125
- * means in practice.
126
- * - **Bare-repository entries are EXCLUDED.** A bare repo's own `worktree`
127
- * porcelain entry names its root path but has no working tree of ordinary
128
- * files to write project-tier config into.
129
- *
130
- * Best-effort by design: returns `[]` (never throws) if `repoRoot` is not
131
- * inside a git repository, if `git` is not on `PATH`, or on any other
132
- * failure — this is additive coverage on top of the existing single-root
133
- * write path, so a git failure here must not break the sync cycle that
134
- * already succeeds for the main `workspaceRoot`. This also means a
135
- * non-worktree, single-checkout project (the common case) is a harmless
136
- * no-extra-work path: `git worktree list` still runs, still succeeds, and
137
- * returns exactly one entry (the main checkout itself).
138
- */
139
- export declare function discoverWorktrees(repoRoot: string): Promise<string[]>;
140
- //# sourceMappingURL=gitWorktrees.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gitWorktrees.d.ts","sourceRoot":"","sources":["../../src/lib/gitWorktrees.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAA;IACZ,4EAA4E;IAC5E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB;sCACkC;IAClC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAA;IACjB;;4CAEwC;IACxC,IAAI,EAAE,OAAO,CAAA;IACb;;;gEAG4D;IAC5D,MAAM,EAAE,OAAO,CAAA;IACf,oEAAoE;IACpE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B;oDACgD;IAChD,QAAQ,EAAE,OAAO,CAAA;IACjB,2EAA2E;IAC3E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAuDzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgB3E"}
@@ -1,191 +0,0 @@
1
- /**
2
- * gitWorktrees.ts — discovers every `git worktree` checkout of a repo the
3
- * sync daemon is watching, so project-tier governance files can be written
4
- * into each one, not just the main checkout.
5
- *
6
- * # The gap this closes
7
- *
8
- * `git worktree add <path>` creates a second, fully independent WORKING
9
- * TREE that shares the main checkout's `.git` object store (via a `.git`
10
- * FILE pointing back at `<main>/.git/worktrees/<name>`) but has its own
11
- * untracked files. Every project-tier governance file this product writes
12
- * — `.claude/settings.json`, `.cursor/hooks.json`, `.intutic/hooks/*`,
13
- * `AGENTS.md`'s sibling hook registrations, the wrapped `.mcp.json` entries,
14
- * etc. — is untracked by convention (SOP content is workspace-specific and
15
- * synced from the control plane, not committed). That means none of it
16
- * exists in a worktree's working tree by default: `writeConfigFiles`/
17
- * `injectMcpServer` running against only the main checkout's `workspaceRoot`
18
- * leaves every OTHER worktree of that same repo completely ungoverned,
19
- * regardless of what the main checkout has configured.
20
- *
21
- * This was already true for any hand-rolled `git worktree` workflow before
22
- * this module existed — Xirp (an orchestrator that spawns CLI agents each
23
- * inside its own tmux session + git worktree, see `tools/cli/src/harness/
24
- * xirp.ts`) is what surfaced it, but the fix here is general: it benefits
25
- * ANY worktree-based workflow, Xirp-managed or not. See TD-390.
26
- *
27
- * # Verifying the mechanics for real
28
- *
29
- * Confirmed against a real throwaway repo during this module's development
30
- * (not asserted from memory of git's docs): an untracked file written into
31
- * a main checkout is NOT visible from a `git worktree add`-created sibling
32
- * checkout's directory. `git worktree list --porcelain`'s block format,
33
- * including `locked`/`prunable`/`bare`/`detached` fields, was captured from
34
- * a real `git worktree list --porcelain` run (this module's own test suite
35
- * builds the same kind of fixture, in an isolated temp directory, rather
36
- * than relying on this description alone).
37
- *
38
- * @module
39
- */
40
- import { execFile as _execFile } from 'node:child_process';
41
- import { promisify } from 'node:util';
42
- const execFile = promisify(_execFile);
43
- /**
44
- * Parses `git worktree list --porcelain` output.
45
- *
46
- * Real format (verified against a live `git worktree list --porcelain` run,
47
- * git 2.x): one block per worktree, separated by a blank line, each line a
48
- * bare keyword or `<keyword> <value>`:
49
- *
50
- * ```
51
- * worktree /path/to/main
52
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
53
- * branch refs/heads/master
54
- *
55
- * worktree /path/to/locked-wt
56
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
57
- * branch refs/heads/feature2
58
- * locked testing lock
59
- *
60
- * worktree /path/to/detached-wt
61
- * HEAD 56bdba0a04f83da4e821a0a3e7a6208d43fcaec5
62
- * detached
63
- * ```
64
- *
65
- * Deliberately implemented with plain string methods (`startsWith`/`slice`)
66
- * rather than a line-matching regex — this parses `git`-controlled, not
67
- * attacker-controlled, input, but a sibling Wave 1 phase shipped a
68
- * CodeQL-flagged polynomial-regex bug from exactly this kind of "just trim
69
- * a path" text handling, so the same class of construct is avoided here on
70
- * principle even though the input source differs.
71
- */
72
- export function parseWorktreeListPorcelain(output) {
73
- const blocks = output.split('\n\n');
74
- const worktrees = [];
75
- for (const block of blocks) {
76
- const trimmedBlock = block.trim();
77
- if (!trimmedBlock)
78
- continue;
79
- let path = '';
80
- let head = null;
81
- let branch = null;
82
- let detached = false;
83
- let bare = false;
84
- let locked = false;
85
- let lockedReason = null;
86
- let prunable = false;
87
- let prunableReason = null;
88
- for (const rawLine of trimmedBlock.split('\n')) {
89
- const line = rawLine.trim();
90
- if (!line)
91
- continue;
92
- if (line === 'bare') {
93
- bare = true;
94
- }
95
- else if (line === 'detached') {
96
- detached = true;
97
- }
98
- else if (line.startsWith('worktree ')) {
99
- path = line.slice('worktree '.length).trim();
100
- }
101
- else if (line.startsWith('HEAD ')) {
102
- head = line.slice('HEAD '.length).trim();
103
- }
104
- else if (line.startsWith('branch ')) {
105
- branch = line.slice('branch '.length).trim();
106
- }
107
- else if (line === 'locked') {
108
- locked = true;
109
- }
110
- else if (line.startsWith('locked ')) {
111
- locked = true;
112
- lockedReason = line.slice('locked '.length).trim() || null;
113
- }
114
- else if (line === 'prunable') {
115
- prunable = true;
116
- }
117
- else if (line.startsWith('prunable ')) {
118
- prunable = true;
119
- prunableReason = line.slice('prunable '.length).trim() || null;
120
- }
121
- // Any other line is a porcelain field this parser does not know about
122
- // yet (git has added a few over the years) — ignored rather than
123
- // treated as an error, so a future git version adding a new field
124
- // degrades gracefully instead of breaking discovery entirely.
125
- }
126
- if (path) {
127
- worktrees.push({ path, head, branch, detached, bare, locked, lockedReason, prunable, prunableReason });
128
- }
129
- }
130
- return worktrees;
131
- }
132
- /**
133
- * Discovers every worktree of the git repository containing `repoRoot`,
134
- * returning the absolute paths that should be treated as additional
135
- * project-tier workspace roots.
136
- *
137
- * Filtering decisions, made explicit rather than left implicit:
138
- *
139
- * - **The main checkout is included.** `git worktree list` always lists it
140
- * first (confirmed against a live run) — it needs no special-casing by
141
- * callers; a caller that already writes to `repoRoot` directly can simply
142
- * skip a returned path equal to `repoRoot` if it wants to avoid a
143
- * redundant duplicate write, but the list is uniformly correct either way.
144
- * - **Locked worktrees are included.** `git worktree lock` only prevents
145
- * git's own pruning of a worktree it cannot otherwise verify still
146
- * exists (e.g. on removable storage) — it says nothing about whether the
147
- * directory is currently present and writable, which it normally is.
148
- * Excluding locked worktrees would silently under-cover a workflow (like
149
- * Xirp's) that locks worktrees deliberately to protect them from being
150
- * pruned out from under a long-running session — exactly the worktrees
151
- * most worth covering.
152
- * - **Prunable worktrees are EXCLUDED.** `prunable` means git itself has
153
- * flagged the worktree's directory as missing or otherwise administratively
154
- * invalid. Writing into that path would either fail or (via this
155
- * codebase's `mkdir(dir, { recursive: true })` write convention) silently
156
- * RECREATE a directory git considers gone — resurrecting a deleted
157
- * worktree's folder with governance files nobody asked for. Skipping it
158
- * is what "don't write into a directory git says isn't really there"
159
- * means in practice.
160
- * - **Bare-repository entries are EXCLUDED.** A bare repo's own `worktree`
161
- * porcelain entry names its root path but has no working tree of ordinary
162
- * files to write project-tier config into.
163
- *
164
- * Best-effort by design: returns `[]` (never throws) if `repoRoot` is not
165
- * inside a git repository, if `git` is not on `PATH`, or on any other
166
- * failure — this is additive coverage on top of the existing single-root
167
- * write path, so a git failure here must not break the sync cycle that
168
- * already succeeds for the main `workspaceRoot`. This also means a
169
- * non-worktree, single-checkout project (the common case) is a harmless
170
- * no-extra-work path: `git worktree list` still runs, still succeeds, and
171
- * returns exactly one entry (the main checkout itself).
172
- */
173
- export async function discoverWorktrees(repoRoot) {
174
- try {
175
- const { stdout } = await execFile('git', ['worktree', 'list', '--porcelain'], {
176
- cwd: repoRoot,
177
- encoding: 'utf-8',
178
- timeout: 5000,
179
- });
180
- return parseWorktreeListPorcelain(stdout)
181
- .filter((wt) => !wt.bare && !wt.prunable)
182
- .map((wt) => wt.path);
183
- }
184
- catch {
185
- // Not a git repo, git not installed, or a transient failure — additive
186
- // coverage, so this degrades to "no extra worktrees found", not a
187
- // thrown error the caller must handle.
188
- return [];
189
- }
190
- }
191
- //# sourceMappingURL=gitWorktrees.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gitWorktrees.js","sourceRoot":"","sources":["../../src/lib/gitWorktrees.ts"],"names":[],"mappings":"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"}