@intutic/sync-daemon 2.0.0 → 2.2.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 (206) hide show
  1. package/dist/agentReporter.d.ts +5 -12
  2. package/dist/agentReporter.d.ts.map +1 -1
  3. package/dist/agentReporter.js +25 -4
  4. package/dist/agentReporter.js.map +1 -1
  5. package/dist/configReader.d.ts +44 -22
  6. package/dist/configReader.d.ts.map +1 -1
  7. package/dist/configReader.js +70 -44
  8. package/dist/configReader.js.map +1 -1
  9. package/dist/configWriter.d.ts +29 -41
  10. package/dist/configWriter.d.ts.map +1 -1
  11. package/dist/configWriter.js +28 -625
  12. package/dist/configWriter.js.map +1 -1
  13. package/dist/disconnect/harnesses.d.ts +31 -0
  14. package/dist/disconnect/harnesses.d.ts.map +1 -0
  15. package/dist/disconnect/harnesses.js +728 -0
  16. package/dist/disconnect/harnesses.js.map +1 -0
  17. package/dist/disconnect/index.d.ts +25 -0
  18. package/dist/disconnect/index.d.ts.map +1 -0
  19. package/dist/disconnect/index.js +82 -0
  20. package/dist/disconnect/index.js.map +1 -0
  21. package/dist/disconnect/mcp.d.ts +60 -0
  22. package/dist/disconnect/mcp.d.ts.map +1 -0
  23. package/dist/disconnect/mcp.js +283 -0
  24. package/dist/disconnect/mcp.js.map +1 -0
  25. package/dist/disconnect/originals.d.ts +88 -0
  26. package/dist/disconnect/originals.d.ts.map +1 -0
  27. package/dist/disconnect/originals.js +257 -0
  28. package/dist/disconnect/originals.js.map +1 -0
  29. package/dist/disconnect/plan.d.ts +175 -0
  30. package/dist/disconnect/plan.d.ts.map +1 -0
  31. package/dist/disconnect/plan.js +580 -0
  32. package/dist/disconnect/plan.js.map +1 -0
  33. package/dist/disconnect/recognise.d.ts +43 -0
  34. package/dist/disconnect/recognise.d.ts.map +1 -0
  35. package/dist/disconnect/recognise.js +98 -0
  36. package/dist/disconnect/recognise.js.map +1 -0
  37. package/dist/disconnect/tomlLines.d.ts +39 -0
  38. package/dist/disconnect/tomlLines.d.ts.map +1 -0
  39. package/dist/disconnect/tomlLines.js +105 -0
  40. package/dist/disconnect/tomlLines.js.map +1 -0
  41. package/dist/harness/aiderConfigMerger.d.ts +42 -5
  42. package/dist/harness/aiderConfigMerger.d.ts.map +1 -1
  43. package/dist/harness/aiderConfigMerger.js +113 -86
  44. package/dist/harness/aiderConfigMerger.js.map +1 -1
  45. package/dist/harness/antigravityHooks.d.ts +13 -8
  46. package/dist/harness/antigravityHooks.d.ts.map +1 -1
  47. package/dist/harness/antigravityHooks.js +53 -39
  48. package/dist/harness/antigravityHooks.js.map +1 -1
  49. package/dist/harness/claudeCodeHooks.d.ts +1 -2
  50. package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
  51. package/dist/harness/claudeCodeHooks.js +61 -34
  52. package/dist/harness/claudeCodeHooks.js.map +1 -1
  53. package/dist/harness/claudeDesktopHooks.d.ts +3 -0
  54. package/dist/harness/claudeDesktopHooks.d.ts.map +1 -1
  55. package/dist/harness/claudeDesktopHooks.js +3 -1
  56. package/dist/harness/claudeDesktopHooks.js.map +1 -1
  57. package/dist/harness/claudeProjectApproval.d.ts +53 -0
  58. package/dist/harness/claudeProjectApproval.d.ts.map +1 -0
  59. package/dist/harness/claudeProjectApproval.js +159 -0
  60. package/dist/harness/claudeProjectApproval.js.map +1 -0
  61. package/dist/harness/clineHooks.d.ts +39 -9
  62. package/dist/harness/clineHooks.d.ts.map +1 -1
  63. package/dist/harness/clineHooks.js +142 -60
  64. package/dist/harness/clineHooks.js.map +1 -1
  65. package/dist/harness/codexConfigMerger.d.ts +38 -0
  66. package/dist/harness/codexConfigMerger.d.ts.map +1 -0
  67. package/dist/harness/codexConfigMerger.js +105 -0
  68. package/dist/harness/codexConfigMerger.js.map +1 -0
  69. package/dist/harness/codexHooks.d.ts +4 -2
  70. package/dist/harness/codexHooks.d.ts.map +1 -1
  71. package/dist/harness/codexHooks.js +14 -11
  72. package/dist/harness/codexHooks.js.map +1 -1
  73. package/dist/harness/continueConfigMerger.d.ts +46 -0
  74. package/dist/harness/continueConfigMerger.d.ts.map +1 -0
  75. package/dist/harness/continueConfigMerger.js +94 -0
  76. package/dist/harness/continueConfigMerger.js.map +1 -0
  77. package/dist/harness/continueHooks.d.ts +15 -25
  78. package/dist/harness/continueHooks.d.ts.map +1 -1
  79. package/dist/harness/continueHooks.js +25 -119
  80. package/dist/harness/continueHooks.js.map +1 -1
  81. package/dist/harness/cursorHooks.d.ts +33 -16
  82. package/dist/harness/cursorHooks.d.ts.map +1 -1
  83. package/dist/harness/cursorHooks.js +69 -25
  84. package/dist/harness/cursorHooks.js.map +1 -1
  85. package/dist/harness/dshHooks.d.ts +59 -52
  86. package/dist/harness/dshHooks.d.ts.map +1 -1
  87. package/dist/harness/dshHooks.js +152 -147
  88. package/dist/harness/dshHooks.js.map +1 -1
  89. package/dist/harness/gateBody.d.ts +11 -2
  90. package/dist/harness/gateBody.d.ts.map +1 -1
  91. package/dist/harness/gateBody.js +33 -6
  92. package/dist/harness/gateBody.js.map +1 -1
  93. package/dist/harness/gateKind.d.ts.map +1 -1
  94. package/dist/harness/gateKind.js +1 -0
  95. package/dist/harness/gateKind.js.map +1 -1
  96. package/dist/harness/githubCopilotHooks.d.ts.map +1 -1
  97. package/dist/harness/githubCopilotHooks.js +5 -10
  98. package/dist/harness/githubCopilotHooks.js.map +1 -1
  99. package/dist/harness/gooseHooks.d.ts +15 -0
  100. package/dist/harness/gooseHooks.d.ts.map +1 -1
  101. package/dist/harness/gooseHooks.js +55 -43
  102. package/dist/harness/gooseHooks.js.map +1 -1
  103. package/dist/harness/grokHooks.d.ts.map +1 -1
  104. package/dist/harness/grokHooks.js +14 -12
  105. package/dist/harness/grokHooks.js.map +1 -1
  106. package/dist/harness/hermesHooks.d.ts +9 -0
  107. package/dist/harness/hermesHooks.d.ts.map +1 -1
  108. package/dist/harness/hermesHooks.js +39 -33
  109. package/dist/harness/hermesHooks.js.map +1 -1
  110. package/dist/harness/holdRedaction.d.ts +4 -1
  111. package/dist/harness/holdRedaction.d.ts.map +1 -1
  112. package/dist/harness/holdRedaction.js +32 -8
  113. package/dist/harness/holdRedaction.js.map +1 -1
  114. package/dist/harness/jetbrainsXmlConfig.d.ts +20 -0
  115. package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -1
  116. package/dist/harness/jetbrainsXmlConfig.js +39 -18
  117. package/dist/harness/jetbrainsXmlConfig.js.map +1 -1
  118. package/dist/harness/jsonMergeTarget.d.ts +23 -0
  119. package/dist/harness/jsonMergeTarget.d.ts.map +1 -0
  120. package/dist/harness/jsonMergeTarget.js +50 -0
  121. package/dist/harness/jsonMergeTarget.js.map +1 -0
  122. package/dist/harness/mcpAutoWrite.d.ts +64 -20
  123. package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
  124. package/dist/harness/mcpAutoWrite.js +429 -85
  125. package/dist/harness/mcpAutoWrite.js.map +1 -1
  126. package/dist/harness/museHooks.d.ts.map +1 -1
  127. package/dist/harness/museHooks.js +6 -2
  128. package/dist/harness/museHooks.js.map +1 -1
  129. package/dist/harness/n8nHooks.d.ts.map +1 -1
  130. package/dist/harness/n8nHooks.js +6 -7
  131. package/dist/harness/n8nHooks.js.map +1 -1
  132. package/dist/harness/openCodeHooks.d.ts +37 -6
  133. package/dist/harness/openCodeHooks.d.ts.map +1 -1
  134. package/dist/harness/openCodeHooks.js +103 -13
  135. package/dist/harness/openCodeHooks.js.map +1 -1
  136. package/dist/harness/openWebuiHooks.d.ts.map +1 -1
  137. package/dist/harness/openWebuiHooks.js +10 -5
  138. package/dist/harness/openWebuiHooks.js.map +1 -1
  139. package/dist/harness/openclawHooks.d.ts +5 -0
  140. package/dist/harness/openclawHooks.d.ts.map +1 -1
  141. package/dist/harness/openclawHooks.js +3 -1
  142. package/dist/harness/openclawHooks.js.map +1 -1
  143. package/dist/harness/openhandsHooks.d.ts +26 -1
  144. package/dist/harness/openhandsHooks.d.ts.map +1 -1
  145. package/dist/harness/openhandsHooks.js +160 -40
  146. package/dist/harness/openhandsHooks.js.map +1 -1
  147. package/dist/harness/piHooks.d.ts +17 -0
  148. package/dist/harness/piHooks.d.ts.map +1 -1
  149. package/dist/harness/piHooks.js +31 -29
  150. package/dist/harness/piHooks.js.map +1 -1
  151. package/dist/harness/protectedPaths.d.ts +64 -6
  152. package/dist/harness/protectedPaths.d.ts.map +1 -1
  153. package/dist/harness/protectedPaths.js +161 -11
  154. package/dist/harness/protectedPaths.js.map +1 -1
  155. package/dist/harness/rooCodeHooks.d.ts.map +1 -1
  156. package/dist/harness/rooCodeHooks.js +5 -10
  157. package/dist/harness/rooCodeHooks.js.map +1 -1
  158. package/dist/harness/windsurfHooks.d.ts +21 -3
  159. package/dist/harness/windsurfHooks.d.ts.map +1 -1
  160. package/dist/harness/windsurfHooks.js +96 -44
  161. package/dist/harness/windsurfHooks.js.map +1 -1
  162. package/dist/harness/windsurfJetBrainsProxy.d.ts +10 -7
  163. package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -1
  164. package/dist/harness/windsurfJetBrainsProxy.js +22 -7
  165. package/dist/harness/windsurfJetBrainsProxy.js.map +1 -1
  166. package/dist/index.d.ts +12 -12
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +11 -10
  169. package/dist/index.js.map +1 -1
  170. package/dist/lib/decisionsDigest.d.ts +1 -1
  171. package/dist/lib/decisionsDigest.js +1 -1
  172. package/dist/lib/policySnapshot.d.ts +37 -0
  173. package/dist/lib/policySnapshot.d.ts.map +1 -1
  174. package/dist/lib/policySnapshot.js +170 -8
  175. package/dist/lib/policySnapshot.js.map +1 -1
  176. package/dist/sessionReporter.d.ts +2 -2
  177. package/dist/sessionReporter.js +2 -2
  178. package/dist/syncCycle.d.ts +142 -0
  179. package/dist/syncCycle.d.ts.map +1 -0
  180. package/dist/syncCycle.js +315 -0
  181. package/dist/syncCycle.js.map +1 -0
  182. package/dist/trajectoryMonitor.d.ts +1 -1
  183. package/dist/trajectoryMonitor.d.ts.map +1 -1
  184. package/dist/trajectoryMonitor.js +1 -1
  185. package/dist/trajectoryMonitor.js.map +1 -1
  186. package/dist/watcher/settingsGuard.d.ts +4 -1
  187. package/dist/watcher/settingsGuard.d.ts.map +1 -1
  188. package/dist/watcher/settingsGuard.js +42 -18
  189. package/dist/watcher/settingsGuard.js.map +1 -1
  190. package/package.json +6 -6
  191. package/dist/hashReporter.d.ts +0 -33
  192. package/dist/hashReporter.d.ts.map +0 -1
  193. package/dist/hashReporter.js +0 -69
  194. package/dist/hashReporter.js.map +0 -1
  195. package/dist/integrityStore.d.ts +0 -35
  196. package/dist/integrityStore.d.ts.map +0 -1
  197. package/dist/integrityStore.js +0 -71
  198. package/dist/integrityStore.js.map +0 -1
  199. package/dist/lib/gitWorktrees.d.ts +0 -140
  200. package/dist/lib/gitWorktrees.d.ts.map +0 -1
  201. package/dist/lib/gitWorktrees.js +0 -191
  202. package/dist/lib/gitWorktrees.js.map +0 -1
  203. package/dist/syncLoop.d.ts +0 -172
  204. package/dist/syncLoop.d.ts.map +0 -1
  205. package/dist/syncLoop.js +0 -878
  206. package/dist/syncLoop.js.map +0 -1
