@intutic/sync-daemon 1.10.0 → 2.0.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 (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,353 @@
1
+ /**
2
+ * The config files an agent must never write, and the command shapes it must
3
+ * never run — whichever harness it runs under.
4
+ *
5
+ * # Why this is one list
6
+ *
7
+ * It was eleven lists, and no two agreed. Measured on 2026-08-04:
8
+ *
9
+ * | path | harnesses protecting it |
10
+ * |---|---|
11
+ * | `.claude/settings.local.json` | 3 of 11 |
12
+ * | `.gemini/settings.json` | 5 of 11 |
13
+ * | `.intutic/events` | 5 of 11 |
14
+ * | `.codeium/windsurf/hooks.json` | 8 of 11 |
15
+ * | `.cursor/hooks.json` | 8 of 11 |
16
+ *
17
+ * That is not eleven partial views of one intent, it is a **cross-harness
18
+ * tamper matrix**. The Claude-family lists carried only Claude paths, so an
19
+ * agent under Claude Code could rewrite `.cursor/hooks.json`,
20
+ * `.openhands/hooks.json`, `.gemini/settings.json` or the governance plugin
21
+ * directory unopposed; the other nine could write `.claude/settings.local.json`,
22
+ * which Claude Code loads at *higher* precedence than the `settings.json` they
23
+ * all did protect. Whichever harness the agent was running under, it could
24
+ * disarm a different one.
25
+ *
26
+ * A protected-path list is a security control. Eleven copies of a security
27
+ * control is eleven chances for one to be wrong, and every one of them was.
28
+ *
29
+ * # The same was true of the command guards
30
+ *
31
+ * Nine writers hand-maintained a `BYPASS_PATTERNS` list. Measured on 2026-08-05:
32
+ *
33
+ * | pattern | writers carrying it |
34
+ * |---|---|
35
+ * | `chflags nouchg` / `chattr -i` | 9 of 9 |
36
+ * | `rm -rf .intutic` | 7 of 9 — **`cursorHooks` and `windsurfHooks` had no protected-path command guard at all** |
37
+ * | `rm -rf .gemini/settings` | 4 of 9 |
38
+ * | the harness's own env kill-switch | 1 each |
39
+ *
40
+ * That last row is the load-bearing one. `claudeCodeHooks` guarded
41
+ * `CLAUDE_CODE_HOOKS=` and nothing else; `piHooks` guarded `PI_PRE_TOOL_HOOK=`
42
+ * and nothing else. So under any harness, the *other eight* kill-switches were
43
+ * free to set — the identical cross-harness hole the path list already had.
44
+ * `GOVERNANCE_BYPASS_PATTERNS` closes it with one generic pattern rather than
45
+ * nine specific ones, so a harness added tomorrow is covered on the day it
46
+ * lands.
47
+ *
48
+ * Two writers also used `/chflags\s+nouchg/` where the other seven used a
49
+ * literal substring. `\s` does not exist in POSIX ERE — see
50
+ * {@link assertPortableEre} for why that class of divergence is now a load
51
+ * failure rather than a silent one.
52
+ *
53
+ * # Scope
54
+ *
55
+ * Universal by design. A Cursor agent has no legitimate reason to edit Claude
56
+ * Code's settings, and the reverse holds for every pair — so the union is the
57
+ * correct list for all of them, not a Cursor list plus a Claude list.
58
+ * Harness-specific additions spread this and append; `harnessProtectedPaths.test.ts`
59
+ * asserts each is a superset.
60
+ *
61
+ * @module
62
+ */
63
+ /** Governance config that must hold still, for every harness. */
64
+ export declare const UNIVERSAL_PROTECTED_PATHS: readonly string[];
65
+ /**
66
+ * One command-guard rule, in a form every gate can evaluate identically.
67
+ *
68
+ * `source` is matched against the **normalised, padded** command — see
69
+ * {@link NORMALISE_CONTRACT}. It is deliberately restricted to the intersection
70
+ * of POSIX ERE and JavaScript `RegExp`; {@link assertPortableEre} enforces that
71
+ * at module load.
72
+ */
73
+ /**
74
+ * Which part of the tool call a rule is matched against.
75
+ *
76
+ * Not cosmetic. A `BLOCK:` SOP compiles to a **tool-name** pattern (`Bash`,
77
+ * `Write`), while every pattern in this file matches **command or path text**.
78
+ * Evaluating one against the other silently matches nothing — the SOP rules
79
+ * would have loaded, appeared in the audit trail as active, and never fired.
80
+ * Making the subject an explicit column means a rule cannot be pointed at the
81
+ * wrong string by omission.
82
+ */
83
+ /** `action` is the space-padded action-token string the gate classifies a
84
+ * shell command to (`" action:deploy "`, from `ACTION_NEEDLES`) — the subject
85
+ * a `review_before: action:deploy` hold rule matches. */
86
+ export type GuardSubject = 'tool' | 'command' | 'target' | 'content' | 'action' | 'any';
87
+ export interface GuardPattern {
88
+ /** Stable id. Appears in the block message and the audit line, so it is the
89
+ * thing a support conversation is conducted in. Never renumber one. */
90
+ id: string;
91
+ /** Portable ERE ∩ JS RegExp source. */
92
+ source: string;
93
+ /** What {@link source} is matched against. Defaults to `any` — command and
94
+ * target, but never the tool name. `content` is the serialized tool input
95
+ * (`JSON.stringify(tool_input)` / `$TOOL_INPUT_JSON`), un-normalised — the
96
+ * same subject the WHERE argPattern machinery matches, so a content rule
97
+ * sees the bytes a Write would put on disk, not a whitespace-collapsed
98
+ * rendering of them. */
99
+ subject?: GuardSubject;
100
+ /** Matched case-insensitively (`grep -iE` / the JS `i` flag). */
101
+ ignoreCase?: boolean;
102
+ /**
103
+ * What the rule does when it matches.
104
+ *
105
+ * `block` refuses the call. `warn` allows it and emits `tool_flagged` — the
106
+ * advisory tier that earns a pattern its promotion to `block`, following
107
+ * `sslGateEvaluator.ts` rather than inventing a second discipline. `shadow`
108
+ * also allows, but emits `tool_would_block`: the rule is certain and the
109
+ * workspace's interventionMode asked us not to act on it. The two allow-ing
110
+ * severities are kept apart because a SHADOW rollout is decided on the second
111
+ * count, and collapsing them into `warn` made it unmeasurable. `hold`
112
+ * refuses the call like `block` but records it for a human (`tool_held`
113
+ * plus a v1 hold record) and lets the exact same call through once an
114
+ * approved bypass for it exists — the `review_before:` / `REQUIRE_APPROVAL:`
115
+ * tier, one mechanism in every gate since gate body v8.
116
+ */
117
+ severity: 'block' | 'warn' | 'shadow' | 'hold';
118
+ /** Shown to the developer when it fires. Written for someone who is mid-task
119
+ * and now blocked, not for a security reviewer. */
120
+ reason: string;
121
+ /** Why the rule exists **and what it deliberately does not catch**. The second
122
+ * half is not optional: a guard whose limits are undocumented gets mistaken
123
+ * for containment. */
124
+ rationale: string;
125
+ /** Commands that MUST match. */
126
+ matches: readonly string[];
127
+ /** Commands that MUST NOT match — the false-positive contract. A pattern with
128
+ * fewer than three of these fails {@link assertGuardTableSane}, because the
129
+ * cheapest way to write a guard that never fires wrongly is to never think
130
+ * about the case where it would. */
131
+ notMatches: readonly string[];
132
+ /**
133
+ * Argument-level condition from a ` WHERE ` SOP rule, as JS `RegExp` source.
134
+ *
135
+ * When present, a rule whose {@link source} has matched (for SOP rules: the
136
+ * tool NAME) fires only if this also matches the serialized tool input —
137
+ * `JSON.stringify(tool_input ?? {})`, compact, insertion order, non-ASCII
138
+ * intact, the exact shape `matchSopRule` in the control plane and
139
+ * `serialise_tool_input` in intutic-clawde match against. Without this field
140
+ * a `BLOCK:^shell$ WHERE kubectl\s+apply(?!.*@sha256:)` rule reached the
141
+ * gates as "block shell unconditionally" — over-blocking `make test` while
142
+ * failing to express the condition it was written for.
143
+ *
144
+ * Deliberately NOT restricted to the portable ERE subset
145
+ * ({@link assertPortableEre}): it never runs under grep. The JS gates compile
146
+ * it as a `RegExp`; the bash gates delegate the match to `python3` `re`. The
147
+ * supported dialect is therefore the JS ∩ Python `re` intersection —
148
+ * character classes, alternation, anchors, quantifiers, `\s`, lookahead and
149
+ * lookbehind all agree; named groups do NOT (`(?<n>…)` vs `(?P<n>…)`), nor do
150
+ * some Unicode escapes. A pattern one engine cannot compile is enforced
151
+ * name-only by that gate and reported as `rule_downgraded`, never silently
152
+ * dropped — the same honest-divergence stance the LangGraph port documents in
153
+ * its snapshot reader.
154
+ */
155
+ argPattern?: string;
156
+ }
157
+ export declare const NORMALISE_CONTRACT: {
158
+ /**
159
+ * JS: produce the string patterns are matched against.
160
+ *
161
+ * Compiled from {@link NORMALISE_JS_EXPR} rather than written out, so it
162
+ * cannot diverge from what the gates run. `unknown` in, because callers pass
163
+ * whatever a harness put in its payload.
164
+ */
165
+ readonly js: (s: unknown) => string;
166
+ /** The JS function, emitted verbatim into every JavaScript gate. */
167
+ readonly jsSource: "function intuticNormalise(s) {\n return ' ' + String(s == null ? '' : s).replace(/\\s+/g, ' ') + ' ';\n}";
168
+ /**
169
+ * The Python function, emitted into the Open WebUI filter.
170
+ *
171
+ * `re.sub(r"\s+", " ", …)` rather than the more idiomatic `" ".join(s.split())`,
172
+ * and the difference is the one a test caught: `split()` **strips** leading and
173
+ * trailing whitespace, while the JS `replace(/\s+/g, ' ')` collapses it to a
174
+ * single space and keeps it. So `" a b "` normalised to `" a b "` in Python
175
+ * and `" a b "` in JS and bash. Both match the same patterns, since patterns
176
+ * use single-space boundaries — but "happens to be equivalent" is not the
177
+ * property this contract claims, and the next edit would not have been so lucky.
178
+ *
179
+ * Python's `\s` on a `str` covers Unicode whitespace (U+00A0, U+3000), matching
180
+ * JS. The shell fallback cannot, which is why SHELL_EXTRACT pre-passes.
181
+ */
182
+ /** Requires `re` in scope — the emitted filter imports it. */
183
+ readonly pySource: string;
184
+ /**
185
+ * Shell: pure parameter expansion — no subshell, no `tr`, no `python3`.
186
+ *
187
+ * **ASCII only, and deliberately second in line.** Bash cannot express a
188
+ * Unicode whitespace class, so this collapses only the C0 set; U+00A0 would
189
+ * survive it and a pattern written with a literal space would then miss. The
190
+ * bash gates are not exposed to that because `SHELL_EXTRACT` runs every field
191
+ * through Python's `" ".join(str(v).split())` *before* this ever sees it —
192
+ * which is Unicode-aware. This is the belt to that pair of braces, and saying
193
+ * so here is the point: an earlier version of this comment claimed the three
194
+ * normalisers were provably identical, and they were not.
195
+ */
196
+ readonly shell: string;
197
+ };
198
+ /**
199
+ * Rejects any pattern that would not mean the same thing to `grep -E` and to
200
+ * JavaScript.
201
+ *
202
+ * Runs at module load rather than from a test, so a non-portable pattern breaks
203
+ * the import — every writer, every test, immediately — instead of breaking one
204
+ * test that someone might skip. The failure this prevents is not hypothetical:
205
+ * `cursorHooks` and `windsurfHooks` shipped `\s+` for a year.
206
+ *
207
+ * `\s`, `\d`, `\w` and `\b` are forbidden **even though GNU grep accepts them**,
208
+ * because GNU grep is not the only grep — busybox and BSD do not, and a customer
209
+ * running us in an Alpine image would get a gate that silently matches nothing.
210
+ */
211
+ export declare function assertPortableEre(source: string, id: string): void;
212
+ /**
213
+ * Commands that disarm governance itself.
214
+ *
215
+ * The union of the nine hand-rolled `BYPASS_PATTERNS` lists, plus the two holes
216
+ * the union exposed: `cursorHooks`/`windsurfHooks` never guarded `.intutic` at
217
+ * all, and every list guarded only its own harness's env kill-switch.
218
+ */
219
+ export declare const GOVERNANCE_BYPASS_PATTERNS: readonly GuardPattern[];
220
+ /**
221
+ * Credential VALUES in the content an agent is about to write.
222
+ *
223
+ * The gap this closes, measured before it was built: the PreToolUse gate —
224
+ * the only enforcement point that runs before the harness executes a tool —
225
+ * matched tool name, target path and command, never content. A key the model
226
+ * had seen anywhere in context could be written into a config file and the
227
+ * gate had no rule that could notice; the proxy's DLP covers the same case
228
+ * only when LLM traffic actually routes through the proxy, so a
229
+ * hooks-installed-but-unproxied workspace had zero write-direction scanning.
230
+ * (GitGuardian's 2025 measurement of why this matters: AI-assisted commits
231
+ * shipped hardcoded secrets at 3.2% against a 1.5% human baseline.)
232
+ *
233
+ * Sources live in `@intutic/shared-types` (`secretPatterns.ts`) because the
234
+ * pre-commit scan in `tools/cli/src/lib/gitHooks.ts` greps the SAME shapes
235
+ * over the staged diff — two hand-kept copies of "what is a credential" is
236
+ * the drift this repo keeps paying for. Fixtures stay here, where the
237
+ * table's self-test runs.
238
+ *
239
+ * ## Severity: block, deliberately skipping the warn-first ramp
240
+ *
241
+ * DESTRUCTIVE_COMMAND_PATTERNS shipped at warn to earn promotion on measured
242
+ * false positives. These four ship at block because both halves of that
243
+ * trade differ: the patterns are prefix-anchored value shapes already
244
+ * hard-blocking in production on the MCP proxy's input path with no
245
+ * false-positive reports, and the failure being prevented — a credential in
246
+ * a file, then in a commit — is not undone by an undo (the key is burned;
247
+ * rotation is the only remedy). A warn that lets the write proceed IS the
248
+ * incident.
249
+ *
250
+ * ## What this deliberately does not catch
251
+ *
252
+ * A secret split across two Writes, base64/hex-encoded values, secrets
253
+ * assembled by concatenation in generated code, values reached through
254
+ * env-var indirection, and any credential format without a distinctive
255
+ * prefix. Those need entropy analysis and cross-call state that belong in
256
+ * the proxy's DLP, not in a gate that must stay fast and false-positive-free
257
+ * to keep its block tier trusted. This is the same floor-vs-DLP split the
258
+ * warn tier's own comment draws ("arguments and paths stay out — that is
259
+ * DLP's job"): the floor takes the four shapes precise enough to refuse on.
260
+ */
261
+ export declare const SECRET_CONTENT_PATTERNS: readonly GuardPattern[];
262
+ /**
263
+ * Writes and edits targeting the agent-skill surface — `.agents/skills/**`
264
+ * and `.claude/skills/**`.
265
+ *
266
+ * TD-358 (updated 2026-08-18): these two entries stay `warn` and stay
267
+ * compiled into {@link staticFloorPatterns} — that part of the original
268
+ * decision is unchanged. What changed is what that tier assignment now
269
+ * *means*: it is the DEGRADED-MODE baseline, not the intended steady state.
270
+ * The steady state, everywhere a valid policy snapshot has landed, is `block`
271
+ * — shipped as `skill_surface.*.tier` entries through
272
+ * `services/sync-daemon/src/lib/policySnapshot.ts`'s `buildSnapshotRules`,
273
+ * gated behind `SKILL_SURFACE_TIER_SEVERITY`. See that constant's doc comment
274
+ * for why skill-directory *path* writes no longer sit behind the same
275
+ * false-positive-rate justification skill-CONTENT scanning still does — this
276
+ * entry only covers the half that stayed at `warn`.
277
+ *
278
+ * The two design choices below are for different reasons and worth
279
+ * separating:
280
+ *
281
+ * - **Why the FLOOR copy stays `warn`:** a compiled-in rule ships on every
282
+ * machine at once and can only be changed by a release — no one-sync-cycle
283
+ * undo if it turns out wrong. That is exactly the property a degraded-mode
284
+ * baseline needs (safe to run forever, unconditionally, on a machine that
285
+ * has never talked to the control plane) and exactly the property the
286
+ * steady-state decision does not need to have, since it lives in the
287
+ * snapshot and can be retracted in a cycle. Blocking here as well would
288
+ * collapse that distinction and reintroduce the un-retractable blast radius
289
+ * the snapshot channel exists to avoid.
290
+ * - **Why a floor copy exists at all, unlike `DESTRUCTIVE_COMMAND_PATTERNS`:**
291
+ * this pattern set is NOT content-conditional — it does not run
292
+ * `scanSkillContent` or judge what a skill file says, only WHERE a write
293
+ * targets. That is a deterministic, zero-ambiguity match (a write's target
294
+ * path either is or is not under `.agents/skills/` or `.claude/skills/`),
295
+ * so a workspace with no control-plane connectivity (offline, pre-`connect`,
296
+ * or a snapshot that failed its digest/workspace check) still gets an
297
+ * advisory signal from the moment the gate is written, rather than falling
298
+ * back to nothing.
299
+ *
300
+ * `subject: 'target'` deliberately, not `'any'`: this matches the tool's own
301
+ * path argument (`file_path`/`path`/…, the same extraction every Write/Edit
302
+ * gate already does), not a bare mention in a shell command. A `cat` or `grep`
303
+ * of a skill file is a read, not a write, and is not what this pattern
304
+ * exists to flag — narrower than `UNIVERSAL_PROTECTED_PATHS`'s "any mention"
305
+ * rule on purpose, since that rule blocks and this one only advises.
306
+ *
307
+ * A future promotion to `block` on skill CONTENT (not path) is a different,
308
+ * later, and still-open decision — it needs the corpus measurement TD-358
309
+ * describes, which this change does not supply. It should ship through the
310
+ * same policy-snapshot channel the way this path-tier promotion and
311
+ * `DESTRUCTIVE_COMMAND_PATTERNS` both do, so it too is retractable in a sync
312
+ * cycle rather than a release if the measurement turns out wrong.
313
+ */
314
+ export declare const SKILL_SURFACE_PATTERNS: readonly GuardPattern[];
315
+ /**
316
+ * Commands that destroy the machine or its data irrecoverably.
317
+ *
318
+ * TD-309: none of these were blocked by any harness. They are shipped through
319
+ * the policy snapshot rather than compiled into the gate, and at `warn` before
320
+ * `block` — see the note on `severity` below.
321
+ *
322
+ * ## What is deliberately allowed
323
+ *
324
+ * `rm -rf ./`, `rm -rf .`, `rm -rf *`, `rm -rf build/`, `rm -rf node_modules`
325
+ * and `rm -rf /home/…` are all ordinary developer commands and all pass. That
326
+ * is not an oversight to tighten later. A guard that blocks routine work
327
+ * teaches the developer to run `chflags nouchg` on the hook — the exact bypass
328
+ * `GOVERNANCE_BYPASS_PATTERNS` exists to stop. Blocking too much manufactures
329
+ * the adversary the rest of this file defends against.
330
+ *
331
+ * ## What no pattern here catches
332
+ *
333
+ * Shell redirection to a raw device (`cat /dev/zero > /dev/sda`), obfuscation
334
+ * (`eval "$(printf cm0gLXJmIC8= | base64 -d)"`), anything reached through a
335
+ * script file rather than typed as a command, and any of these run by a process
336
+ * the agent spawns rather than by the agent. This tier is a speed bump against
337
+ * accident and casual bypass. Containment is the proxy and OS permissions.
338
+ */
339
+ export declare const DESTRUCTIVE_COMMAND_PATTERNS: readonly GuardPattern[];
340
+ export declare function protectedPathShellPatterns(): readonly GuardPattern[];
341
+ /** Every compiled-in guard: the static floor. Destructive patterns are **not**
342
+ * here — they ship through the policy snapshot so they can be retracted
343
+ * without a release. `SKILL_SURFACE_PATTERNS` IS here, deliberately, despite
344
+ * also being new: unlike the destructive tier it is a deterministic path
345
+ * match with no content judgement to get wrong, so there is no measurement
346
+ * risk to hold it back from — see its own doc comment. As of TD-358's
347
+ * block-tier promotion these two entries are the DEGRADED-MODE baseline
348
+ * only: the steady state is `block`, delivered through the policy snapshot
349
+ * (`SKILL_SURFACE_TIER_SEVERITY` in `lib/policySnapshot.ts`) and additive on
350
+ * top of these, exactly the way the destructive tier layers on top of this
351
+ * same floor. */
352
+ export declare function staticFloorPatterns(): readonly GuardPattern[];
353
+ //# sourceMappingURL=protectedPaths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protectedPaths.d.ts","sourceRoot":"","sources":["../../src/harness/protectedPaths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AAIH,iEAAiE;AACjE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAiEtD,CAAA;AAMD;;;;;;;GAOG;AACH;;;;;;;;;GASG;AACH;;0DAE0D;AAC1D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAA;AAEvF,MAAM,WAAW,YAAY;IAC3B;4EACwE;IACxE,EAAE,EAAE,MAAM,CAAA;IACV,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAA;IACd;;;;;6BAKyB;IACzB,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;IAC9C;wDACoD;IACpD,MAAM,EAAE,MAAM,CAAA;IACd;;2BAEuB;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B;;;yCAGqC;IACrC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAA;IAC7B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAoCD,eAAO,MAAM,kBAAkB;IAC7B;;;;;;OAMG;iBACqD,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM;IAE9E,oEAAoE;;IAGpE;;;;;;;;;;;;;OAaG;IACH,8DAA8D;;IAM9D;;;;;;;;;;;OAWG;;CASK,CAAA;AAEV;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CA2BlE;AA0CD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,YAAY,EAyD5D,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,YAAY,EAyG1D,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,YAAY,EA+CxD,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,4BAA4B,EAAE,SAAS,YAAY,EAmJ/D,CAAA;AA2CD,wBAAgB,0BAA0B,IAAI,SAAS,YAAY,EAAE,CAEpE;AAED;;;;;;;;;;kBAUkB;AAClB,wBAAgB,mBAAmB,IAAI,SAAS,YAAY,EAAE,CAO7D"}