@intutic/sync-daemon 1.10.0 → 1.10.1

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 (200) hide show
  1. package/README.md +2 -2
  2. package/dist/agentReporter.d.ts +205 -0
  3. package/dist/agentReporter.d.ts.map +1 -0
  4. package/dist/agentReporter.js +394 -0
  5. package/dist/agentReporter.js.map +1 -0
  6. package/dist/configReader.d.ts +39 -2
  7. package/dist/configReader.d.ts.map +1 -1
  8. package/dist/configReader.js +56 -2
  9. package/dist/configReader.js.map +1 -1
  10. package/dist/configWriter.d.ts +51 -1
  11. package/dist/configWriter.d.ts.map +1 -1
  12. package/dist/configWriter.js +490 -63
  13. package/dist/configWriter.js.map +1 -1
  14. package/dist/harness/antigravityHooks.d.ts.map +1 -1
  15. package/dist/harness/antigravityHooks.js +33 -55
  16. package/dist/harness/antigravityHooks.js.map +1 -1
  17. package/dist/harness/claudeCodeHooks.d.ts +47 -13
  18. package/dist/harness/claudeCodeHooks.d.ts.map +1 -1
  19. package/dist/harness/claudeCodeHooks.js +316 -54
  20. package/dist/harness/claudeCodeHooks.js.map +1 -1
  21. package/dist/harness/claudeDesktopHooks.d.ts.map +1 -1
  22. package/dist/harness/claudeDesktopHooks.js +35 -48
  23. package/dist/harness/claudeDesktopHooks.js.map +1 -1
  24. package/dist/harness/clineHooks.d.ts.map +1 -1
  25. package/dist/harness/clineHooks.js +42 -34
  26. package/dist/harness/clineHooks.js.map +1 -1
  27. package/dist/harness/codexHooks.d.ts +36 -0
  28. package/dist/harness/codexHooks.d.ts.map +1 -0
  29. package/dist/harness/codexHooks.js +227 -0
  30. package/dist/harness/codexHooks.js.map +1 -0
  31. package/dist/harness/continueHooks.d.ts +45 -5
  32. package/dist/harness/continueHooks.d.ts.map +1 -1
  33. package/dist/harness/continueHooks.js +225 -5
  34. package/dist/harness/continueHooks.js.map +1 -1
  35. package/dist/harness/cursorHooks.d.ts +31 -0
  36. package/dist/harness/cursorHooks.d.ts.map +1 -1
  37. package/dist/harness/cursorHooks.js +78 -49
  38. package/dist/harness/cursorHooks.js.map +1 -1
  39. package/dist/harness/dshHooks.d.ts +198 -0
  40. package/dist/harness/dshHooks.d.ts.map +1 -0
  41. package/dist/harness/dshHooks.js +569 -0
  42. package/dist/harness/dshHooks.js.map +1 -0
  43. package/dist/harness/gateBody.d.ts +422 -0
  44. package/dist/harness/gateBody.d.ts.map +1 -0
  45. package/dist/harness/gateBody.js +1816 -0
  46. package/dist/harness/gateBody.js.map +1 -0
  47. package/dist/harness/gateKind.d.ts +164 -0
  48. package/dist/harness/gateKind.d.ts.map +1 -0
  49. package/dist/harness/gateKind.js +143 -0
  50. package/dist/harness/gateKind.js.map +1 -0
  51. package/dist/harness/githubCopilotHooks.d.ts +54 -0
  52. package/dist/harness/githubCopilotHooks.d.ts.map +1 -0
  53. package/dist/harness/githubCopilotHooks.js +218 -0
  54. package/dist/harness/githubCopilotHooks.js.map +1 -0
  55. package/dist/harness/gooseHooks.d.ts.map +1 -1
  56. package/dist/harness/gooseHooks.js +67 -37
  57. package/dist/harness/gooseHooks.js.map +1 -1
  58. package/dist/harness/grokHooks.d.ts +77 -0
  59. package/dist/harness/grokHooks.d.ts.map +1 -0
  60. package/dist/harness/grokHooks.js +350 -0
  61. package/dist/harness/grokHooks.js.map +1 -0
  62. package/dist/harness/hermesHooks.d.ts.map +1 -1
  63. package/dist/harness/hermesHooks.js +26 -55
  64. package/dist/harness/hermesHooks.js.map +1 -1
  65. package/dist/harness/holdRedaction.d.ts +69 -0
  66. package/dist/harness/holdRedaction.d.ts.map +1 -0
  67. package/dist/harness/holdRedaction.js +211 -0
  68. package/dist/harness/holdRedaction.js.map +1 -0
  69. package/dist/harness/jetbrainsXmlConfig.d.ts +51 -0
  70. package/dist/harness/jetbrainsXmlConfig.d.ts.map +1 -0
  71. package/dist/harness/jetbrainsXmlConfig.js +151 -0
  72. package/dist/harness/jetbrainsXmlConfig.js.map +1 -0
  73. package/dist/harness/mcpAutoWrite.d.ts +100 -3
  74. package/dist/harness/mcpAutoWrite.d.ts.map +1 -1
  75. package/dist/harness/mcpAutoWrite.js +712 -90
  76. package/dist/harness/mcpAutoWrite.js.map +1 -1
  77. package/dist/harness/museHooks.d.ts +53 -0
  78. package/dist/harness/museHooks.d.ts.map +1 -0
  79. package/dist/harness/museHooks.js +273 -0
  80. package/dist/harness/museHooks.js.map +1 -0
  81. package/dist/harness/n8nHooks.d.ts +25 -9
  82. package/dist/harness/n8nHooks.d.ts.map +1 -1
  83. package/dist/harness/n8nHooks.js +174 -9
  84. package/dist/harness/n8nHooks.js.map +1 -1
  85. package/dist/harness/openCodeHooks.d.ts +93 -0
  86. package/dist/harness/openCodeHooks.d.ts.map +1 -0
  87. package/dist/harness/openCodeHooks.js +248 -0
  88. package/dist/harness/openCodeHooks.js.map +1 -0
  89. package/dist/harness/openWebuiHooks.d.ts.map +1 -1
  90. package/dist/harness/openWebuiHooks.js +56 -11
  91. package/dist/harness/openWebuiHooks.js.map +1 -1
  92. package/dist/harness/openclawHooks.d.ts.map +1 -1
  93. package/dist/harness/openclawHooks.js +30 -54
  94. package/dist/harness/openclawHooks.js.map +1 -1
  95. package/dist/harness/openhandsHooks.d.ts.map +1 -1
  96. package/dist/harness/openhandsHooks.js +35 -41
  97. package/dist/harness/openhandsHooks.js.map +1 -1
  98. package/dist/harness/piHooks.d.ts.map +1 -1
  99. package/dist/harness/piHooks.js +31 -58
  100. package/dist/harness/piHooks.js.map +1 -1
  101. package/dist/harness/protectedPaths.d.ts +353 -0
  102. package/dist/harness/protectedPaths.d.ts.map +1 -0
  103. package/dist/harness/protectedPaths.js +805 -0
  104. package/dist/harness/protectedPaths.js.map +1 -0
  105. package/dist/harness/rooCodeHooks.d.ts.map +1 -1
  106. package/dist/harness/rooCodeHooks.js +34 -48
  107. package/dist/harness/rooCodeHooks.js.map +1 -1
  108. package/dist/harness/windsurfHooks.d.ts +72 -0
  109. package/dist/harness/windsurfHooks.d.ts.map +1 -1
  110. package/dist/harness/windsurfHooks.js +172 -58
  111. package/dist/harness/windsurfHooks.js.map +1 -1
  112. package/dist/harness/windsurfJetBrainsProxy.d.ts +78 -0
  113. package/dist/harness/windsurfJetBrainsProxy.d.ts.map +1 -0
  114. package/dist/harness/windsurfJetBrainsProxy.js +159 -0
  115. package/dist/harness/windsurfJetBrainsProxy.js.map +1 -0
  116. package/dist/hashReporter.js +1 -1
  117. package/dist/hashReporter.js.map +1 -1
  118. package/dist/index.d.ts +12 -6
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +14 -6
  121. package/dist/index.js.map +1 -1
  122. package/dist/integrityStore.d.ts +0 -8
  123. package/dist/integrityStore.d.ts.map +1 -1
  124. package/dist/integrityStore.js +6 -29
  125. package/dist/integrityStore.js.map +1 -1
  126. package/dist/lib/approvedBypasses.d.ts +76 -0
  127. package/dist/lib/approvedBypasses.d.ts.map +1 -0
  128. package/dist/lib/approvedBypasses.js +140 -0
  129. package/dist/lib/approvedBypasses.js.map +1 -0
  130. package/dist/lib/complianceProbes.d.ts.map +1 -1
  131. package/dist/lib/complianceProbes.js +5 -0
  132. package/dist/lib/complianceProbes.js.map +1 -1
  133. package/dist/lib/decisionsDigest.d.ts +99 -0
  134. package/dist/lib/decisionsDigest.d.ts.map +1 -0
  135. package/dist/lib/decisionsDigest.js +199 -0
  136. package/dist/lib/decisionsDigest.js.map +1 -0
  137. package/dist/lib/egressPolicy.d.ts +69 -0
  138. package/dist/lib/egressPolicy.d.ts.map +1 -0
  139. package/dist/lib/egressPolicy.js +126 -0
  140. package/dist/lib/egressPolicy.js.map +1 -0
  141. package/dist/lib/gitWorktrees.d.ts +140 -0
  142. package/dist/lib/gitWorktrees.d.ts.map +1 -0
  143. package/dist/lib/gitWorktrees.js +191 -0
  144. package/dist/lib/gitWorktrees.js.map +1 -0
  145. package/dist/lib/policySnapshot.d.ts +224 -0
  146. package/dist/lib/policySnapshot.d.ts.map +1 -0
  147. package/dist/lib/policySnapshot.js +637 -0
  148. package/dist/lib/policySnapshot.js.map +1 -0
  149. package/dist/lib/processPoller.d.ts +44 -0
  150. package/dist/lib/processPoller.d.ts.map +1 -1
  151. package/dist/lib/processPoller.js +176 -1
  152. package/dist/lib/processPoller.js.map +1 -1
  153. package/dist/lib/runtimeEnv.d.ts +8 -0
  154. package/dist/lib/runtimeEnv.d.ts.map +1 -1
  155. package/dist/lib/runtimeEnv.js +3 -0
  156. package/dist/lib/runtimeEnv.js.map +1 -1
  157. package/dist/localTrajectoryHeuristics.d.ts +51 -0
  158. package/dist/localTrajectoryHeuristics.d.ts.map +1 -0
  159. package/dist/localTrajectoryHeuristics.js +90 -0
  160. package/dist/localTrajectoryHeuristics.js.map +1 -0
  161. package/dist/sessionReporter.d.ts +70 -0
  162. package/dist/sessionReporter.d.ts.map +1 -0
  163. package/dist/sessionReporter.js +140 -0
  164. package/dist/sessionReporter.js.map +1 -0
  165. package/dist/skillWriter.d.ts +1 -1
  166. package/dist/skillWriter.d.ts.map +1 -1
  167. package/dist/skillWriter.js +5 -2
  168. package/dist/skillWriter.js.map +1 -1
  169. package/dist/syncLoop.d.ts +105 -3
  170. package/dist/syncLoop.d.ts.map +1 -1
  171. package/dist/syncLoop.js +397 -65
  172. package/dist/syncLoop.js.map +1 -1
  173. package/dist/trajectoryMonitor.d.ts +2 -0
  174. package/dist/trajectoryMonitor.d.ts.map +1 -1
  175. package/dist/trajectoryMonitor.js +57 -0
  176. package/dist/trajectoryMonitor.js.map +1 -1
  177. package/dist/watcher/driftWatcher.d.ts.map +1 -1
  178. package/dist/watcher/driftWatcher.js +12 -3
  179. package/dist/watcher/driftWatcher.js.map +1 -1
  180. package/dist/watcher/settingsGuard.d.ts +23 -0
  181. package/dist/watcher/settingsGuard.d.ts.map +1 -1
  182. package/dist/watcher/settingsGuard.js +202 -17
  183. package/dist/watcher/settingsGuard.js.map +1 -1
  184. package/package.json +37 -6
  185. package/dist/brainIndexer.d.ts +0 -51
  186. package/dist/brainIndexer.d.ts.map +0 -1
  187. package/dist/brainIndexer.js +0 -148
  188. package/dist/brainIndexer.js.map +0 -1
  189. package/dist/harness/cursorHooksJson.d.ts +0 -29
  190. package/dist/harness/cursorHooksJson.d.ts.map +0 -1
  191. package/dist/harness/cursorHooksJson.js +0 -130
  192. package/dist/harness/cursorHooksJson.js.map +0 -1
  193. package/dist/harness/gooseHooksWriter.d.ts +0 -27
  194. package/dist/harness/gooseHooksWriter.d.ts.map +0 -1
  195. package/dist/harness/gooseHooksWriter.js +0 -147
  196. package/dist/harness/gooseHooksWriter.js.map +0 -1
  197. package/dist/harness/openhandsHooksWriter.d.ts +0 -23
  198. package/dist/harness/openhandsHooksWriter.d.ts.map +0 -1
  199. package/dist/harness/openhandsHooksWriter.js +0 -146
  200. package/dist/harness/openhandsHooksWriter.js.map +0 -1