@@ -0,0 +1,98 @@
1
+ /**
2
+ * recognise.ts — how disconnect tells Intutic's entries from the user's.
3
+ *
4
+ * Every test here is on content Intutic writes and nothing else: a hook
5
+ * command that runs a gate script from an `.intutic/hooks/` directory, a
6
+ * rules file that starts with the generated header, a URL on the origin of
7
+ * the proxy connect pointed the harness at.
8
+ *
9
+ * @module
10
+ */
11
+ import * as node_fs from 'node:fs/promises';
12
+ import * as node_path from 'node:path';
13
+ import { proxyHost } from '@intutic/shared-types';
14
+ import { isObject } from './plan.js';
15
+ /** First line of every rules file Intutic generates. */
16
+ export const RULES_HEADER = '# Intutic Governance Rules (auto-generated)';
17
+ export function startsWithRulesHeader(text) {
18
+ return text.startsWith(RULES_HEADER);
19
+ }
20
+ /** Whether `text` mentions `marker`, for owned files recognised by a line Intutic writes in them. */
21
+ export function contains(marker) {
22
+ return (text) => text.includes(marker);
23
+ }
24
+ /**
25
+ * Whether `command` runs the gate script `script` from an `.intutic/hooks/`
26
+ * directory (any workspace's, or the home one) — however it is quoted or
27
+ * whichever interpreter runs it.
28
+ */
29
+ export function runsGate(command, script) {
30
+ if (typeof command !== 'string')
31
+ return false;
32
+ const escaped = script.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
33
+ return new RegExp(`[\\\\/]\\.intutic[\\\\/]hooks[\\\\/]${escaped}(?=["'\\s]|$)`).test(command);
34
+ }
35
+ /**
36
+ * Whether a `{ matcher, hooks: [{ command }] }` entry is Intutic's: every
37
+ * hook in it runs `script`. The shape Claude Code, Codex, Continue, Muse,
38
+ * Gemini CLI, Pi and Claude Desktop share.
39
+ */
40
+ export function isGateEntry(script) {
41
+ return (entry) => {
42
+ if (!isObject(entry) || !Array.isArray(entry.hooks) || entry.hooks.length === 0)
43
+ return false;
44
+ return entry.hooks.every((h) => isObject(h) && runsGate(h.command, script));
45
+ };
46
+ }
47
+ /** Whether a `{ command }` entry (Cursor, Windsurf, Roo) runs `script`. */
48
+ export function isGateCommandEntry(script) {
49
+ return (entry) => isObject(entry) && runsGate(entry.command, script);
50
+ }
51
+ /** Loopback hosts compare equal: connect writes `localhost` in one place and `127.0.0.1` in another. */
52
+ function originOf(value) {
53
+ try {
54
+ const url = new URL(value);
55
+ const host = url.hostname === 'localhost' || url.hostname === '[::1]' ? '127.0.0.1' : url.hostname;
56
+ const port = url.port || (url.protocol === 'https:' ? '443' : '80');
57
+ return `${url.protocol}//${host}:${port}`;
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /**
64
+ * A test for "this value is a URL on the Intutic proxy", given the proxy
65
+ * URLs connect is known to have written. Any path on the proxy's origin
66
+ * counts: connect writes the bare host for Anthropic SDKs, `/v1` for OpenAI
67
+ * ones, and a trailing slash for Continue.
68
+ */
69
+ export function proxyUrlMatcher(proxyUrls) {
70
+ const origins = new Set(proxyUrls.map((u) => originOf(proxyHost(u))).filter((o) => o !== null));
71
+ return (value) => typeof value === 'string' && origins.size > 0 && origins.has(originOf(value) ?? '');
72
+ }
73
+ /**
74
+ * Proxy URLs an earlier connect left in a workspace's own generated files:
75
+ * the "Proxy URL" line of a rules file and `INTUTIC_PROXY_URL` in
76
+ * `.env.intutic`. Used when connect predates the recorded list.
77
+ */
78
+ export async function proxyUrlsInWorkspace(workspaceRoot) {
79
+ const found = new Set();
80
+ const files = ['CLAUDE.md', '.cursorrules', '.windsurfrules', 'AGENTS.md', '.github/copilot-instructions.md', '.env.intutic'];
81
+ for (const rel of files) {
82
+ let text;
83
+ try {
84
+ text = await node_fs.readFile(node_path.join(workspaceRoot, rel), 'utf-8');
85
+ }
86
+ catch {
87
+ continue;
88
+ }
89
+ if (!startsWithRulesHeader(text))
90
+ continue;
91
+ for (const m of text.matchAll(/^> \*\*Proxy URL:\*\* `([^`]+)`$/gm))
92
+ found.add(m[1]);
93
+ for (const m of text.matchAll(/^export INTUTIC_PROXY_URL="([^"]+)"$/gm))
94
+ found.add(m[1]);
95
+ }
96
+ return [...found];
97
+ }
98
+ //# sourceMappingURL=recognise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recognise.js","sourceRoot":"","sources":["../../src/disconnect/recognise.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * tomlLines.ts — line-level TOML edits that keep the user's comments.
3
+ *
4
+ * Codex's and OpenHands' writers set a key or append a table by editing
5
+ * lines, so the user's comments survive; undoing them the same way keeps
6
+ * that promise. Only the shapes those writers produce are handled: a
7
+ * `key = value` line in the top level or in a `[table]`, and a whole table.
8
+ *
9
+ * @module
10
+ */
11
+ interface Section {
12
+ /** Table name as written between the brackets, or null for the top level. */
13
+ name: string | null;
14
+ /** Index of the header line (-1 for the top level). */
15
+ header: number;
16
+ /** One past the last line of the section. */
17
+ end: number;
18
+ }
19
+ /** Splits lines into sections, ignoring `[` lines inside multi-line strings. */
20
+ export declare function tomlSections(lines: readonly string[]): Section[];
21
+ /** The value a one-line `key = value` assignment holds, or undefined when the line is not one. */
22
+ export declare function lineValue(line: string, key: string): unknown;
23
+ /** Index of `key`'s line in the first section named `table` (null: top level), or -1. */
24
+ export declare function findKeyLine(lines: readonly string[], table: string | null, key: string): number;
25
+ /**
26
+ * Removes the table named `table`, header to end, with the blank line a
27
+ * writer put before it when it appended the table.
28
+ */
29
+ export declare function removeTable(lines: string[], table: string): boolean;
30
+ /** Removes a `[table]` header with nothing left under it but blank lines. */
31
+ export declare function removeEmptyTable(lines: string[], table: string): boolean;
32
+ /**
33
+ * Puts back one key a writer set. When the original text had the key in
34
+ * the same section its line is restored; otherwise the line is removed.
35
+ * Only a line whose value `isIntutic` recognises is touched.
36
+ */
37
+ export declare function restoreKeyLine(lines: string[], table: string | null, key: string, originalLines: readonly string[] | null, isIntutic: (value: unknown) => boolean): boolean;
38
+ export {};
39
+ //# sourceMappingURL=tomlLines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tomlLines.d.ts","sourceRoot":"","sources":["../../src/disconnect/tomlLines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,UAAU,OAAO;IACf,6EAA6E;IAC7E,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,EAAE,CAuBhE;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5D;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO/F;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOnE;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKxE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,EACvC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,GACrC,OAAO,CAWT"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * tomlLines.ts — line-level TOML edits that keep the user's comments.
3
+ *
4
+ * Codex's and OpenHands' writers set a key or append a table by editing
5
+ * lines, so the user's comments survive; undoing them the same way keeps
6
+ * that promise. Only the shapes those writers produce are handled: a
7
+ * `key = value` line in the top level or in a `[table]`, and a whole table.
8
+ *
9
+ * @module
10
+ */
11
+ import { parse as parseToml } from 'smol-toml';
12
+ /** Splits lines into sections, ignoring `[` lines inside multi-line strings. */
13
+ export function tomlSections(lines) {
14
+ const sections = [{ name: null, header: -1, end: lines.length }];
15
+ let inString = null;
16
+ lines.forEach((line, i) => {
17
+ if (inString === null) {
18
+ // `[table]` or `[[array.of.tables]]`; the name is what is between the brackets.
19
+ const header = /^\s*\[\[?\s*([^\][]+?)\s*\]\]?\s*(#.*)?$/.exec(line);
20
+ if (header) {
21
+ sections[sections.length - 1].end = i;
22
+ sections.push({ name: header[1], header: i, end: lines.length });
23
+ return;
24
+ }
25
+ }
26
+ for (const quote of ['"""', "'''"]) {
27
+ let at = line.indexOf(quote);
28
+ while (at !== -1) {
29
+ if (inString === null)
30
+ inString = quote;
31
+ else if (inString === quote)
32
+ inString = null;
33
+ at = line.indexOf(quote, at + 3);
34
+ }
35
+ }
36
+ });
37
+ return sections;
38
+ }
39
+ /** The value a one-line `key = value` assignment holds, or undefined when the line is not one. */
40
+ export function lineValue(line, key) {
41
+ if (!new RegExp(`^\\s*${key}\\s*=`).test(line))
42
+ return undefined;
43
+ try {
44
+ return parseToml(line)[key];
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ /** Index of `key`'s line in the first section named `table` (null: top level), or -1. */
51
+ export function findKeyLine(lines, table, key) {
52
+ const section = tomlSections(lines).find((s) => s.name === table);
53
+ if (!section)
54
+ return -1;
55
+ for (let i = section.header + 1; i < section.end; i++) {
56
+ if (lineValue(lines[i], key) !== undefined)
57
+ return i;
58
+ }
59
+ return -1;
60
+ }
61
+ /**
62
+ * Removes the table named `table`, header to end, with the blank line a
63
+ * writer put before it when it appended the table.
64
+ */
65
+ export function removeTable(lines, table) {
66
+ const section = tomlSections(lines).find((s) => s.name === table);
67
+ if (!section)
68
+ return false;
69
+ let start = section.header;
70
+ if (start > 0 && lines[start - 1].trim() === '')
71
+ start--;
72
+ lines.splice(start, section.end - start);
73
+ return true;
74
+ }
75
+ /** Removes a `[table]` header with nothing left under it but blank lines. */
76
+ export function removeEmptyTable(lines, table) {
77
+ const section = tomlSections(lines).find((s) => s.name === table);
78
+ if (!section)
79
+ return false;
80
+ for (let i = section.header + 1; i < section.end; i++)
81
+ if (lines[i].trim() !== '')
82
+ return false;
83
+ return removeTable(lines, table);
84
+ }
85
+ /**
86
+ * Puts back one key a writer set. When the original text had the key in
87
+ * the same section its line is restored; otherwise the line is removed.
88
+ * Only a line whose value `isIntutic` recognises is touched.
89
+ */
90
+ export function restoreKeyLine(lines, table, key, originalLines, isIntutic) {
91
+ const at = findKeyLine(lines, table, key);
92
+ if (at === -1 || !isIntutic(lineValue(lines[at], key)))
93
+ return false;
94
+ const was = originalLines ? findKeyLine(originalLines, table, key) : -1;
95
+ if (was !== -1) {
96
+ if (lines[at] === originalLines[was])
97
+ return false;
98
+ lines[at] = originalLines[was];
99
+ }
100
+ else {
101
+ lines.splice(at, 1);
102
+ }
103
+ return true;
104
+ }
105
+ //# sourceMappingURL=tomlLines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tomlLines.js","sourceRoot":"","sources":["../../src/disconnect/tomlLines.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,26 @@
2
2
  * aiderConfigMerger.ts — Safe YAML merge for .aider.conf.yml.
3
3
  *
4
4
  * Reads any existing .aider.conf.yml, STRIPS dangerous auto-exec keys
5
- * (test-cmd, lint-cmd, auto-test, auto-lint), merges in Intutic governance
6
- * keys (openai-api-base, anthropic-api-base), and writes back atomically.
5
+ * (test-cmd, lint-cmd, auto-test, auto-lint), merges in the Intutic proxy
6
+ * routing, and writes back atomically. Everything else in the file — lists,
7
+ * nested values, comments — is kept: the file is edited through the `yaml`
8
+ * library's document model, never re-serialised from a flattened copy.
9
+ *
10
+ * Aider rejects any config key that is not one of its command-line options
11
+ * ("unrecognized arguments"), so only real options are written:
12
+ *
13
+ * - `openai-api-base` — the proxy's OpenAI-style base URL (host + `/v1`).
14
+ * - `set-env: ANTHROPIC_BASE_URL=<host>` — Aider has no Anthropic base-URL
15
+ * option; its model layer (LiteLLM) reads this variable, and wants the bare
16
+ * host because it appends `/v1/messages` itself. Entries the user set for
17
+ * other variables are kept.
18
+ * - `read: .intutic/aider-sops.md` — the SOP text, as a read-only context
19
+ * file (Aider's own mechanism for conventions), written next to the config.
20
+ *
21
+ * Earlier versions wrote `anthropic-api-base` and `extra-instructions`, which
22
+ * are not Aider options and stopped Aider from starting; both are removed.
23
+ *
24
+ * A file that does not parse as YAML, or is not a mapping, is left untouched.
7
25
  *
8
26
  * Each strip emits a governance_config_sanitized log entry visible in
9
27
  * the control plane audit feed.
@@ -13,15 +31,34 @@
13
31
  *
14
32
  * @module
15
33
  */
34
+ /** SOP file, relative to the workspace root (where Aider runs). */
35
+ export declare const AIDER_SOPS_FILE = ".intutic/aider-sops.md";
36
+ export declare function stripOwnHeader(raw: string): string;
37
+ /** Result of merging the Intutic keys into an Aider config's text. */
38
+ export interface AiderMergeResult {
39
+ /** New file content, or `null` when the file must be left untouched. */
40
+ content: string | null;
41
+ /** Suppressed keys that were removed. */
42
+ stripped: string[];
43
+ }
44
+ /**
45
+ * Merge the Intutic keys into the text of an `.aider.conf.yml`.
46
+ *
47
+ * @param raw - Current file content ('' when the file does not exist).
48
+ * @param proxyUrl - The proxy host (a trailing `/v1` is tolerated).
49
+ * @param hasSops - Whether the SOP file is to be listed under `read`.
50
+ */
51
+ export declare function mergeAiderYaml(raw: string, proxyUrl: string, hasSops: boolean): AiderMergeResult;
16
52
  /**
17
53
  * Merge Intutic governance settings into .aider.conf.yml.
18
54
  *
19
55
  * Preserves all user keys EXCEPT the suppressed auto-exec keys.
20
- * Adds/updates openai-api-base and anthropic-api-base.
21
56
  *
22
57
  * @param configPath - Absolute path to .aider.conf.yml
23
58
  * @param proxyUrl - Intutic proxy URL
24
- * @param sopsText - Optional SOP instructions for extra-instructions field
59
+ * @param sopsText - Optional SOP instructions, written to the `read` file
60
+ * @returns `true` when the config was written, `false` when it was left
61
+ * untouched because it is not a YAML mapping (a warning is logged).
25
62
  */
26
- export declare function mergeAiderConfig(configPath: string, proxyUrl: string, sopsText?: string): Promise<void>;
63
+ export declare function mergeAiderConfig(configPath: string, proxyUrl: string, sopsText?: string): Promise<boolean>;
27
64
  //# sourceMappingURL=aiderConfigMerger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aiderConfigMerger.d.ts","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA0EH;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAmDf"}
1
+ {"version":3,"file":"aiderConfigMerger.d.ts","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAoBH,mEAAmE;AACnE,eAAO,MAAM,eAAe,2BAA2B,CAAA;AAcvD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAYD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB,CA2BhG;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CA8ClB"}
@@ -2,8 +2,26 @@
2
2
  * aiderConfigMerger.ts — Safe YAML merge for .aider.conf.yml.
3
3
  *
4
4
  * Reads any existing .aider.conf.yml, STRIPS dangerous auto-exec keys
5
- * (test-cmd, lint-cmd, auto-test, auto-lint), merges in Intutic governance
6
- * keys (openai-api-base, anthropic-api-base), and writes back atomically.
5
+ * (test-cmd, lint-cmd, auto-test, auto-lint), merges in the Intutic proxy
6
+ * routing, and writes back atomically. Everything else in the file — lists,
7
+ * nested values, comments — is kept: the file is edited through the `yaml`
8
+ * library's document model, never re-serialised from a flattened copy.
9
+ *
10
+ * Aider rejects any config key that is not one of its command-line options
11
+ * ("unrecognized arguments"), so only real options are written:
12
+ *
13
+ * - `openai-api-base` — the proxy's OpenAI-style base URL (host + `/v1`).
14
+ * - `set-env: ANTHROPIC_BASE_URL=<host>` — Aider has no Anthropic base-URL
15
+ * option; its model layer (LiteLLM) reads this variable, and wants the bare
16
+ * host because it appends `/v1/messages` itself. Entries the user set for
17
+ * other variables are kept.
18
+ * - `read: .intutic/aider-sops.md` — the SOP text, as a read-only context
19
+ * file (Aider's own mechanism for conventions), written next to the config.
20
+ *
21
+ * Earlier versions wrote `anthropic-api-base` and `extra-instructions`, which
22
+ * are not Aider options and stopped Aider from starting; both are removed.
23
+ *
24
+ * A file that does not parse as YAML, or is not a mapping, is left untouched.
7
25
  *
8
26
  * Each strip emits a governance_config_sanitized log entry visible in
9
27
  * the control plane audit feed.
@@ -15,125 +33,134 @@
15
33
  */
16
34
  import * as fs from 'node:fs/promises';
17
35
  import * as path from 'node:path';
36
+ import { parseDocument, isMap, isSeq, isScalar, YAMLSeq } from 'yaml';
18
37
  import { createLogger } from '@intutic/logger';
19
- import { newIso } from '@intutic/id';
38
+ import { keepOriginal } from '../disconnect/originals.js';
39
+ import { anthropicBaseUrl, openaiBaseUrl } from '@intutic/shared-types';
20
40
  const log = createLogger('sync-aider-merger');
21
41
  /**
22
42
  * Keys that Aider auto-executes on startup without user confirmation.
23
43
  * Stripping these prevents supply-chain persistence attacks.
24
44
  */
25
45
  const SUPPRESSED_KEYS = ['test-cmd', 'lint-cmd', 'auto-test', 'auto-lint', 'test_cmd', 'lint_cmd'];
26
- /**
27
- * Minimal YAML parser for .aider.conf.yml — handles simple key: value lines
28
- * and multi-line strings. Does not handle complex YAML. Good enough for the
29
- * flat structure of .aider.conf.yml.
30
- */
31
- function parseAiderYaml(raw) {
32
- const result = {};
46
+ /** Keys earlier versions wrote that Aider rejects as unrecognized arguments. */
47
+ const INVALID_LEGACY_KEYS = ['anthropic-api-base', 'extra-instructions'];
48
+ /** SOP file, relative to the workspace root (where Aider runs). */
49
+ export const AIDER_SOPS_FILE = '.intutic/aider-sops.md';
50
+ /** Header written at the top of the file. Kept short: it sits above the
51
+ * user's own content, and is replaced, not stacked, on every sync. */
52
+ const HEADER = [
53
+ '# Intutic: openai-api-base, the ANTHROPIC_BASE_URL set-env entry and the',
54
+ `# ${AIDER_SOPS_FILE} read entry are managed by intutic connect. test-cmd,`,
55
+ '# lint-cmd, auto-test and auto-lint are removed on every sync.',
56
+ ];
57
+ /** Leading lines this product wrote (the header above, or the one earlier
58
+ * versions wrote), removed before the file is parsed. */
59
+ const OWN_HEADER_LINE = /^# (Intutic: |Intutic Governance Rules \(auto-generated|Last sync: |WARNING: test-cmd and lint-cmd keys are suppressed|\.intutic\/aider-sops\.md read entry|lint-cmd, auto-test and auto-lint are removed)/;
60
+ export function stripOwnHeader(raw) {
33
61
  const lines = raw.split('\n');
34
62
  let i = 0;
35
- while (i < lines.length) {
36
- const line = lines[i];
37
- // Skip comments and blank lines
38
- if (!line || line.trim().startsWith('#')) {
39
- i++;
40
- continue;
41
- }
42
- const colonIdx = line.indexOf(':');
43
- if (colonIdx === -1) {
44
- i++;
45
- continue;
46
- }
47
- const key = line.slice(0, colonIdx).trim();
48
- const rest = line.slice(colonIdx + 1).trim();
49
- if (rest === '|' || rest === '>') {
50
- // Multi-line block scalar — collect until next key or EOF
51
- const blockLines = [];
52
- i++;
53
- while (i < lines.length && (lines[i].startsWith(' ') || lines[i] === '')) {
54
- blockLines.push(lines[i].startsWith(' ') ? lines[i].slice(2) : '');
55
- i++;
56
- }
57
- result[key] = blockLines.join('\n').trimEnd();
58
- }
59
- else {
60
- // Strip inline quotes
61
- result[key] = rest.replace(/^["']|["']$/g, '');
62
- i++;
63
- }
64
- }
65
- return result;
63
+ while (i < lines.length && OWN_HEADER_LINE.test(lines[i]))
64
+ i++;
65
+ if (i === 0)
66
+ return raw;
67
+ while (i < lines.length && lines[i].trim() === '')
68
+ i++;
69
+ return lines.slice(i).join('\n');
70
+ }
71
+ /** Turn `key`'s value into a sequence (a scalar becomes a one-item list). */
72
+ function ensureSeq(doc, key) {
73
+ const current = doc.get(key, true);
74
+ if (isSeq(current))
75
+ return current;
76
+ const seq = new YAMLSeq();
77
+ if (isScalar(current) && current.value !== null && current.value !== '')
78
+ seq.add(current.value);
79
+ doc.set(key, seq);
80
+ return seq;
66
81
  }
67
82
  /**
68
- * Minimal YAML serializer — writes flat key: value pairs.
69
- * Multi-line values use the | block scalar style.
83
+ * Merge the Intutic keys into the text of an `.aider.conf.yml`.
84
+ *
85
+ * @param raw - Current file content ('' when the file does not exist).
86
+ * @param proxyUrl - The proxy host (a trailing `/v1` is tolerated).
87
+ * @param hasSops - Whether the SOP file is to be listed under `read`.
70
88
  */
71
- function serializeAiderYaml(obj) {
72
- const lines = [];
73
- for (const [key, value] of Object.entries(obj)) {
74
- if (typeof value === 'string' && value.includes('\n')) {
75
- lines.push(`${key}: |`);
76
- for (const ln of value.split('\n')) {
77
- lines.push(` ${ln}`);
78
- }
79
- }
80
- else if (typeof value === 'boolean') {
81
- lines.push(`${key}: ${value}`);
82
- }
83
- else {
84
- lines.push(`${key}: ${String(value)}`);
85
- }
86
- }
87
- return lines.join('\n');
89
+ export function mergeAiderYaml(raw, proxyUrl, hasSops) {
90
+ const doc = parseDocument(stripOwnHeader(raw));
91
+ if (doc.errors.length > 0)
92
+ return { content: null, stripped: [] };
93
+ // A missing, empty or comment-only file starts as an empty mapping (its
94
+ // comments stay on the document); anything else that is not a mapping (a
95
+ // list, a bare scalar) is not an Aider config to merge into.
96
+ if (doc.contents === null)
97
+ doc.contents = doc.createNode({});
98
+ if (!isMap(doc.contents))
99
+ return { content: null, stripped: [] };
100
+ const stripped = SUPPRESSED_KEYS.filter((key) => doc.has(key));
101
+ for (const key of [...stripped, ...INVALID_LEGACY_KEYS])
102
+ doc.delete(key);
103
+ doc.set('openai-api-base', openaiBaseUrl(proxyUrl));
104
+ const setEnv = ensureSeq(doc, 'set-env');
105
+ setEnv.items = setEnv.items.filter((item) => {
106
+ const value = isScalar(item) ? item.value : item;
107
+ return !(typeof value === 'string' && value.startsWith('ANTHROPIC_BASE_URL='));
108
+ });
109
+ setEnv.add(`ANTHROPIC_BASE_URL=${anthropicBaseUrl(proxyUrl)}`);
110
+ const read = ensureSeq(doc, 'read');
111
+ read.items = read.items.filter((item) => (isScalar(item) ? item.value : item) !== AIDER_SOPS_FILE);
112
+ if (hasSops)
113
+ read.add(AIDER_SOPS_FILE);
114
+ if (read.items.length === 0)
115
+ doc.delete('read');
116
+ return { content: `${HEADER.join('\n')}\n\n${doc.toString()}`, stripped };
88
117
  }
89
118
  /**
90
119
  * Merge Intutic governance settings into .aider.conf.yml.
91
120
  *
92
121
  * Preserves all user keys EXCEPT the suppressed auto-exec keys.
93
- * Adds/updates openai-api-base and anthropic-api-base.
94
122
  *
95
123
  * @param configPath - Absolute path to .aider.conf.yml
96
124
  * @param proxyUrl - Intutic proxy URL
97
- * @param sopsText - Optional SOP instructions for extra-instructions field
125
+ * @param sopsText - Optional SOP instructions, written to the `read` file
126
+ * @returns `true` when the config was written, `false` when it was left
127
+ * untouched because it is not a YAML mapping (a warning is logged).
98
128
  */
99
129
  export async function mergeAiderConfig(configPath, proxyUrl, sopsText) {
100
- // Read existing config if present
101
- let existing = {};
130
+ let raw = '';
102
131
  try {
103
- const raw = await fs.readFile(configPath, 'utf-8');
104
- existing = parseAiderYaml(raw);
132
+ raw = await fs.readFile(configPath, 'utf-8');
105
133
  }
106
- catch {
107
- // No existing file — start fresh
134
+ catch (err) {
135
+ if (err.code !== 'ENOENT')
136
+ throw err;
108
137
  }
109
- // Strip dangerous auto-exec keys
110
- const stripped = [];
111
- for (const key of SUPPRESSED_KEYS) {
112
- if (key in existing) {
113
- stripped.push(key);
114
- delete existing[key];
115
- }
138
+ const { content, stripped } = mergeAiderYaml(raw, proxyUrl, Boolean(sopsText));
139
+ if (content === null) {
140
+ log.warn({ action: 'aider_config_merge_skipped', path: configPath }, `${configPath} is not a YAML mapping — left untouched; fix it and the next sync will add the Intutic keys`);
141
+ return false;
116
142
  }
117
143
  if (stripped.length > 0) {
118
144
  log.warn({ action: 'aider_keys_stripped', keys: stripped, path: configPath }, `Stripped dangerous auto-exec keys from .aider.conf.yml: ${stripped.join(', ')}`);
119
145
  }
120
- // Merge governance keys
121
- existing['openai-api-base'] = proxyUrl;
122
- existing['anthropic-api-base'] = proxyUrl;
146
+ // The SOP file lives next to the config, under the workspace's .intutic/.
147
+ const sopsPath = path.join(path.dirname(configPath), AIDER_SOPS_FILE);
123
148
  if (sopsText) {
124
- existing['extra-instructions'] = sopsText;
149
+ await fs.mkdir(path.dirname(sopsPath), { recursive: true });
150
+ const tmpSops = sopsPath + '.intutic-tmp';
151
+ await fs.writeFile(tmpSops, sopsText + '\n', 'utf-8');
152
+ await fs.rename(tmpSops, sopsPath);
153
+ }
154
+ else {
155
+ await fs.rm(sopsPath, { force: true });
125
156
  }
126
- const header = [
127
- '# Intutic Governance Rules (auto-generated — do not edit proxy keys)',
128
- `# Last sync: ${newIso()}`,
129
- `# WARNING: test-cmd and lint-cmd keys are suppressed by Intutic governance`,
130
- '',
131
- ].join('\n');
132
- const content = header + serializeAiderYaml(existing) + '\n';
133
157
  const tmpPath = configPath + '.intutic-tmp';
158
+ // The config sits at the workspace root, so its directory is the workspace.
159
+ await keepOriginal(configPath, path.dirname(configPath));
134
160
  await fs.mkdir(path.dirname(configPath), { recursive: true });
135
161
  await fs.writeFile(tmpPath, content, 'utf-8');
136
162
  await fs.rename(tmpPath, configPath);
137
163
  log.info({ action: 'aider_config_written', path: configPath, stripped }, 'Aider config merged with proxy URL and dangerous keys stripped');
164
+ return true;
138
165
  }
139
166
  //# sourceMappingURL=aiderConfigMerger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aiderConfigMerger.js","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aiderConfigMerger.js","sourceRoot":"","sources":["../../src/harness/aiderConfigMerger.ts"],"names":[],"mappings":"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"}