@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
@@ -16,7 +16,7 @@
16
16
  *
17
17
  * Opt-in via `WorkspaceSettings.decisionsLogEnabled` (default off). The
18
18
  * CALLER is responsible for that gate — `refreshDecisionsDigest` always
19
- * fetches and writes when invoked, so `syncLoop.ts` only calls it when the
19
+ * fetches and writes when invoked, so `intutic connect` only calls it when the
20
20
  * workspace has opted in. When disabled, the caller simply stops calling
21
21
  * this module; existing files are left as they were last written rather than
22
22
  * being force-deleted (a developer's editor may have that file open) or
@@ -29,13 +29,22 @@
29
29
  * pattern (i): a DO-NOT-EDIT header + `atomicWrite`. Gitignored — runtime
30
30
  * artifacts stay untracked, the same rule this repo's own CLAUDE.md doc
31
31
  * comment states for daemon-generated governance files.
32
- * 2. A bounded, marker-delimited section (last ~10 entries) idempotently
33
- * injected into the `claude-code` harness's own regenerated config file
34
- * (`HARNESS_FILES['claude-code']`, i.e. `CLAUDE.md`) — this is what makes
35
- * the digest something the agent actually reads without needing to know
36
- * `.intutic/DECISIONS.md` exists. A marker pair
37
- * (`INTUTIC:DECISIONS_LOG:START`/`END`) is replaced in place on every
38
- * cycle, never re-appended.
32
+ * 2. The newest ~10 entries, delivered to every active harness that reads
33
+ * an instructions file, where `HARNESS_RULES_FILES` says it reads them
34
+ * (`decisionsTargetOf`) — this is what makes the digest something the
35
+ * agent actually reads without needing to know `.intutic/DECISIONS.md`
36
+ * exists. In a file the user also writes (`AGENTS.md`, `GEMINI.md`,
37
+ * ...) it is a marked section of its own (`INTUTIC:DECISIONS_LOG`),
38
+ * apart from the rules section; next to a rules file of Intutic's own it
39
+ * is a second file (`.claude/rules/intutic-decisions.md`, ...). Claude
40
+ * Code gets it from `.claude/rules/`, which it loads with or without a
41
+ * `CLAUDE.md`; `CLAUDE.md` itself is never written. When Claude Code
42
+ * also reads the workspace's `AGENTS.md` and that file carries the
43
+ * section for another harness, Claude Code's own file is left out, so it
44
+ * does not read the log twice (see `claudeAgentsMd.ts`).
45
+ *
46
+ * Earlier versions put the section in `CLAUDE.md`; {@link
47
+ * retireClaudeMdDigest} takes it out again on every sync.
39
48
  *
40
49
  * Deliberately does NOT reuse `configWriter.ts`'s own `fileHeader()` for the
41
50
  * DECISIONS.md header — that helper stamps `newIso()` (wall-clock "Last
@@ -49,13 +58,18 @@
49
58
  import * as fs from 'node:fs/promises';
50
59
  import * as path from 'node:path';
51
60
  import { createLogger } from '@intutic/logger';
52
- import { HarnessType } from '@intutic/shared-types';
53
- import { HARNESS_FILES, atomicWrite } from '../configWriter.js';
61
+ import { HarnessType, decisionsTargetOf, rulesFileOf } from '@intutic/shared-types';
62
+ import { atomicWrite } from '../configWriter.js';
63
+ import { DECISIONS_MARKERS, removeRulesSection, retireRulesFile, writeRulesSection } from '../harness/rulesSection.js';
64
+ import { claudeCodeReadsAgentsMd } from '../harness/claudeAgentsMd.js';
65
+ import { openclawAgentWorkspace } from '../harness/openclawHooks.js';
66
+ import { ensureAiderReadEntry } from '../harness/aiderConfigMerger.js';
67
+ import { forgetOriginal, readOriginal, writeOwnedFile } from '../disconnect/originals.js';
54
68
  const log = createLogger('sync-decisions-digest');
55
69
  /** Relative to the workspace root. */
56
70
  export const DECISIONS_LOG_RELATIVE_PATH = path.join('.intutic', 'DECISIONS.md');
57
- const SECTION_START = '<!-- INTUTIC:DECISIONS_LOG:START -->';
58
- const SECTION_END = '<!-- INTUTIC:DECISIONS_LOG:END -->';
71
+ /** First line of the decisions log's own files, which `intutic disconnect` recognises. */
72
+ export const DECISIONS_FILE_HEADER = '# Intutic Governed Decisions Log (auto-generated)';
59
73
  /**
60
74
  * Trims trailing `/` without a regex — see the identical helper in
61
75
  * `egressPolicy.ts`/`approvedBypasses.ts`: `/\/+$/` is flagged by CodeQL as a
@@ -131,29 +145,93 @@ export function renderDecisionsMarkdown(entries) {
131
145
  const lines = entries.map((e) => `- ${e.timestamp} — ${e.summary}`);
132
146
  return header + lines.join('\n') + '\n';
133
147
  }
134
- /** Renders the bounded, marker-delimited section injected into the harness config file — the newest `limit` entries only. */
135
- export function renderBoundedSection(entries, limit = 10) {
148
+ /** The newest `limit` entries, as the body of the section or file each harness reads. */
149
+ export function renderDecisionsSectionBody(entries, limit = 10) {
136
150
  const bounded = entries.slice(0, limit);
137
151
  const lines = bounded.length > 0
138
152
  ? bounded.map((e) => `- ${e.timestamp} — ${e.summary}`)
139
153
  : ['_No governance decisions recorded yet._'];
140
- return [SECTION_START, '## Recent Governed Decisions', '', ...lines, SECTION_END].join('\n');
154
+ return ['## Recent Governed Decisions', '', ...lines].join('\n');
155
+ }
156
+ /** A harness's decisions file: the product's front matter, the header, the entries. */
157
+ function renderDecisionsFile(body, frontMatter) {
158
+ const head = frontMatter ? `---\n${frontMatter}\n---\n\n` : '';
159
+ return `${head}${DECISIONS_FILE_HEADER}\n# DO NOT EDIT — managed by intutic sync daemon\n\n${body}\n`;
160
+ }
161
+ async function readText(file) {
162
+ try {
163
+ return await fs.readFile(file, 'utf-8');
164
+ }
165
+ catch {
166
+ return null;
167
+ }
141
168
  }
142
169
  /**
143
- * Idempotently inject/replace the bounded section in `content`. If the
144
- * markers are present, everything between them (inclusive) is replaced — the
145
- * mechanism the `applyConfigEdits` SkillOpt writer already uses elsewhere in
146
- * this file's sibling module, `configWriter.ts` — never duplicated. If
147
- * absent, the section is appended once, with a separating blank line.
170
+ * Writes `body` wherever each of `harnesses` reads its instructions, once per
171
+ * file. Claude Code's own file is left out (and removed) when Claude Code
172
+ * reads the workspace's `AGENTS.md` and that file gets the section for
173
+ * another harness.
148
174
  */
149
- export function injectBoundedSection(content, section) {
150
- const startIdx = content.indexOf(SECTION_START);
151
- const endIdx = content.indexOf(SECTION_END);
152
- if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
153
- return content.slice(0, startIdx) + section + content.slice(endIdx + SECTION_END.length);
175
+ export async function writeDecisionsTargets(workspaceRoot, harnesses, body) {
176
+ const claudeFromAgentsMd = harnesses.includes(HarnessType.CLAUDE_CODE) &&
177
+ harnesses.some((h) => rulesFileOf(h) === 'AGENTS.md') &&
178
+ (await claudeCodeReadsAgentsMd(workspaceRoot));
179
+ const written = new Set();
180
+ for (const harness of harnesses) {
181
+ const target = decisionsTargetOf(harness);
182
+ if (!target)
183
+ continue;
184
+ const file = target.kind === 'section' && target.scope === 'user'
185
+ ? path.join(await openclawAgentWorkspace(), 'AGENTS.md')
186
+ : path.join(workspaceRoot, target.path);
187
+ if (harness === HarnessType.CLAUDE_CODE && claudeFromAgentsMd) {
188
+ await retireRulesFile(file, workspaceRoot);
189
+ continue;
190
+ }
191
+ if (written.has(file))
192
+ continue;
193
+ written.add(file);
194
+ if (target.kind === 'section') {
195
+ await writeRulesSection(file, workspaceRoot, body, DECISIONS_MARKERS);
196
+ continue;
197
+ }
198
+ const content = renderDecisionsFile(body, target.frontMatter?.('Intutic governed decisions log') ?? '');
199
+ if ((await readText(file)) !== content)
200
+ await writeOwnedFile(file, workspaceRoot, content);
201
+ // Aider loads no file it is not told about.
202
+ if (harness === HarnessType.AIDER)
203
+ await ensureAiderReadEntry(path.join(workspaceRoot, '.aider.conf.yml'), file);
154
204
  }
155
- const sep = content.endsWith('\n\n') ? '' : content.endsWith('\n') ? '\n' : '\n\n';
156
- return `${content}${sep}${section}\n`;
205
+ }
206
+ /**
207
+ * Takes out the decisions-log section earlier versions wrote into the
208
+ * workspace's `CLAUDE.md`, leaving the user's text as it was. A `CLAUDE.md`
209
+ * Intutic created that holds nothing else goes, with its record; one an
210
+ * earlier version wrote whole is given back (`retireRulesFile`). Runs on
211
+ * every sync, whether or not the decisions log is on.
212
+ */
213
+ export async function retireClaudeMdDigest(workspaceRoot) {
214
+ const file = path.join(workspaceRoot, 'CLAUDE.md');
215
+ const text = await readText(file);
216
+ if (text === null)
217
+ return;
218
+ const next = removeRulesSection(text, DECISIONS_MARKERS);
219
+ if (next !== null) {
220
+ const record = await readOriginal(file, workspaceRoot);
221
+ if (next.trim() === '' && record && !record.existed) {
222
+ await fs.rm(file, { force: true });
223
+ await forgetOriginal(file, workspaceRoot);
224
+ log.info({ action: 'decisions_claude_md_removed', path: file }, 'Removed the CLAUDE.md an earlier version created for the decisions log');
225
+ return;
226
+ }
227
+ const mode = (await fs.stat(file)).mode & 0o7777;
228
+ const tmp = `${file}.intutic-tmp`;
229
+ await fs.writeFile(tmp, next, 'utf-8');
230
+ await fs.chmod(tmp, mode);
231
+ await fs.rename(tmp, file);
232
+ log.info({ action: 'decisions_claude_md_section_removed', path: file }, 'Took the decisions-log section out of CLAUDE.md');
233
+ }
234
+ await retireRulesFile(file, workspaceRoot);
157
235
  }
158
236
  /**
159
237
  * Fetch and write both files in one call, mirroring `refreshEgressPolicy`.
@@ -169,26 +247,7 @@ export async function refreshDecisionsDigest(opts) {
169
247
  try {
170
248
  const fullPath = path.join(opts.workspaceRoot, DECISIONS_LOG_RELATIVE_PATH);
171
249
  await atomicWrite(fullPath, renderDecisionsMarkdown(digest.entries));
172
- if (opts.harnesses.includes(HarnessType.CLAUDE_CODE)) {
173
- const claudeMdPath = path.join(opts.workspaceRoot, HARNESS_FILES[HarnessType.CLAUDE_CODE]);
174
- let existing = null;
175
- try {
176
- existing = await fs.readFile(claudeMdPath, 'utf-8');
177
- }
178
- catch {
179
- existing = null;
180
- }
181
- if (existing !== null) {
182
- const section = renderBoundedSection(digest.entries, 10);
183
- const updated = injectBoundedSection(existing, section);
184
- if (updated !== existing) {
185
- await atomicWrite(claudeMdPath, updated);
186
- }
187
- }
188
- else {
189
- log.debug({ action: 'decisions_digest_skip_inject' }, 'claude-code config file not written yet this run — skipping bounded-section injection this cycle');
190
- }
191
- }
250
+ await writeDecisionsTargets(opts.workspaceRoot, opts.harnesses, renderDecisionsSectionBody(digest.entries, 10));
192
251
  return { entriesWritten: digest.entries.length };
193
252
  }
194
253
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"decisionsDigest.js","sourceRoot":"","sources":["../../src/lib/decisionsDigest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"decisionsDigest.js","sourceRoot":"","sources":["../../src/lib/decisionsDigest.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * egressPolicy.ts — ships the workspace's central egress policy *to* the
3
3
  * machine, so an admin sets `enforce`/`monitor` + an allow list once in the
4
- * control plane rather than in every developer's local proxy config
5
- * (LLD #63 §4). Mirrors `policySnapshot.ts` / `approvedBypasses.ts`: fetch from
4
+ * control plane rather than in every developer's local proxy config.
5
+ * Mirrors `policySnapshot.ts` / `approvedBypasses.ts`: fetch from
6
6
  * the control plane, write a local artifact under `.intutic/hooks` with
7
7
  * integrity headers, and let the consumer (here the Rust proxy) read it.
8
8
  *
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * egressPolicy.ts — ships the workspace's central egress policy *to* the
3
3
  * machine, so an admin sets `enforce`/`monitor` + an allow list once in the
4
- * control plane rather than in every developer's local proxy config
5
- * (LLD #63 §4). Mirrors `policySnapshot.ts` / `approvedBypasses.ts`: fetch from
4
+ * control plane rather than in every developer's local proxy config.
5
+ * Mirrors `policySnapshot.ts` / `approvedBypasses.ts`: fetch from
6
6
  * the control plane, write a local artifact under `.intutic/hooks` with
7
7
  * integrity headers, and let the consumer (here the Rust proxy) read it.
8
8
  *
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The MCP server registry and allowlist decisions in Python, for the bash
3
+ * gates (their extractor already requires python3).
4
+ *
5
+ * Byte-identical to `packages/intutic-clawde/intutic_clawde/gate/mcp_registry.py`,
6
+ * which a test compares; edit that file and copy it here. It is the
7
+ * transliteration of `@intutic/shared-types`'s mcpRegistryRecord.ts, and both
8
+ * run the shared vectors.
9
+ */
10
+ export declare const MCP_REGISTRY_PY_SOURCE: string;
11
+ //# sourceMappingURL=mcpRegistryPy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpRegistryPy.d.ts","sourceRoot":"","sources":["../../src/lib/mcpRegistryPy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,QAkKlC,CAAA"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The MCP server registry and allowlist decisions in Python, for the bash
3
+ * gates (their extractor already requires python3).
4
+ *
5
+ * Byte-identical to `packages/intutic-clawde/intutic_clawde/gate/mcp_registry.py`,
6
+ * which a test compares; edit that file and copy it here. It is the
7
+ * transliteration of `@intutic/shared-types`'s mcpRegistryRecord.ts, and both
8
+ * run the shared vectors.
9
+ */
10
+ export const MCP_REGISTRY_PY_SOURCE = String.raw `"""The MCP server registry and allowlist decisions, read from the policy snapshot.
11
+
12
+ A transliteration of packages/shared-types/src/mcpRegistryRecord.ts: the
13
+ registry decision (evaluateMcpRegistry), the allowlist decision
14
+ (evaluateMcpAllowlist), and the snapshot's @mcp_registry and @mcp_allowlist
15
+ records. The control plane's hook gate, the MCP proxy and the JavaScript hook
16
+ gates run the TypeScript; the bash hook gates and this package run this file,
17
+ and every one of them runs packages/shared-types/fixtures/mcp-registry-vectors.json,
18
+ so all of them refuse a call with the same code, rule id and reason.
19
+
20
+ The bash gates emit this file verbatim (services/sync-daemon/src/lib/mcpRegistryPy.ts
21
+ holds a byte-identical copy, which a test compares). It must stay
22
+ self-contained: the standard library only, no module state beyond the
23
+ constants below, and no backtick or dollar-brace, which the TypeScript copy
24
+ cannot hold.
25
+
26
+ Both records sit inside the snapshot's digest. A gate that finds the snapshot
27
+ unverified (its digest broken or missing, or another workspace's) trusts
28
+ neither: it refuses every MCP call with unverified_refusal, at block, in an
29
+ observe-only workspace too.
30
+ """
31
+
32
+ import base64
33
+ import json
34
+
35
+ MCP_REGISTRY_RECORD_TAG = "@mcp_registry"
36
+ MCP_ALLOWLIST_RECORD_TAG = "@mcp_allowlist"
37
+
38
+
39
+ def split_mcp_tool_name(tool):
40
+ """(server, tool) for a harness name mcp__<server>__<tool>, else None.
41
+
42
+ The server is the part before the first double underscore; the tool, the
43
+ rest, may hold more of them.
44
+ """
45
+ if not isinstance(tool, str) or not tool.startswith("mcp__"):
46
+ return None
47
+ rest = tool[len("mcp__"):]
48
+ sep = rest.find("__")
49
+ if sep <= 0:
50
+ return None
51
+ return rest[:sep], rest[sep + 2:]
52
+
53
+
54
+ def _strings(value):
55
+ return [v for v in value if isinstance(v, str)] if isinstance(value, list) else []
56
+
57
+
58
+ def parse_registry(value):
59
+ """The registry as the control plane sends it, or None for a non-object.
60
+
61
+ Wrong-typed lists read as empty, and any default but deny as allow.
62
+ """
63
+ if not isinstance(value, dict):
64
+ return None
65
+ disabled = {}
66
+ if isinstance(value.get("disabledTools"), dict):
67
+ for server, tools in value["disabledTools"].items():
68
+ names = _strings(tools)
69
+ if names:
70
+ disabled[server] = names
71
+ return {
72
+ "defaultPolicy": "deny" if value.get("defaultPolicy") == "deny" else "allow",
73
+ "approvedServers": _strings(value.get("approvedServers")),
74
+ "blockedServers": _strings(value.get("blockedServers")),
75
+ "heldServers": _strings(value.get("heldServers")),
76
+ "disabledTools": disabled,
77
+ }
78
+
79
+
80
+ def decode_registry_record(line):
81
+ """The @mcp_registry line's registry; None for another line or a damaged one."""
82
+ parts = line.split("\t")
83
+ if len(parts) != 2 or parts[0] != MCP_REGISTRY_RECORD_TAG or not parts[1]:
84
+ return None
85
+ try:
86
+ return parse_registry(json.loads(base64.b64decode(parts[1], validate=True).decode("utf-8")))
87
+ except Exception:
88
+ return None
89
+
90
+
91
+ def evaluate_registry(registry, server, tool):
92
+ """(code, rule_id, reason) refusing one MCP call, or None to let it continue.
93
+
94
+ A blocked server, then a held one, then (under deny) one not approved,
95
+ then a disabled tool.
96
+ """
97
+ if server in registry["blockedServers"]:
98
+ return (
99
+ "SERVER_BLOCKED",
100
+ "mcp_registry." + server,
101
+ "MCP server \"" + server + "\" is blocked in this workspace's MCP server registry. "
102
+ "An owner or admin can change that on the MCP Servers page.",
103
+ )
104
+ if server in registry["heldServers"]:
105
+ return (
106
+ "SERVER_HELD",
107
+ "mcp_registry." + server,
108
+ "MCP server \"" + server + "\" changed its tools in a way scored high risk, and this workspace "
109
+ "holds such a server until it is approved again. It is waiting in the approval queue on the MCP "
110
+ "Servers page for an owner or admin.",
111
+ )
112
+ if registry["defaultPolicy"] == "deny" and server not in registry["approvedServers"]:
113
+ return (
114
+ "SERVER_NOT_APPROVED",
115
+ "mcpDefaultPolicy",
116
+ "MCP server \"" + server + "\" is not approved in this workspace's MCP server registry, "
117
+ "and the workspace refuses unapproved servers (mcpDefaultPolicy: deny). It is waiting in "
118
+ "the approval queue on the MCP Servers page for an owner or admin.",
119
+ )
120
+ if tool in registry["disabledTools"].get(server, []):
121
+ return (
122
+ "TOOL_DISABLED",
123
+ "mcp_registry." + server + "." + tool,
124
+ "Tool \"" + tool + "\" is disabled on MCP server \"" + server + "\" in this workspace's "
125
+ "MCP server registry. An owner or admin can re-enable it on the MCP Servers page.",
126
+ )
127
+ return None
128
+
129
+
130
+ def decode_allowlist_record(line):
131
+ """The @mcp_allowlist line as {"severity", "servers"}; None for another line.
132
+
133
+ A severity other than shadow reads as block, so a damaged one refuses.
134
+ """
135
+ parts = line.split("\t")
136
+ if len(parts) != 3 or parts[0] != MCP_ALLOWLIST_RECORD_TAG:
137
+ return None
138
+ return {
139
+ "severity": "shadow" if parts[1] == "shadow" else "block",
140
+ "servers": [s for s in parts[2].split(",") if s],
141
+ }
142
+
143
+
144
+ def evaluate_allowlist(allowlist, server):
145
+ """(code, rule_id, reason) for a server the allowlist does not name, else None.
146
+
147
+ Under shadow the caller records the refusal instead of enforcing it.
148
+ """
149
+ if server in allowlist["servers"]:
150
+ return None
151
+ return (
152
+ "SERVER_NOT_ALLOWED",
153
+ "mcp_allowlist",
154
+ "MCP server \"" + server + "\" is not on the MCP server allowlist for this workspace",
155
+ )
156
+
157
+
158
+ def unverified_refusal(server):
159
+ """(code, rule_id, reason) refusing an MCP call on an unverified snapshot.
160
+
161
+ Neither the registry's approvals nor the allowlist's servers can be
162
+ vouched for, and a deleted record looks like one never set, so the
163
+ snapshot admits no MCP server at all.
164
+ """
165
+ return (
166
+ "POLICY_SNAPSHOT_UNVERIFIED",
167
+ "policy_snapshot",
168
+ "MCP server \"" + server + "\" is refused because the policy snapshot on this machine failed its "
169
+ "integrity check, so its MCP server registry and allowlist admit no server until the sync daemon "
170
+ "restores a verified snapshot",
171
+ )
172
+ `;
173
+ //# sourceMappingURL=mcpRegistryPy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpRegistryPy.js","sourceRoot":"","sources":["../../src/lib/mcpRegistryPy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkK/C,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The phrase matcher in Python, for the gates that run Python: the bash gates
3
+ * (their extractor already requires python3) and the Open WebUI filter.
4
+ *
5
+ * Byte-identical to `packages/intutic-clawde/intutic_clawde/gate/phrases.py`,
6
+ * which a test compares; edit that file and copy it here. It is the
7
+ * transliteration of `@intutic/shared-types`'s phrases.ts, and both run the
8
+ * shared vectors.
9
+ */
10
+ export declare const PHRASES_PY_SOURCE: string;
11
+ //# sourceMappingURL=phrasesPy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phrasesPy.d.ts","sourceRoot":"","sources":["../../src/lib/phrasesPy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,QAoV7B,CAAA"}