@@ -0,0 +1,140 @@
1
+ /**
2
+ * approvedBypasses.ts — ships approved `review_before` bypasses *to* the
3
+ * machine, mirroring how `policySnapshot.ts` ships policy.
4
+ *
5
+ * # Why a separate file from policySnapshot.ts
6
+ *
7
+ * A bypass entry is not a rule: it is a one-time, per-call approval keyed on
8
+ * (workspace, SOP rule id, normalised tool name, hashed command/target), with
9
+ * its own TTL, and it is additive in the *opposite* direction from a policy
10
+ * rule — a policy snapshot can only turn an allow into a block, this cache can
11
+ * only turn one already-held call into an allow, for the one caller who
12
+ * already approved it. Folding the two into one artifact would make either
13
+ * "what does this line do" or "is this additive in the safe direction"
14
+ * dependent on which column you are looking at.
15
+ *
16
+ * # The contract with the gate
17
+ *
18
+ * `.intutic/hooks/approved-bypasses.jsonl` — same directory as the policy
19
+ * snapshot, and for the same reason: `.intutic/hooks` is already in
20
+ * `UNIVERSAL_PROTECTED_PATHS`, so every gate already refuses an agent's own
21
+ * attempt to write here. Two header lines carry integrity, exactly like the
22
+ * `.rules` projection: `#digest` (sha256 of the JSONL body, first 32 hex
23
+ * chars) and `#workspace` (refused if it does not match the gate's own
24
+ * workspace id). Unlike the policy snapshot there is no `#generated` age
25
+ * check — each line carries its own `expiresAt`, and the gate compares that
26
+ * against wall-clock time on every read. A stale FILE degrades to "fewer
27
+ * valid bypasses" (fail closed toward the hold); it can never resurrect an
28
+ * entry whose own TTL has passed.
29
+ *
30
+ * Only `review_before` gates read this today (claudeCodeHooks.ts's
31
+ * `_intuticApprovedBypass`) — see that module's docstring for why the other
32
+ * harness writers are not wired to it: none of them implement `review_before`
33
+ * holds at all, so there is nothing for a bypass to apply to there yet.
34
+ *
35
+ * @module
36
+ */
37
+ import * as fs from 'node:fs/promises';
38
+ import * as path from 'node:path';
39
+ import * as os from 'node:os';
40
+ import { createHash } from 'node:crypto';
41
+ import { createLogger } from '@intutic/logger';
42
+ const log = createLogger('sync-approved-bypasses');
43
+ export const DEFAULT_BYPASS_CACHE_DIR = path.join(os.homedir(), '.intutic', 'hooks');
44
+ export const APPROVED_BYPASSES_FILE = 'approved-bypasses.jsonl';
45
+ /**
46
+ * Trims trailing `/` characters without a regex.
47
+ *
48
+ * `controlPlaneUrl` is operator-configured, not remotely attacker-controlled
49
+ * — but CodeQL's static analysis flags `/\/+$/` as a polynomial-time pattern
50
+ * on external input regardless of practical exploitability here, and the
51
+ * identical pattern already existed unflagged in `onboarding.ts` and
52
+ * `exec.ts` (fixed alongside this one). A loop is O(n), cannot be
53
+ * mis-classified as a ReDoS shape by any static analyzer, and needs no
54
+ * exemption to justify.
55
+ */
56
+ function trimTrailingSlashes(s) {
57
+ let end = s.length;
58
+ while (end > 0 && s.charCodeAt(end - 1) === 47 /* '/' */)
59
+ end--;
60
+ return s.slice(0, end);
61
+ }
62
+ /** Fetches the workspace's currently-approved bypasses. Returns null on any
63
+ * failure — the caller keeps the previous cache file rather than replacing
64
+ * it with nothing, same rule `fetchResolvedPolicy` follows. */
65
+ export async function fetchApprovedBypasses(opts) {
66
+ const url = `${trimTrailingSlashes(opts.controlPlaneUrl)}/api/v1/decisions/approved-bypasses` +
67
+ `?workspaceId=${encodeURIComponent(opts.workspaceId)}`;
68
+ try {
69
+ const res = await fetch(url, {
70
+ headers: { Authorization: `Bearer ${opts.apiKey}` },
71
+ signal: AbortSignal.timeout(10_000),
72
+ });
73
+ if (!res.ok) {
74
+ log.warn({ action: 'bypass_fetch_failed', status: res.status }, 'approved-bypasses returned non-OK');
75
+ return null;
76
+ }
77
+ const body = (await res.json());
78
+ if (typeof body !== 'object' || body === null)
79
+ return null;
80
+ const rec = body;
81
+ const rows = Array.isArray(rec.bypasses) ? rec.bypasses : [];
82
+ return rows.filter((r) => {
83
+ if (typeof r !== 'object' || r === null)
84
+ return false;
85
+ const x = r;
86
+ return (typeof x.workspaceId === 'string' &&
87
+ typeof x.sopRuleId === 'string' &&
88
+ typeof x.toolNameNormalized === 'string' &&
89
+ typeof x.targetHash === 'string' &&
90
+ typeof x.holdId === 'string' &&
91
+ typeof x.decidedBy === 'string' &&
92
+ typeof x.decidedAt === 'string' &&
93
+ typeof x.expiresAt === 'string');
94
+ });
95
+ }
96
+ catch (err) {
97
+ log.warn({ action: 'bypass_fetch_failed', err }, 'approved-bypasses unreachable');
98
+ return null;
99
+ }
100
+ }
101
+ /** Writes the cache file atomically, digest and workspace header included —
102
+ * same convention as `writePolicySnapshot`. Exported so a test can assert
103
+ * the on-disk shape directly. */
104
+ export async function writeApprovedBypasses(entries, workspaceId, cacheDir = DEFAULT_BYPASS_CACHE_DIR) {
105
+ const lines = entries.map((e) => JSON.stringify(e));
106
+ const digest = createHash('sha256').update(lines.join('\n')).digest('hex').slice(0, 32);
107
+ const text = `# Intutic approved review_before bypasses — auto-generated. DO NOT EDIT.\n` +
108
+ `#digest ${digest}\n` +
109
+ `#workspace ${workspaceId}\n` +
110
+ `#generated ${new Date().toISOString()}\n` +
111
+ (lines.length > 0 ? lines.join('\n') + '\n' : '');
112
+ await fs.mkdir(cacheDir, { recursive: true });
113
+ const target = path.join(cacheDir, APPROVED_BYPASSES_FILE);
114
+ const tmp = target + '.tmp';
115
+ await fs.writeFile(tmp, text, { encoding: 'utf-8' });
116
+ // Same read-only-by-rename posture as the policy snapshot: the daemon
117
+ // never needs write access to the file itself after this, only to replace
118
+ // it wholesale on the next cycle.
119
+ await fs.chmod(tmp, 0o444);
120
+ await fs.rename(tmp, target);
121
+ log.debug({ action: 'approved_bypasses_written', digest, count: entries.length, dir: cacheDir }, 'Approved-bypass cache refreshed');
122
+ return { digest, count: entries.length };
123
+ }
124
+ /** Fetch and write in one call. Safe to run on every sync cycle. Never
125
+ * throws — a failed poll must not take down the sync loop, and leaves the
126
+ * previous cache in place (stale bypasses still expire on their own TTL,
127
+ * which is what makes that safe). */
128
+ export async function refreshApprovedBypasses(opts) {
129
+ const entries = await fetchApprovedBypasses(opts);
130
+ if (entries === null)
131
+ return null;
132
+ try {
133
+ return await writeApprovedBypasses(entries, opts.workspaceId, opts.cacheDir ?? DEFAULT_BYPASS_CACHE_DIR);
134
+ }
135
+ catch (err) {
136
+ log.warn({ action: 'approved_bypasses_write_failed', err }, 'Could not write approved-bypasses cache');
137
+ return null;
138
+ }
139
+ }
140
+ //# sourceMappingURL=approvedBypasses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvedBypasses.js","sourceRoot":"","sources":["../../src/lib/approvedBypasses.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"complianceProbes.d.ts","sourceRoot":"","sources":["../../src/lib/complianceProbes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAUH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,gBAAgB,CAAA;QACvB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,WAAW,EAAE,MAAM,CAAA;QACnB,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgF5G;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAiBjG"}
1
+ {"version":3,"file":"complianceProbes.d.ts","sourceRoot":"","sources":["../../src/lib/complianceProbes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,gBAAgB,CAAA;QACvB,QAAQ,EAAE,MAAM,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;QACd,WAAW,EAAE,MAAM,CAAA;QACnB,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KACnB,CAAA;CACF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqF5G;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAiBjG"}
@@ -78,6 +78,11 @@ export function checkHostContainment(hostname, workspaceId, port = 443) {
78
78
  resolve({
79
79
  host: hostname,
80
80
  contained: true,
81
+ // `||`, not `??`, and deliberately. `??` only falls through on
82
+ // null/undefined, so an ErrnoException carrying `code: ''` would report
83
+ // `error: ''` and discard the message that says what actually happened.
84
+ // An empty code is the one case where these differ, and falling through
85
+ // is the behaviour worth having.
81
86
  error: err.code || err.message,
82
87
  });
83
88
  });
@@ -1 +1 @@
1
- {"version":3,"file":"complianceProbes.js","sourceRoot":"","sources":["../../src/lib/complianceProbes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"complianceProbes.js","sourceRoot":"","sources":["../../src/lib/complianceProbes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * decisionsDigest.ts — governed decisions log.
3
+ *
4
+ * Mirrors `egressPolicy.ts`'s thin-projection pattern (fetch a bounded,
5
+ * read-only projection from the control plane every sync cycle, write it
6
+ * locally) for a different payload: the last ~20 governance decisions
7
+ * (adjudications, approved/rejected decisions, resolved incidents,
8
+ * settings changes), rendered as one-line summaries SERVER-SIDE by
9
+ * `GET /api/v1/workspace/decisions-digest`. This module never parses or
10
+ * re-renders decision content — it only writes what it is given.
11
+ *
12
+ * Deliberately narrow, same boundary the control-plane route documents:
13
+ * governance-decision records only, never conversational memory or general
14
+ * context management (this repo pivoted away from that harness product —
15
+ * see this repo's own CLAUDE.md history, and `apps/docs/guide/decisions-log.md`).
16
+ *
17
+ * Opt-in via `WorkspaceSettings.decisionsLogEnabled` (default off). The
18
+ * CALLER is responsible for that gate — `refreshDecisionsDigest` always
19
+ * fetches and writes when invoked, so `syncLoop.ts` only calls it when the
20
+ * workspace has opted in. When disabled, the caller simply stops calling
21
+ * this module; existing files are left as they were last written rather than
22
+ * being force-deleted (a developer's editor may have that file open) or
23
+ * overwritten with a stale/misleading "disabled" placeholder.
24
+ *
25
+ * Two files:
26
+ *
27
+ * 1. `.intutic/DECISIONS.md` — the full bounded record (all entries the
28
+ * digest returns), regenerated whole every cycle with `configWriter.ts`'s
29
+ * pattern (i): a DO-NOT-EDIT header + `atomicWrite`. Gitignored — runtime
30
+ * artifacts stay untracked, the same rule this repo's own CLAUDE.md doc
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.
39
+ *
40
+ * Deliberately does NOT reuse `configWriter.ts`'s own `fileHeader()` for the
41
+ * DECISIONS.md header — that helper stamps `newIso()` (wall-clock "Last
42
+ * sync"), which would make the file churn every cycle even when the digest
43
+ * itself hasn't changed. The header here instead derives its timestamp from
44
+ * the digest's own newest entry, so identical input renders an identical
45
+ * file — see the render-idempotence test.
46
+ *
47
+ * @module
48
+ */
49
+ import { HarnessType } from '@intutic/shared-types';
50
+ /** Relative to the workspace root. */
51
+ export declare const DECISIONS_LOG_RELATIVE_PATH: string;
52
+ /** One digest entry, exactly as `GET /api/v1/workspace/decisions-digest` returns it — the summary line is already rendered server-side. */
53
+ export interface DecisionsDigestEntry {
54
+ id: string;
55
+ kind: string;
56
+ timestamp: string;
57
+ summary: string;
58
+ }
59
+ export interface DecisionsDigestResponse {
60
+ workspaceId: string;
61
+ entries: DecisionsDigestEntry[];
62
+ }
63
+ export interface DecisionsDigestOptions {
64
+ controlPlaneUrl: string;
65
+ apiKey: string;
66
+ workspaceId: string;
67
+ workspaceRoot: string;
68
+ /** Active harnesses this cycle — the bounded section is only injected when `claude-code` is among them. */
69
+ harnesses: HarnessType[];
70
+ }
71
+ /**
72
+ * Fetch this workspace's decisions digest. Returns null on any failure — the
73
+ * caller keeps whatever was written last cycle rather than replacing it with
74
+ * nothing, the same rule `egressPolicy.ts`'s fetch follows.
75
+ */
76
+ export declare function fetchDecisionsDigest(opts: Pick<DecisionsDigestOptions, 'controlPlaneUrl' | 'apiKey' | 'workspaceId'>): Promise<DecisionsDigestResponse | null>;
77
+ /** Renders the full bounded record written to `.intutic/DECISIONS.md`. */
78
+ export declare function renderDecisionsMarkdown(entries: DecisionsDigestEntry[]): string;
79
+ /** Renders the bounded, marker-delimited section injected into the harness config file — the newest `limit` entries only. */
80
+ export declare function renderBoundedSection(entries: DecisionsDigestEntry[], limit?: number): string;
81
+ /**
82
+ * Idempotently inject/replace the bounded section in `content`. If the
83
+ * markers are present, everything between them (inclusive) is replaced — the
84
+ * mechanism the `applyConfigEdits` SkillOpt writer already uses elsewhere in
85
+ * this file's sibling module, `configWriter.ts` — never duplicated. If
86
+ * absent, the section is appended once, with a separating blank line.
87
+ */
88
+ export declare function injectBoundedSection(content: string, section: string): string;
89
+ /**
90
+ * Fetch and write both files in one call, mirroring `refreshEgressPolicy`.
91
+ * Never throws — a failed poll must not take down the sync loop.
92
+ *
93
+ * Does NOT itself check `WorkspaceSettings.decisionsLogEnabled` — see this
94
+ * module's own doc comment for why that gate belongs to the caller.
95
+ */
96
+ export declare function refreshDecisionsDigest(opts: DecisionsDigestOptions): Promise<{
97
+ entriesWritten: number;
98
+ } | null>;
99
+ //# sourceMappingURL=decisionsDigest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisionsDigest.d.ts","sourceRoot":"","sources":["../../src/lib/decisionsDigest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAKnD,sCAAsC;AACtC,eAAO,MAAM,2BAA2B,QAAwC,CAAA;AAKhF,2IAA2I;AAC3I,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,2GAA2G;IAC3G,SAAS,EAAE,WAAW,EAAE,CAAA;CACzB;AAyBD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,iBAAiB,GAAG,QAAQ,GAAG,aAAa,CAAC,GAC/E,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CA0BzC;AAkBD,0EAA0E;AAC1E,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAO/E;AAED,6HAA6H;AAC7H,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,oBAAoB,EAAE,EAAE,KAAK,SAAK,GAAG,MAAM,CAOxF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ7E;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmC5C"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * decisionsDigest.ts — governed decisions log.
3
+ *
4
+ * Mirrors `egressPolicy.ts`'s thin-projection pattern (fetch a bounded,
5
+ * read-only projection from the control plane every sync cycle, write it
6
+ * locally) for a different payload: the last ~20 governance decisions
7
+ * (adjudications, approved/rejected decisions, resolved incidents,
8
+ * settings changes), rendered as one-line summaries SERVER-SIDE by
9
+ * `GET /api/v1/workspace/decisions-digest`. This module never parses or
10
+ * re-renders decision content — it only writes what it is given.
11
+ *
12
+ * Deliberately narrow, same boundary the control-plane route documents:
13
+ * governance-decision records only, never conversational memory or general
14
+ * context management (this repo pivoted away from that harness product —
15
+ * see this repo's own CLAUDE.md history, and `apps/docs/guide/decisions-log.md`).
16
+ *
17
+ * Opt-in via `WorkspaceSettings.decisionsLogEnabled` (default off). The
18
+ * CALLER is responsible for that gate — `refreshDecisionsDigest` always
19
+ * fetches and writes when invoked, so `syncLoop.ts` only calls it when the
20
+ * workspace has opted in. When disabled, the caller simply stops calling
21
+ * this module; existing files are left as they were last written rather than
22
+ * being force-deleted (a developer's editor may have that file open) or
23
+ * overwritten with a stale/misleading "disabled" placeholder.
24
+ *
25
+ * Two files:
26
+ *
27
+ * 1. `.intutic/DECISIONS.md` — the full bounded record (all entries the
28
+ * digest returns), regenerated whole every cycle with `configWriter.ts`'s
29
+ * pattern (i): a DO-NOT-EDIT header + `atomicWrite`. Gitignored — runtime
30
+ * artifacts stay untracked, the same rule this repo's own CLAUDE.md doc
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.
39
+ *
40
+ * Deliberately does NOT reuse `configWriter.ts`'s own `fileHeader()` for the
41
+ * DECISIONS.md header — that helper stamps `newIso()` (wall-clock "Last
42
+ * sync"), which would make the file churn every cycle even when the digest
43
+ * itself hasn't changed. The header here instead derives its timestamp from
44
+ * the digest's own newest entry, so identical input renders an identical
45
+ * file — see the render-idempotence test.
46
+ *
47
+ * @module
48
+ */
49
+ import * as fs from 'node:fs/promises';
50
+ import * as path from 'node:path';
51
+ import { createLogger } from '@intutic/logger';
52
+ import { HarnessType } from '@intutic/shared-types';
53
+ import { HARNESS_FILES, atomicWrite } from '../configWriter.js';
54
+ const log = createLogger('sync-decisions-digest');
55
+ /** Relative to the workspace root. */
56
+ 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 -->';
59
+ /**
60
+ * Trims trailing `/` without a regex — see the identical helper in
61
+ * `egressPolicy.ts`/`approvedBypasses.ts`: `/\/+$/` is flagged by CodeQL as a
62
+ * polynomial-time pattern on external input, and a loop sidesteps the whole
63
+ * category.
64
+ */
65
+ function trimTrailingSlashes(s) {
66
+ let end = s.length;
67
+ while (end > 0 && s.charCodeAt(end - 1) === 47 /* '/' */)
68
+ end--;
69
+ return s.slice(0, end);
70
+ }
71
+ function isDigestEntry(value) {
72
+ if (typeof value !== 'object' || value === null)
73
+ return false;
74
+ const e = value;
75
+ return (typeof e.id === 'string' &&
76
+ typeof e.kind === 'string' &&
77
+ typeof e.timestamp === 'string' &&
78
+ typeof e.summary === 'string');
79
+ }
80
+ /**
81
+ * Fetch this workspace's decisions digest. Returns null on any failure — the
82
+ * caller keeps whatever was written last cycle rather than replacing it with
83
+ * nothing, the same rule `egressPolicy.ts`'s fetch follows.
84
+ */
85
+ export async function fetchDecisionsDigest(opts) {
86
+ const url = `${trimTrailingSlashes(opts.controlPlaneUrl)}/api/v1/workspace/decisions-digest` +
87
+ `?workspaceId=${encodeURIComponent(opts.workspaceId)}`;
88
+ try {
89
+ const res = await fetch(url, {
90
+ headers: { Authorization: `Bearer ${opts.apiKey}`, 'x-workspace-id': opts.workspaceId },
91
+ signal: AbortSignal.timeout(10_000),
92
+ });
93
+ if (!res.ok) {
94
+ log.warn({ action: 'decisions_digest_fetch_failed', status: res.status }, 'decisions-digest returned non-OK');
95
+ return null;
96
+ }
97
+ const body = (await res.json());
98
+ if (typeof body !== 'object' || body === null)
99
+ return null;
100
+ const rec = body;
101
+ const workspaceId = typeof rec.workspaceId === 'string' ? rec.workspaceId : opts.workspaceId;
102
+ const entries = Array.isArray(rec.entries) ? rec.entries.filter(isDigestEntry) : [];
103
+ return { workspaceId, entries };
104
+ }
105
+ catch (err) {
106
+ log.warn({ action: 'decisions_digest_fetch_failed', err }, 'decisions-digest unreachable');
107
+ return null;
108
+ }
109
+ }
110
+ /** Deterministic header: no wall-clock stamp, so identical input renders an identical file. */
111
+ function renderHeader(entries) {
112
+ const latest = entries[0]?.timestamp ?? 'never';
113
+ return [
114
+ '# Intutic Governed Decisions Log (auto-generated)',
115
+ '# DO NOT EDIT — managed by intutic sync daemon',
116
+ `# Most recent entry: ${latest}`,
117
+ '#',
118
+ '# Governance-decision records only (adjudications, approved/rejected',
119
+ '# decisions, resolved incidents, settings changes) — NOT conversational',
120
+ '# memory or general context management.',
121
+ '',
122
+ '',
123
+ ].join('\n');
124
+ }
125
+ /** Renders the full bounded record written to `.intutic/DECISIONS.md`. */
126
+ export function renderDecisionsMarkdown(entries) {
127
+ const header = renderHeader(entries);
128
+ if (entries.length === 0) {
129
+ return `${header}_No governance decisions recorded yet._\n`;
130
+ }
131
+ const lines = entries.map((e) => `- ${e.timestamp} — ${e.summary}`);
132
+ return header + lines.join('\n') + '\n';
133
+ }
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) {
136
+ const bounded = entries.slice(0, limit);
137
+ const lines = bounded.length > 0
138
+ ? bounded.map((e) => `- ${e.timestamp} — ${e.summary}`)
139
+ : ['_No governance decisions recorded yet._'];
140
+ return [SECTION_START, '## Recent Governed Decisions', '', ...lines, SECTION_END].join('\n');
141
+ }
142
+ /**
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.
148
+ */
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);
154
+ }
155
+ const sep = content.endsWith('\n\n') ? '' : content.endsWith('\n') ? '\n' : '\n\n';
156
+ return `${content}${sep}${section}\n`;
157
+ }
158
+ /**
159
+ * Fetch and write both files in one call, mirroring `refreshEgressPolicy`.
160
+ * Never throws — a failed poll must not take down the sync loop.
161
+ *
162
+ * Does NOT itself check `WorkspaceSettings.decisionsLogEnabled` — see this
163
+ * module's own doc comment for why that gate belongs to the caller.
164
+ */
165
+ export async function refreshDecisionsDigest(opts) {
166
+ const digest = await fetchDecisionsDigest(opts);
167
+ if (digest === null)
168
+ return null;
169
+ try {
170
+ const fullPath = path.join(opts.workspaceRoot, DECISIONS_LOG_RELATIVE_PATH);
171
+ 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
+ }
192
+ return { entriesWritten: digest.entries.length };
193
+ }
194
+ catch (err) {
195
+ log.warn({ action: 'decisions_digest_write_failed', err }, 'Could not write decisions-log files');
196
+ return null;
197
+ }
198
+ }
199
+ //# sourceMappingURL=decisionsDigest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisionsDigest.js","sourceRoot":"","sources":["../../src/lib/decisionsDigest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * egressPolicy.ts — ships the workspace's central egress policy *to* the
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
6
+ * the control plane, write a local artifact under `.intutic/hooks` with
7
+ * integrity headers, and let the consumer (here the Rust proxy) read it.
8
+ *
9
+ * # The contract with the proxy
10
+ *
11
+ * `.intutic/hooks/egress-policy.json` — same directory as the policy snapshot
12
+ * and for the same reason: `.intutic/hooks` is in `UNIVERSAL_PROTECTED_PATHS`,
13
+ * so a gate already refuses an agent's own write there. The file carries its
14
+ * own integrity: `digest` (sha256 of a canonical `mode\nallow…` string, first
15
+ * 32 hex) and `workspace`. The proxy recomputes the digest and refuses a file
16
+ * whose digest or workspace does not match, keeping its config-derived policy
17
+ * instead — a corrupt or foreign file degrades to "local config", never to a
18
+ * weaker enforcement than the operator configured.
19
+ *
20
+ * `mode: null` means "central management not configured": the proxy keeps its
21
+ * local `intutic_settings.egress` / `INTUTIC_EGRESS_MODE`. A `mode` of
22
+ * `off`/`monitor`/`enforce` is authoritative for the mode; the `allow` list is
23
+ * UNIONed with the proxy's local allow entries so a developer's local infra
24
+ * allowances are never dropped.
25
+ *
26
+ * @module
27
+ */
28
+ export declare const DEFAULT_EGRESS_CACHE_DIR: string;
29
+ export declare const EGRESS_POLICY_FILE = "egress-policy.json";
30
+ export type EgressMode = 'off' | 'monitor' | 'enforce';
31
+ /** The workspace egress policy, as `GET /api/v1/workspace/egress-policy` returns it. */
32
+ export interface WorkspaceEgressPolicy {
33
+ /** null → central management not configured; the proxy keeps local config. */
34
+ mode: EgressMode | null;
35
+ allow: string[];
36
+ }
37
+ export interface EgressPolicyOptions {
38
+ controlPlaneUrl: string;
39
+ apiKey: string;
40
+ workspaceId: string;
41
+ /** Override the directory (tests). */
42
+ cacheDir?: string;
43
+ }
44
+ /**
45
+ * The canonical string the digest is computed over — identical on the daemon
46
+ * (here) and the proxy (Rust `load_local_egress_file`), so both derive the same
47
+ * digest. Mode (or empty) then each allow entry, newline-joined. Allow entries
48
+ * are hosts/CIDRs and never contain newlines.
49
+ */
50
+ export declare function egressDigestInput(mode: EgressMode | null, allow: string[]): string;
51
+ /** Fetch this workspace's central egress policy. Returns null on any failure —
52
+ * the caller keeps the previous cache file rather than replacing it with
53
+ * nothing, the same rule the policy snapshot follows. */
54
+ export declare function fetchWorkspaceEgressPolicy(opts: EgressPolicyOptions): Promise<WorkspaceEgressPolicy | null>;
55
+ /** Write the cache file atomically, digest + workspace header included — same
56
+ * read-only-by-rename posture as the policy snapshot. Exported so a test can
57
+ * assert the on-disk shape directly. */
58
+ export declare function writeEgressPolicy(policy: WorkspaceEgressPolicy, workspaceId: string, cacheDir?: string): Promise<{
59
+ digest: string;
60
+ mode: EgressMode | null;
61
+ }>;
62
+ /** Fetch and write in one call. Safe to run on every sync cycle. Never throws —
63
+ * a failed poll must not take down the sync loop, and leaves the previous
64
+ * cache in place. */
65
+ export declare function refreshEgressPolicy(opts: EgressPolicyOptions): Promise<{
66
+ digest: string;
67
+ mode: EgressMode | null;
68
+ } | null>;
69
+ //# sourceMappingURL=egressPolicy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egressPolicy.d.ts","sourceRoot":"","sources":["../../src/lib/egressPolicy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAUH,eAAO,MAAM,wBAAwB,QAA+C,CAAA;AACpF,eAAO,MAAM,kBAAkB,uBAAuB,CAAA;AAEtD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAA;AAEtD,wFAAwF;AACxF,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;IACvB,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAaD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAElF;AAED;;0DAE0D;AAC1D,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA0BvC;AAED;;yCAEyC;AACzC,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,qBAAqB,EAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,MAAiC,GAC1C,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,CAAC,CAuBtD;AAED;;sBAEsB;AACtB,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAAC,CAS7D"}