@yanlinglabs/winter-agent-runtime 0.0.27

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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +64 -0
  4. package/dist/checkpoint/file-history.d.ts +81 -0
  5. package/dist/checkpoint/rewind.d.ts +55 -0
  6. package/dist/checkpoint/seam.d.ts +47 -0
  7. package/dist/checkpoint/sink.d.ts +66 -0
  8. package/dist/commands/builtins-listing.d.ts +40 -0
  9. package/dist/commands/resolver.d.ts +103 -0
  10. package/dist/commands/seam.d.ts +53 -0
  11. package/dist/compaction/controller.d.ts +23 -0
  12. package/dist/compaction/retention.d.ts +35 -0
  13. package/dist/compaction/seam.d.ts +115 -0
  14. package/dist/compaction/summarizer.d.ts +79 -0
  15. package/dist/context/agent-listing.d.ts +39 -0
  16. package/dist/context/assembler.d.ts +46 -0
  17. package/dist/context/attachments.d.ts +104 -0
  18. package/dist/context/dynamic-sections.d.ts +31 -0
  19. package/dist/context/git-fixture.d.ts +18 -0
  20. package/dist/context/git-status.d.ts +16 -0
  21. package/dist/context/imports.d.ts +22 -0
  22. package/dist/context/injection.d.ts +53 -0
  23. package/dist/context/memory-key.d.ts +46 -0
  24. package/dist/context/memory.d.ts +28 -0
  25. package/dist/context/minimal-prompt.d.ts +5 -0
  26. package/dist/context/output-styles.d.ts +68 -0
  27. package/dist/context/plan-mode.d.ts +29 -0
  28. package/dist/context/request-layout.d.ts +138 -0
  29. package/dist/context/rules.d.ts +63 -0
  30. package/dist/context/seam.d.ts +136 -0
  31. package/dist/context/tool-epoch.d.ts +118 -0
  32. package/dist/context/winter-code-preset.d.ts +39 -0
  33. package/dist/context/winter-md.d.ts +81 -0
  34. package/dist/embedded-host.d.ts +48 -0
  35. package/dist/embedded-host.js +155 -0
  36. package/dist/embedded-protocol.d.ts +44 -0
  37. package/dist/embedded-worker.d.ts +1 -0
  38. package/dist/embedded-worker.js +74 -0
  39. package/dist/embedded.d.ts +34 -0
  40. package/dist/embedded.js +9 -0
  41. package/dist/engine.d.ts +1298 -0
  42. package/dist/hooks/additional-context.d.ts +21 -0
  43. package/dist/hooks/bounds.d.ts +6 -0
  44. package/dist/hooks/bridge-invoker.d.ts +3 -0
  45. package/dist/hooks/command-invoker.d.ts +52 -0
  46. package/dist/hooks/from-config.d.ts +31 -0
  47. package/dist/hooks/hook-stage.d.ts +25 -0
  48. package/dist/hooks/input-validator.d.ts +6 -0
  49. package/dist/hooks/reducer.d.ts +74 -0
  50. package/dist/hooks/registry.d.ts +33 -0
  51. package/dist/hooks/runner.d.ts +105 -0
  52. package/dist/index-584yahed.js +6037 -0
  53. package/dist/index-97t2rmtf.js +42 -0
  54. package/dist/index-9qgkpv56.js +27183 -0
  55. package/dist/index-bef62z3r.js +437 -0
  56. package/dist/index-rkhh0457.js +187 -0
  57. package/dist/index.d.ts +37 -0
  58. package/dist/index.js +353 -0
  59. package/dist/main.d.ts +1 -0
  60. package/dist/mcp/client.d.ts +105 -0
  61. package/dist/mcp/control-seam.d.ts +25 -0
  62. package/dist/mcp/control.d.ts +5 -0
  63. package/dist/mcp/elicitation.d.ts +35 -0
  64. package/dist/mcp/env.d.ts +12 -0
  65. package/dist/mcp/lifecycle.d.ts +142 -0
  66. package/dist/mcp/output-cap.d.ts +15 -0
  67. package/dist/mcp/state.d.ts +24 -0
  68. package/dist/mcp/test-fixtures.d.ts +88 -0
  69. package/dist/mcp/transports/__fixtures__/stdio-server.d.ts +1 -0
  70. package/dist/mcp/transports/http.d.ts +5 -0
  71. package/dist/mcp/transports/sdk.d.ts +5 -0
  72. package/dist/mcp/transports/sse.d.ts +3 -0
  73. package/dist/mcp/transports/stdio.d.ts +35 -0
  74. package/dist/mcp/winter-server.d.ts +2 -0
  75. package/dist/messaging/reference-adapter.d.ts +88 -0
  76. package/dist/messaging/router.d.ts +8 -0
  77. package/dist/paths/project-dir-name.d.ts +2 -0
  78. package/dist/paths/temp.d.ts +25 -0
  79. package/dist/permissions/approvals.d.ts +107 -0
  80. package/dist/permissions/auto/caches.d.ts +53 -0
  81. package/dist/permissions/auto/config.d.ts +37 -0
  82. package/dist/permissions/auto/engine.d.ts +74 -0
  83. package/dist/permissions/auto/envelope.d.ts +45 -0
  84. package/dist/permissions/auto/inheritance.d.ts +27 -0
  85. package/dist/permissions/edit-recognition.d.ts +30 -0
  86. package/dist/permissions/evaluator.d.ts +284 -0
  87. package/dist/permissions/file-rules.d.ts +384 -0
  88. package/dist/permissions/grammar.d.ts +113 -0
  89. package/dist/permissions/paths.d.ts +32 -0
  90. package/dist/permissions/policy-state.d.ts +64 -0
  91. package/dist/permissions/prompt-stage.d.ts +3 -0
  92. package/dist/permissions/protected.d.ts +54 -0
  93. package/dist/permissions/ruleset.d.ts +134 -0
  94. package/dist/permissions/shell-structure.d.ts +41 -0
  95. package/dist/plugins/bundle.d.ts +100 -0
  96. package/dist/plugins/installed.d.ts +30 -0
  97. package/dist/plugins/loader.d.ts +56 -0
  98. package/dist/plugins/manifest.d.ts +115 -0
  99. package/dist/production-wiring.d.ts +340 -0
  100. package/dist/protocol/channel.d.ts +22 -0
  101. package/dist/provider/advisor-route.d.ts +47 -0
  102. package/dist/provider/bridge.d.ts +124 -0
  103. package/dist/provider/classifier/model-classifier.d.ts +82 -0
  104. package/dist/provider/classifier/prompt.d.ts +62 -0
  105. package/dist/provider/classifier/verdict-schema.d.ts +83 -0
  106. package/dist/provider/credential-api.d.ts +160 -0
  107. package/dist/provider/family-listing.d.ts +27 -0
  108. package/dist/provider/first-party.d.ts +4 -0
  109. package/dist/provider/keychain-store.d.ts +59 -0
  110. package/dist/provider/lean-prompt.d.ts +7 -0
  111. package/dist/provider/mock.d.ts +55 -0
  112. package/dist/provider/scenario-fake.d.ts +96 -0
  113. package/dist/provider/selection.d.ts +115 -0
  114. package/dist/provider/session-provider.d.ts +426 -0
  115. package/dist/provider/slots.d.ts +120 -0
  116. package/dist/provider/stream-frames.d.ts +25 -0
  117. package/dist/provider/tool-secret.d.ts +57 -0
  118. package/dist/rpc/bridge.d.ts +14 -0
  119. package/dist/rpc/mcp-control.d.ts +26 -0
  120. package/dist/runtime.d.ts +14 -0
  121. package/dist/sandbox/profile.d.ts +249 -0
  122. package/dist/sandbox/spawn.d.ts +139 -0
  123. package/dist/settings/env-filter.d.ts +52 -0
  124. package/dist/settings/loaders/hooks.d.ts +44 -0
  125. package/dist/settings/loaders/mcp-config.d.ts +83 -0
  126. package/dist/settings/loaders/plugin-mcp.d.ts +3 -0
  127. package/dist/settings/loaders/strict-plugin-only.d.ts +13 -0
  128. package/dist/settings/resolve.d.ts +2 -0
  129. package/dist/settings/sources.d.ts +2 -0
  130. package/dist/settings/trust.d.ts +36 -0
  131. package/dist/skills/attachment.d.ts +25 -0
  132. package/dist/skills/frontmatter.d.ts +64 -0
  133. package/dist/skills/index.d.ts +16 -0
  134. package/dist/skills/listing.d.ts +89 -0
  135. package/dist/skills/loader.d.ts +104 -0
  136. package/dist/skills/option.d.ts +68 -0
  137. package/dist/skills/permission-rules.d.ts +21 -0
  138. package/dist/skills/runtime.d.ts +21 -0
  139. package/dist/skills/store.d.ts +163 -0
  140. package/dist/store/continuation-attach.d.ts +44 -0
  141. package/dist/store/dialect.d.ts +526 -0
  142. package/dist/store/provider-state.d.ts +188 -0
  143. package/dist/store/resume.d.ts +92 -0
  144. package/dist/structured/ajv-seam.d.ts +7 -0
  145. package/dist/structured/descriptor.d.ts +9 -0
  146. package/dist/structured/seam.d.ts +51 -0
  147. package/dist/structured/validator.d.ts +22 -0
  148. package/dist/subagents/activity.d.ts +13 -0
  149. package/dist/subagents/availability.d.ts +30 -0
  150. package/dist/subagents/builtin-agents.d.ts +37 -0
  151. package/dist/subagents/child-engine.d.ts +198 -0
  152. package/dist/subagents/child-handle.d.ts +344 -0
  153. package/dist/subagents/definitions.d.ts +189 -0
  154. package/dist/subagents/fork.d.ts +55 -0
  155. package/dist/subagents/git-root.d.ts +1 -0
  156. package/dist/subagents/limits.d.ts +28 -0
  157. package/dist/subagents/notification-queue.d.ts +233 -0
  158. package/dist/subagents/plugin-agents.d.ts +5 -0
  159. package/dist/subagents/policy.d.ts +46 -0
  160. package/dist/subagents/register-default-factory.d.ts +66 -0
  161. package/dist/subagents/resolution.d.ts +56 -0
  162. package/dist/subagents/restore.d.ts +9 -0
  163. package/dist/subagents/roster.d.ts +17 -0
  164. package/dist/subagents/test-fakes.d.ts +12 -0
  165. package/dist/subagents/tool-pools.d.ts +69 -0
  166. package/dist/subagents/watchdog.d.ts +13 -0
  167. package/dist/subagents/workspace.d.ts +27 -0
  168. package/dist/testing.d.ts +5 -0
  169. package/dist/testing.js +194 -0
  170. package/dist/tools/background-tasks.d.ts +10 -0
  171. package/dist/tools/descriptors/_shared.d.ts +34 -0
  172. package/dist/tools/descriptors/advisor.d.ts +1 -0
  173. package/dist/tools/descriptors/agent.d.ts +47 -0
  174. package/dist/tools/descriptors/artifact.d.ts +1 -0
  175. package/dist/tools/descriptors/ask-user-question.d.ts +1 -0
  176. package/dist/tools/descriptors/bash.d.ts +20 -0
  177. package/dist/tools/descriptors/claude-design.d.ts +1 -0
  178. package/dist/tools/descriptors/cron-create.d.ts +1 -0
  179. package/dist/tools/descriptors/cron-delete.d.ts +1 -0
  180. package/dist/tools/descriptors/cron-list.d.ts +1 -0
  181. package/dist/tools/descriptors/edit.d.ts +1 -0
  182. package/dist/tools/descriptors/end-conversation.d.ts +1 -0
  183. package/dist/tools/descriptors/enter-plan-mode.d.ts +1 -0
  184. package/dist/tools/descriptors/enter-worktree.d.ts +1 -0
  185. package/dist/tools/descriptors/exit-plan-mode.d.ts +1 -0
  186. package/dist/tools/descriptors/exit-worktree.d.ts +1 -0
  187. package/dist/tools/descriptors/glob.d.ts +1 -0
  188. package/dist/tools/descriptors/grep.d.ts +1 -0
  189. package/dist/tools/descriptors/index.d.ts +59 -0
  190. package/dist/tools/descriptors/list-agents.d.ts +1 -0
  191. package/dist/tools/descriptors/list-mcp-resources-tool.d.ts +1 -0
  192. package/dist/tools/descriptors/lsp.d.ts +1 -0
  193. package/dist/tools/descriptors/monitor.d.ts +1 -0
  194. package/dist/tools/descriptors/notebook-edit.d.ts +1 -0
  195. package/dist/tools/descriptors/powershell.d.ts +1 -0
  196. package/dist/tools/descriptors/projects.d.ts +1 -0
  197. package/dist/tools/descriptors/propose-goal.d.ts +1 -0
  198. package/dist/tools/descriptors/propose-skills.d.ts +1 -0
  199. package/dist/tools/descriptors/push-notification.d.ts +1 -0
  200. package/dist/tools/descriptors/read-mcp-resource-dir-tool.d.ts +1 -0
  201. package/dist/tools/descriptors/read-mcp-resource-tool.d.ts +1 -0
  202. package/dist/tools/descriptors/read-notifications.d.ts +1 -0
  203. package/dist/tools/descriptors/read.d.ts +1 -0
  204. package/dist/tools/descriptors/refresh-mcp-tools.d.ts +1 -0
  205. package/dist/tools/descriptors/remote-trigger.d.ts +1 -0
  206. package/dist/tools/descriptors/repl.d.ts +1 -0
  207. package/dist/tools/descriptors/report-findings.d.ts +1 -0
  208. package/dist/tools/descriptors/schedule-wakeup.d.ts +1 -0
  209. package/dist/tools/descriptors/send-feedback.d.ts +1 -0
  210. package/dist/tools/descriptors/send-message.d.ts +1 -0
  211. package/dist/tools/descriptors/send-user-file.d.ts +1 -0
  212. package/dist/tools/descriptors/share-onboarding-guide.d.ts +1 -0
  213. package/dist/tools/descriptors/show-onboarding-role-picker.d.ts +1 -0
  214. package/dist/tools/descriptors/skill.d.ts +1 -0
  215. package/dist/tools/descriptors/structured-output.d.ts +1 -0
  216. package/dist/tools/descriptors/task-create.d.ts +1 -0
  217. package/dist/tools/descriptors/task-get.d.ts +1 -0
  218. package/dist/tools/descriptors/task-list.d.ts +1 -0
  219. package/dist/tools/descriptors/task-output.d.ts +1 -0
  220. package/dist/tools/descriptors/task-stop.d.ts +1 -0
  221. package/dist/tools/descriptors/task-update.d.ts +1 -0
  222. package/dist/tools/descriptors/todo-write.d.ts +1 -0
  223. package/dist/tools/descriptors/tool-search.d.ts +1 -0
  224. package/dist/tools/descriptors/wait-for-mcp-servers.d.ts +1 -0
  225. package/dist/tools/descriptors/web-fetch.d.ts +8 -0
  226. package/dist/tools/descriptors/web-search.d.ts +15 -0
  227. package/dist/tools/descriptors/winter-list-agents.d.ts +1 -0
  228. package/dist/tools/descriptors/winter-send-message.d.ts +1 -0
  229. package/dist/tools/descriptors/workflow.d.ts +1 -0
  230. package/dist/tools/descriptors/write.d.ts +1 -0
  231. package/dist/tools/impl/_caller.d.ts +14 -0
  232. package/dist/tools/impl/_domains.d.ts +25 -0
  233. package/dist/tools/impl/_exa-client.d.ts +122 -0
  234. package/dist/tools/impl/_exa-session-client.d.ts +23 -0
  235. package/dist/tools/impl/_inner-model.d.ts +135 -0
  236. package/dist/tools/impl/_search-budget.d.ts +36 -0
  237. package/dist/tools/impl/_web-fetch-cache.d.ts +37 -0
  238. package/dist/tools/impl/_web-fetch-html.d.ts +26 -0
  239. package/dist/tools/impl/_web-fetch-net.d.ts +99 -0
  240. package/dist/tools/impl/_web-search-assembler.d.ts +57 -0
  241. package/dist/tools/impl/advisor.d.ts +37 -0
  242. package/dist/tools/impl/agent.d.ts +10 -0
  243. package/dist/tools/impl/ask-user-question.d.ts +5 -0
  244. package/dist/tools/impl/background-task-runtime.d.ts +272 -0
  245. package/dist/tools/impl/bash.d.ts +78 -0
  246. package/dist/tools/impl/cron.d.ts +11 -0
  247. package/dist/tools/impl/edit.d.ts +1 -0
  248. package/dist/tools/impl/enter-plan-mode.d.ts +4 -0
  249. package/dist/tools/impl/enter-worktree.d.ts +25 -0
  250. package/dist/tools/impl/exit-plan-mode.d.ts +4 -0
  251. package/dist/tools/impl/exit-worktree.d.ts +4 -0
  252. package/dist/tools/impl/glob.d.ts +1 -0
  253. package/dist/tools/impl/grep.d.ts +19 -0
  254. package/dist/tools/impl/index.d.ts +37 -0
  255. package/dist/tools/impl/list-agents.d.ts +7 -0
  256. package/dist/tools/impl/list-mcp-resources-tool.d.ts +9 -0
  257. package/dist/tools/impl/monitor.d.ts +66 -0
  258. package/dist/tools/impl/notebook-edit.d.ts +1 -0
  259. package/dist/tools/impl/push-notification.d.ts +4 -0
  260. package/dist/tools/impl/read-ladder.d.ts +25 -0
  261. package/dist/tools/impl/read-mcp-resource-dir-tool.d.ts +9 -0
  262. package/dist/tools/impl/read-mcp-resource-tool.d.ts +9 -0
  263. package/dist/tools/impl/read-notifications.d.ts +5 -0
  264. package/dist/tools/impl/read.d.ts +44 -0
  265. package/dist/tools/impl/refresh-mcp-tools.d.ts +8 -0
  266. package/dist/tools/impl/report-findings.d.ts +1 -0
  267. package/dist/tools/impl/schedule-wakeup.d.ts +2 -0
  268. package/dist/tools/impl/send-message.d.ts +7 -0
  269. package/dist/tools/impl/skill.d.ts +5 -0
  270. package/dist/tools/impl/task-graph.d.ts +1 -0
  271. package/dist/tools/impl/task-output.d.ts +16 -0
  272. package/dist/tools/impl/task-stop.d.ts +11 -0
  273. package/dist/tools/impl/todo-write.d.ts +8 -0
  274. package/dist/tools/impl/tool-search.d.ts +4 -0
  275. package/dist/tools/impl/wait-for-mcp-servers.d.ts +29 -0
  276. package/dist/tools/impl/web-fetch.d.ts +36 -0
  277. package/dist/tools/impl/web-search.d.ts +30 -0
  278. package/dist/tools/impl/workflow.d.ts +5 -0
  279. package/dist/tools/impl/write.d.ts +8 -0
  280. package/dist/tools/paths-seam.d.ts +6 -0
  281. package/dist/tools/read-state.d.ts +12 -0
  282. package/dist/tools/registry.d.ts +423 -0
  283. package/dist/tools/task-graph-store.d.ts +61 -0
  284. package/dist/toolsearch/aliases.d.ts +26 -0
  285. package/dist/toolsearch/exposure.d.ts +30 -0
  286. package/dist/toolsearch/ranking.d.ts +6 -0
  287. package/dist/toolsearch/search.d.ts +45 -0
  288. package/dist/version.d.ts +1 -0
  289. package/dist/version.js +5 -0
  290. package/dist/web/fetchable-url.d.ts +28 -0
  291. package/dist/web/preapproved-hosts.d.ts +52 -0
  292. package/dist/web/private-address.d.ts +55 -0
  293. package/dist/web/session-runtime.d.ts +86 -0
  294. package/dist/workflows/bridge.d.ts +87 -0
  295. package/dist/workflows/budget.d.ts +24 -0
  296. package/dist/workflows/host-registry.d.ts +142 -0
  297. package/dist/workflows/journal.d.ts +29 -0
  298. package/dist/workflows/meta.d.ts +45 -0
  299. package/dist/workflows/registry.d.ts +24 -0
  300. package/dist/workflows/runtime.d.ts +254 -0
  301. package/dist/workflows/sandbox.d.ts +49 -0
  302. package/dist/workflows/script-api.d.ts +58 -0
  303. package/dist/workflows/seam.d.ts +92 -0
  304. package/dist/workflows/semaphore.d.ts +16 -0
  305. package/dist/workflows/store.d.ts +177 -0
  306. package/dist/workflows/subprocess-entry.d.ts +38 -0
  307. package/dist/workflows/subprocess-entry.js +14 -0
  308. package/dist/workflows/transcript.d.ts +56 -0
  309. package/dist/workflows/types.d.ts +84 -0
  310. package/dist/workflows/worker-harness.d.ts +45 -0
  311. package/package.json +76 -0
@@ -0,0 +1,384 @@
1
+ export type FileRuleKind = "edit" | "read";
2
+ /**
3
+ * SV-7 (the router same-view test): claude's file-rule grammar has only TWO pattern kinds --
4
+ * `Edit(...)` and `Read(...)`. Dump-confirmed: `ln`'s own dispatch switch has exactly two cases
5
+ * (`case"edit":return tn;case"read":return wt`, each a SINGLE literal tool-name string `ub` filters
6
+ * `ruleValue.toolName` against by exact equality) -- there is no third "write" kind anywhere in the
7
+ * data model. Claude's own WRITE decision function (`zC`) ALWAYS consults `"edit"`-kind rules,
8
+ * regardless of which literal write-shaped tool called it -- this is what makes an `Edit(...)` ask
9
+ * rule fire before a **Write** on claude (the router's own SV-7 measurement), and what makes a
10
+ * `Write(...)`-toolName rule a Winter-only spelling with no claude analogue at all: `ub` filtering
11
+ * on the literal string "Write" never runs, because nothing ever calls it with that string.
12
+ *
13
+ * Every `FILE_RULE_TOOLS` member (grammar.ts) routes to exactly one kind, on every direction (allow,
14
+ * ask, deny alike -- the ruling's own "for both ALLOW and DENY" instruction, extended to ask since
15
+ * ask shares deny's conservative "cross tools" posture throughout this codebase already).
16
+ */
17
+ export declare function fileRuleKindFor(toolName: string): FileRuleKind | undefined;
18
+ /**
19
+ * The ONE literal tool name a rule must be AUTHORED under to ever be consulted for `kind` -- claude's
20
+ * own `ub` filters `ruleValue.toolName` by EXACT STRING EQUALITY against a single literal per kind
21
+ * (`tn`/`"Edit"` for `"edit"`, `wt`/`"Read"` for `"read"`; dump-confirmed, `ln`'s own two-case
22
+ * switch), never against every tool that happens to share the kind. This is what makes SV-7's
23
+ * "reverse" finding true: a rule AUTHORED as `Write(...)`, `NotebookEdit(...)`, `Glob(...)` or
24
+ * `Grep(...)` is dead code claude never reads for ANY call -- not even a call from that SAME literal
25
+ * tool -- because `ub` was never invoked with that string. `Write`/`NotebookEdit`/`Glob`/`Grep`
26
+ * remain valid rule-authoring tool names SYNTACTICALLY (grammar.ts's `FILE_RULE_TOOLS` still parses
27
+ * them -- Winter does not forbid authoring one), but this function is what `findMatchingFileRuleEntry`
28
+ * (evaluator.ts) filters CANDIDATES with, so only `Edit(...)`/`Read(...)`-authored rules ever reach
29
+ * a group.
30
+ */
31
+ export declare function canonicalFileRuleAuthoringToolName(kind: FileRuleKind): "Edit" | "Read";
32
+ /** A sentinel distinct from `null` ("resolve against cwd"): a `/`-anchored rule with no resolvable settings-source directory is INERT, never falls back to cwd. */
33
+ declare const INERT_ANCHOR: unique symbol;
34
+ export interface FileRuleAnchor {
35
+ /** The pattern text, relative to `root`, in `ignore`-package (gitignore) grammar. */
36
+ relativePattern: string;
37
+ /** `null` means "resolve against cwd" (`Ma`'s own `P ?? te()`, ported as `root ?? opts.cwd`); the sentinel means the anchor can never match anything. */
38
+ root: string | null | typeof INERT_ANCHOR;
39
+ }
40
+ /**
41
+ * `jOe` (dump-confirmed): the FOUR anchor spellings WS-07 §3.1 documents, resolved to a
42
+ * `{relativePattern, root}` pair -- ported exactly, including the leading-slash-KEPT behaviour on
43
+ * the three anchored forms (`//x`, `~/x`, `/x`) that is what makes them root-anchored in gitignore
44
+ * terms, and its ABSENCE on `./x`/bare `x` that is what lets `deny ./.env` reach `pkg/.env` (C-1's
45
+ * own example) -- a bare pattern with no leading slash and no inner slash is exactly the shape the
46
+ * `ignore` package's own `^(?=[^^])` -> `(?:^|\/)` replacer un-anchors.
47
+ *
48
+ * A bare `~` (no trailing slash) is NOT specially handled by claude's own `jOe` either -- it falls
49
+ * through to the final else branch as a literal filename pattern `"~"`, cwd-anchored. Ported
50
+ * faithfully rather than "fixed", matching this module's own "port what was measured" discipline.
51
+ *
52
+ * `sourceDir` is claude's `bl(source)` -- the settings-source-derived root for a `/`-anchored rule.
53
+ * Since fix round 11 a settings-tier rule carries it (`SourcedRuleEntry.sourceDir`, set by
54
+ * production-wiring.ts's `buildSettingsRuleSeed` per claude's `Wyt`), and a `/`-anchored rule resolves
55
+ * against it. When it is absent -- a rule from Options, canUseTool or a plugin -- the rule is inert
56
+ * (the `INERT_ANCHOR` root below, treated as "no group to match against" by `matchFileRulesGrouped`).
57
+ */
58
+ export declare function resolveFileRuleAnchor(pattern: string, opts: {
59
+ home: string;
60
+ sourceDir?: string | undefined;
61
+ }): FileRuleAnchor;
62
+ /**
63
+ * WS-21 fix round 10, item C: a Read/Edit rule's own pattern, resolved to ONE absolute filesystem
64
+ * path -- for the sandbox's own `subpath` rule (sandbox/profile.ts's `denyWritePaths`/
65
+ * `denyReadPaths`/`writableRoots`), which has no glob grammar of its own to hand a pattern string
66
+ * to; a real Seatbelt `subpath` already means "this directory and everything under it," so it needs
67
+ * ONE real path, never a pattern.
68
+ *
69
+ * `undefined` in two cases, matching claude's own observable posture (dump-confirmed, `Jm`: `let{
70
+ * allowOnly:t}=at.getFsWriteConfig();if(t.some(eg))return!0` -- ANY glob-shaped entry in the
71
+ * write-allow set makes claude's OWN sandbox stop trying to restrict writes via that mechanism at
72
+ * all, relying on the separate, glob-aware PERMISSION-RULE layer instead, which is unaffected by
73
+ * this and stays the real enforcement point):
74
+ * - the pattern is INERT (a bare `/`-anchored rule with no resolvable settings-source root --
75
+ * `resolveFileRuleAnchor`'s own pre-existing posture, unchanged here);
76
+ * - the pattern is genuinely GLOB-SHAPED once a single TRAILING `/**` is stripped (redundant with
77
+ * `subpath`'s own "and everything under it" semantics, so it is not itself disqualifying --
78
+ * `Edit(//repo/secrets/**)` becomes the plain path `/repo/secrets`) -- a glob ANYWHERE else
79
+ * (`src/*.ts`, `[wip]`, `a?b`) cannot become one exact path at all.
80
+ * A caller that gets `undefined` back simply does not add this rule to the sandbox's own filesystem
81
+ * lists; the permission-rule layer (`evaluate()`) still enforces it in full, exactly as it always has.
82
+ */
83
+ export declare function resolveFileRuleAbsolutePath(pattern: string, opts: {
84
+ cwd: string;
85
+ home: string;
86
+ sourceDir?: string;
87
+ }): string | undefined;
88
+ /**
89
+ * WS-21 fix round 11 ("important" item): the sibling of `resolveFileRuleAbsolutePath` that does NOT
90
+ * drop a genuinely glob-shaped pattern -- it resolves the SAME anchor/root as that function but
91
+ * returns the absolute text WITH any remaining glob characters intact (a redundant trailing `/**` is
92
+ * still stripped first, identically, since `subpath`'s/the recursive-regex-suffix's own "and
93
+ * everything under it" semantics already cover it). `undefined` only for the one case that has no
94
+ * absolute form at all -- an INERT `/`-anchored pattern with no resolvable settings-source root,
95
+ * unchanged from `resolveFileRuleAbsolutePath`'s own posture.
96
+ *
97
+ * Exists because claude's own deny-rendering path (`dR`, dump byte 15365699 region) does NOT drop a
98
+ * glob-shaped deny the way `Jm`'s write-ALLOW-only short-circuit does (round 10's own `Jm` finding,
99
+ * `resolveFileRuleAbsolutePath`'s own header) -- a glob-shaped DENY instead becomes an SBPL `(regex
100
+ * ...)` clause (claude's `Li` (dump byte 15365905) / `Rt` (dump byte 15282610)) rather than being silently
101
+ * unenforced by the sandbox layer. Callers check `isGlobShapedFileRulePattern` on the result to
102
+ * decide `subpath` vs a `globToSbplRegexSource`/`recursiveGlobToSbplRegexSource` conversion; ALLOW
103
+ * entries keep using `resolveFileRuleAbsolutePath` (glob-shaped dropped), per the controller's own
104
+ * explicit ruling: "Dropping glob-shaped ALLOW rules stays as it is, because that's stricter."
105
+ */
106
+ export declare function resolveFileRuleAbsoluteGlobText(pattern: string, opts: {
107
+ cwd: string;
108
+ home: string;
109
+ sourceDir?: string;
110
+ }): string | undefined;
111
+ /**
112
+ * claude's own `Rt` (dump byte 15282610: `e.includes("*")||e.includes("?")||e.includes("[")||e.includes("]")`),
113
+ * confirmed byte-equivalent to this module's own pre-existing glob-char test. Kept as the pure claude
114
+ * primitive; the sandbox DENY split (`splitDenyPathsByGlobShape`/`globDenyEntriesOf`) classifies with
115
+ * `scanDenyPathGlob` below instead (fix round 17, R.3 C-1).
116
+ */
117
+ export declare function isGlobShapedFileRulePattern(text: string): boolean;
118
+ /**
119
+ * Fix round 12 ("Important" item, claude's own `ed`, dump byte 15367994, found in the SAME chunk as
120
+ * `Ch`/`mR`/`pR` below): every ANCESTOR directory of `path`, walking up via `dirname` until reaching
121
+ * `/` or a fixed point -- does NOT include `path` itself, nor `/`. Feeds the ancestor-rename-bypass
122
+ * fix: claude's own write/read sandbox profiles additionally deny `file-write-unlink`/
123
+ * `file-write-create` on every ancestor of a denied path (and of a glob deny's own fixed prefix), so
124
+ * a sandboxed `mv <ancestor> <elsewhere> && <write inside where it used to be> && mv <elsewhere>
125
+ * <ancestor>` cannot rename the ancestor out of the way and back to slip a write past the deny.
126
+ */
127
+ export declare function ancestorDirectoriesOf(path: string): string[];
128
+ export declare function globToSbplRegexSource(absoluteGlob: string): string;
129
+ /**
130
+ * claude's own `td` (dump byte 15365977: `Po(e).slice(0,-1)+"(/.*)?$"`) -- `globToSbplRegexSource`'s
131
+ * own whole-string match, WIDENED to also match "the pattern's own match point, optionally followed
132
+ * by `/` and anything deeper" -- the regex equivalent of `subpath`'s own implicit recursive semantics
133
+ * (a plain, non-glob deny already renders as `subpath`, which covers a directory AND everything under
134
+ * it with no extra syntax). claude's own `dR` (the deny-clause builder, same dump region) always uses
135
+ * this recursive form for a glob-shaped deny's OWN base clause -- never the bare `Li`/
136
+ * `globToSbplRegexSource` form, which claude reserves for an ALLOW-carve-out entry nested inside a
137
+ * deny (a feature this port does not carry -- see `resolveFileRuleAbsoluteGlobText`'s own header).
138
+ */
139
+ export declare function recursiveGlobToSbplRegexSource(absoluteGlob: string): string;
140
+ /**
141
+ * WS-21 fix round 11: the ONE place a plain `sandbox.filesystem.denyWrite`/`denyRead` string list
142
+ * (settings.json's own, user-typed, and `deriveSandboxPathsFromRules`'s own rule-derived denies,
143
+ * which now may ALSO contain glob-shaped text -- see `resolveFileRuleAbsoluteGlobText`'s own header)
144
+ * gets split by glob-shape before reaching `SeatbeltProfileInput`/`RunCommandOptions`: a non-glob
145
+ * entry stays a plain path (`subpath`, unchanged); a glob-shaped one is converted via
146
+ * `recursiveGlobToSbplRegexSource` (the recursive form, matching `subpath`'s own implicit
147
+ * "and everything under it" semantics and claude's own `dR`, which always uses the recursive form for
148
+ * a deny's own base clause). Called once per caller (tools/impl/bash.ts, tools/impl/monitor.ts) --
149
+ * kept as one shared, tested primitive rather than two hand-copies, per this codebase's own
150
+ * "a second copy would be exactly the kind of drift risk this whole phase's review lens exists to
151
+ * catch" precedent (evaluator.ts's `extractCandidateWritePaths`, verbatim).
152
+ *
153
+ * Fix round 12: also returns `globFixedPrefixes` -- for each glob-shaped entry, its OWN canonicalized
154
+ * fixed-prefix directory (claude's own `Rh(u)`, `undefined`/dropped when it resolves to `/`, matching
155
+ * `Ch`'s own `if(p==="/")continue`). Feeds the ancestor-rename-bypass port
156
+ * (`SeatbeltProfileInput.denyWriteGlobFixedPrefixes`/`denyReadGlobFixedPrefixes`, sandbox/profile.ts):
157
+ * the plain `paths` entries need only their OWN ancestors walked (`ed`, `ancestorDirectoriesOf`
158
+ * above) to close the bypass; a glob-shaped deny ALSO needs its fixed prefix walked, and the prefix
159
+ * itself added as a literal deny target (claude's own `Ch` adds both).
160
+ *
161
+ * Fix round 17 (R.3 C-1): classified by `scanDenyPathGlob`, not by claude's `Rt` alone -- an entry
162
+ * whose only glob syntax is one-character bracket classes (`/x/[[]wip] app/.winter/skills`, a literal
163
+ * path spelled for the glob grammar) lands in `paths` UNESCAPED (`/x/[wip] app/.winter/skills`), and a
164
+ * glob entry's fixed prefix runs through such classes. Winter-only hardening (R.3 C-1); claude's
165
+ * `Rt`/`Li` stop at the first `[` -- see `scanDenyPathGlob`'s own header.
166
+ */
167
+ export declare function splitDenyPathsByGlobShape(paths: readonly string[]): {
168
+ paths: string[];
169
+ regexes: string[];
170
+ globFixedPrefixes: string[];
171
+ };
172
+ /** One glob-shaped deny entry, its recursive SBPL regex source PAIRED with its own fixed-prefix
173
+ * directory -- `splitDenyPathsByGlobShape`'s own `regexes`/`globFixedPrefixes` are two independently
174
+ * FILTERED flat arrays (the latter drops a "/" prefix entirely) with no positional correspondence
175
+ * once any entry is dropped from one but not the other; `fixedPrefix` here is NEVER dropped -- it is
176
+ * always the literal string `"/"` in that case (claude's own `Rh` returns `"/"` too, and `fR`'s own
177
+ * skip/ancestor logic reads that value directly rather than treating "no prefix" as a distinct case). */
178
+ export interface GlobDenyEntry {
179
+ regex: string;
180
+ fixedPrefix: string;
181
+ }
182
+ /**
183
+ * Fix round 13 ("Important" item 1, claude's own `fR`, dump byte 15367091): the PAIRED form
184
+ * `buildReadDenyKeepInPlaceBlock` (sandbox/profile.ts) needs -- see `GlobDenyEntry`'s own header for
185
+ * why `splitDenyPathsByGlobShape`'s own two flat arrays cannot answer this. Scoped to glob-shaped
186
+ * entries only (a plain entry needs no pairing at all -- its own path IS both its recursive-clause
187
+ * anchor and its ancestor-walk root, `buildReadDenyKeepInPlaceBlock` uses `paths` directly for that).
188
+ */
189
+ export declare function globDenyEntriesOf(paths: readonly string[]): GlobDenyEntry[];
190
+ /**
191
+ * `xi` (dump-confirmed): collapses repeated slashes, and specially handles a LEADING BOM so it
192
+ * cannot accidentally trigger gitignore's own `!`/`#` line-directive meaning (negation/comment). A
193
+ * bare leading BOM with no `!`/`#` after it is DELETED outright (empirically verified: the first of
194
+ * the two `.replace()` calls below always consumes a leading BOM, since `^` in its own regex
195
+ * is unconditional and only the FOLLOWING `[!#]?` is optional -- the second `.replace(/^/,
196
+ * "[]")` is therefore unreachable dead code in the pinned binary's own source whenever the
197
+ * input genuinely starts with a BOM, ported here as harmless dead code too rather than "corrected"
198
+ * into a change of behaviour this module was not asked to make). A leading BOM immediately followed
199
+ * by `!` or `#` becomes an escaped literal `!`/`#` (so the directive character survives as TEXT to
200
+ * match, not as a line-level instruction).
201
+ */
202
+ export declare function normalizeFileRulePattern(relativePattern: string): string;
203
+ /**
204
+ * `ki` (dump-confirmed): a pattern ending in `/**` is rewritten before being fed to `ignore()`.
205
+ * - For DENY/ASK (`isAllow: false`): the trailing `/**` is simply dropped (`x/**` -> `x`), and the
206
+ * result is left UNANCHORED (no leading `/` added) whenever it already has an inner `/`, is not an
207
+ * allow rule, or already starts with `!`/`#` -- i.e. almost always for deny/ask. This is C-1's own
208
+ * "`ki` turns a deny `x/**` into an unanchored `x`" finding: the bare `x` then matches at ANY
209
+ * depth under the `ignore` package's own un-anchoring rule, covering everything under a directory
210
+ * named `x` anywhere, not merely the literal anchor-relative `x/`.
211
+ * - For ALLOW, when the stripped form has NO inner `/` (a single segment) and does not start with
212
+ * `!`/`#`: the result is instead explicitly re-anchored (`x/**` -> `/x`), so `allow x/**` stays
213
+ * scoped to the anchor root rather than becoming an anywhere-match the way the deny/ask case does.
214
+ * This asymmetry is real and claude's own (not the allow-exact-only asymmetry the controller
215
+ * retired) -- it survives because it is measured, not invented.
216
+ * - A pattern whose stripped form is empty or all-slashes (`/**`, `//**`) is left as `/**`.
217
+ * - Any pattern that does NOT end in `/**` passes through unchanged.
218
+ */
219
+ export declare function unanchorTrailingDoubleStar(pattern: string, isAllow: boolean): string;
220
+ export interface FileRuleCandidate<TEntry> {
221
+ entry: TEntry;
222
+ /** The rule's own specifier text, exactly as authored (the `jOe`/`xi`/`ki` chain runs on this). */
223
+ pattern: string;
224
+ /** `bl(source)`'s stand-in for a `/`-anchored rule -- see `resolveFileRuleAnchor`'s own header. Absent = every `/`-anchored candidate is inert. */
225
+ sourceDir?: string | undefined;
226
+ }
227
+ /**
228
+ * Item 2 (fix round 9), REVISED by round 10's own item-3 ruling: a malformed pattern's own compile
229
+ * failure is a THROW out of `matchFileRulesGrouped`, not a direction-aware return value. Round 9
230
+ * tried to resolve the failure INSIDE this function (denyAsk -> the broken group's first entry,
231
+ * allow -> null); round 10's controller ruling is that this is not what claude does -- claude's own
232
+ * `Ma` has no per-group catch at all (only the per-TOOL-CALL one far above it, at `d8t`/`ome`'s own
233
+ * boundary), so ONE throwing group aborts the WHOLE permission check for that call, exactly the same
234
+ * way regardless of which direction (deny/ask/allow) was being evaluated when it happened. This
235
+ * class is what makes that propagation typed rather than "any thrown Error" -- caught exactly once,
236
+ * at `evaluator.ts`'s own `evaluate()` (the "decide this one call" boundary), and turned into the
237
+ * generic fail-closed deny `d8t`'s own hardcoded fallback produces.
238
+ */
239
+ export declare class FileRuleCompileError extends Error {
240
+ constructor(message: string, options?: {
241
+ cause?: unknown;
242
+ });
243
+ }
244
+ /**
245
+ * `ln`+`Ma`, combined into one grouped match: builds ONE `ignore()` instance per anchor ROOT from
246
+ * every candidate (see this module's header for why grouping is load-bearing, not cosmetic), then
247
+ * tests `path` against each root's group in turn, returning the FIRST candidate's own `entry` whose
248
+ * group matched -- `null` when nothing matched anywhere. `behavior` is `"allow"` or `"denyAsk"`,
249
+ * mirroring `matchFileRule`'s own existing direction vocabulary (never allow AND denyAsk on the
250
+ * page a caller passed to `ki`, exactly as `ln`'s `r==="allow"` check is exactly `behavior==="allow"`
251
+ * here too).
252
+ *
253
+ * THROWS `FileRuleCompileError` (fix round 10, item 3) when any consulted anchor root's own
254
+ * candidate patterns fail to compile into a real `ignore()` instance -- never resolved to `null`
255
+ * or a particular entry here; see that class's own header for why, and `evaluator.ts`'s `evaluate()`
256
+ * for the one place it is caught.
257
+ */
258
+ export declare function matchFileRulesGrouped<TEntry>(candidates: readonly FileRuleCandidate<TEntry>[], path: string, opts: {
259
+ cwd: string;
260
+ home: string;
261
+ }, behavior: "allow" | "denyAsk"): TEntry | null;
262
+ /**
263
+ * `Smt`'s own job (round 5's `QCt`): rewrite a path through its REAL prefix (e.g. `/private/tmp/x`, what
264
+ * `realpathSync` actually returns) back to the commonly-typed TRUSTED alias (`/tmp/x`) -- the
265
+ * direction a real, resolved path needs to go to be compared against a rule an author wrote in the
266
+ * short form. A path with no matching real prefix passes through unchanged.
267
+ */
268
+ export declare function canonicalizeTrustedSymlinkPath(path: string): string;
269
+ /**
270
+ * SV-8 (the router same-view test on the 57e7fef binary): claude's own acceptEdits
271
+ * working-directory boundary check is `sm` (dump-confirmed by content search) -- a plain RELATIVE-
272
+ * PATH PREFIX test, never a compiled glob at all. Winter's own `isWithinBounds` (evaluator.ts) used
273
+ * to reuse the general file-rule matcher with a `"**"` sentinel pattern -- harmless before SV-6/C-1,
274
+ * but once the general matcher started interpreting `[`, `]`, `*` and `\` as glob metacharacters, a
275
+ * cwd or additional-directory root containing any of them (e.g. `[wip] app`) made `"**"` fail to
276
+ * compile the way the caller intended, and acceptEdits asked for every write inside that cwd instead
277
+ * of auto-approving them.
278
+ *
279
+ * This function sidesteps the escaping question SV-8 raises entirely, the same way claude's own `sm`
280
+ * does: a plain path-prefix test never interprets EITHER path as glob syntax, so a root containing a
281
+ * glob-special character needs no escaping here at all -- unlike a real RULE pattern (I-G's own
282
+ * concern), which does.
283
+ *
284
+ * Ported: `caseFold` (default `true`, matching `sm`'s own default and I-D's case-insensitivity
285
+ * finding generally) folds BOTH paths before computing the relative path between them; the macOS
286
+ * `/private/var` -> `/var` and `/private/tmp` -> `/tmp` aliasing is real-symlink-aware -- macOS
287
+ * itself maintains both as symlinks to the `/private/...` originals, so a session cwd resolved
288
+ * through one spelling and a root configured with the other name the SAME real directory (this
289
+ * matters in practice: `os.tmpdir()` on macOS resolves through `/private/var/folders/...`, which is
290
+ * exactly the shape every mkdtemp-based fixture in this codebase's own test suite produces). Not
291
+ * ported: `sm`'s own `uncShapeParity` and `skipPrivateAlias` options (Windows-only concerns) and its
292
+ * `Gn`/`Ha` UNC-path checks -- this codebase supports macOS only (CLAUDE.md's own "latest-OS
293
+ * floors" rule).
294
+ *
295
+ * Fix round 6 (R5-2, the re-review against the pinned 2.1.250 dump): ONLY these TWO pairs -- round
296
+ * 5 widened this to the full six-pair `ni()`/`Sl()` map (`/private/etc`, `/usr/bin`, `/usr/lib`,
297
+ * `/usr/sbin` included), which was WRONG for `sm` specifically: content search against the pinned
298
+ * 2.1.250 dump (not the 2.1.280 build round 5 was cited against) found `sm`'s own alias regexes
299
+ * verbatim -- `g=r?/^\/private\/var\//i:/^\/private\/var\//,w=r?/^\/private\/tmp(\/|$)/i:/^\/private\/
300
+ * tmp(\/|$)/` -- exactly these two, unconditionally, never the wider six-pair set. Reverted to match;
301
+ * the six-pair map (`trustedSymlinkEquivalences`/`canonicalizeTrustedSymlinkPath`) stays, but is now
302
+ * used ONLY by the allow-rule retry in evaluator.ts (`cqe`'s own scope, confirmed at the same dump
303
+ * site), never by this function.
304
+ */
305
+ export declare function isPathWithinRoot(childPath: string, rootPath: string, opts?: {
306
+ caseFold?: boolean;
307
+ }): boolean;
308
+ /**
309
+ * The traversal fence for a plugin MANIFEST's own declared component paths (`commands`/`agents`/
310
+ * `skills`/`output-styles`/`workflows`/`hooks`).
311
+ *
312
+ * Fix round 6 (R5-1 + a promoted minor, the re-review against the PINNED 2.1.250 dump): claude's own
313
+ * check here is `nV` (dump-confirmed by content search against the pinned dump directly, at the
314
+ * scratchpad path the controller named -- superseding fix round 5's citation of `KGe`/`Aoe` against
315
+ * the INSTALLED 2.1.280 binary, which this round's own ruling says is not the parity authority):
316
+ * `nV(root,entry)` resolves `entry` against `root`, computes `u=path.relative(root,resolved)`, and
317
+ * refuses (`return null`) when `u.startsWith("..")`. Three ways this DIFFERS from `isPathWithinRoot`/
318
+ * `sm` above, all ported exactly rather than reused:
319
+ * 1. CASE-SENSITIVE, always -- `nV`'s own body has no folding call anywhere (confirmed by reading
320
+ * it in full), unlike `sm`'s own `r?/.../i:/.../ ` case-fold branching. Fix round 5's own
321
+ * `resolvesWithinPluginRoot` wrongly delegated to `isPathWithinRoot`'s DEFAULT `caseFold:true`,
322
+ * so on a case-sensitive volume a manifest entry like `../FOO/agents` under a root
323
+ * `.../plugins/foo` was admitted (folded, `FOO` read as `foo`) where claude's own `nV` (and
324
+ * this rewrite) refuses it.
325
+ * 2. NAIVE STRING-PREFIX, not segment-aware -- `u.startsWith("..")` is a bare string test, unlike
326
+ * `sm`'s own `uj` (`/(?:^|[\\/])\.\.(?:[\\/]|$)/`, confirmed by reading ITS full definition too),
327
+ * which requires a `..` SEGMENT bounded by a separator or a string edge. This means a component
328
+ * name that merely STARTS WITH the two characters `..` -- e.g. `"..x/agents"`, a real,
329
+ * non-escaping subdirectory name -- is REFUSED by claude too, not only a genuine `"../"` escape.
330
+ * Matched here rather than "fixed", per the ruling: claude's own inconsistency between its two
331
+ * path-safety mechanisms is not this codebase's to resolve by choosing the more correct one.
332
+ * 3. NO trusted-symlink alias mapping at all -- `nV`'s own body never calls anything resembling
333
+ * `Smt`/`canonicalizeTrustedSymlinkPath`. Moot in practice here regardless, since both operands
334
+ * below are ALREADY realpath'd before this comparison runs (a real, resolved path from
335
+ * `/tmp`/`/var` already comes back in its long `/private/...` form either way).
336
+ *
337
+ * DISCLOSED DIVERGENCE FROM THE PINNED 2.1.250, kept as DELIBERATE HARDENING (the controller's own
338
+ * explicit ruling): `nV` itself is PURELY LEXICAL -- 2.1.250 has no symlink-following/realpath step
339
+ * for a plugin component path at all. This function still realpaths both the candidate and the
340
+ * plugin root first (originally ported from the INSTALLED 2.1.280 binary's own `KGe`/`Aoe`, which DID
341
+ * add this in a build newer than the pin), refusing a symlinked override that points outside the
342
+ * plugin where 2.1.250 would load it -- the safe direction, and it matches claude's own newer
343
+ * behaviour. `nV`'s own comparison shape (case-sensitive, naive-prefix, no alias) is then applied to
344
+ * the REALPATH'D forms rather than to the raw ones `nV` itself compares. `resolveRealTarget` (paths.ts)
345
+ * has the graceful "walk up to the nearest existing ancestor" fallback for a candidate that does not
346
+ * exist YET, and rethrows a non-ENOENT failure (ELOOP on a symlink cycle, EACCES, ...), caught here
347
+ * and treated as a refusal rather than letting a malformed manifest entry crash the whole
348
+ * plugin-loading pass.
349
+ */
350
+ export declare function resolvesWithinPluginRoot(candidatePath: string, pluginRoot: string): boolean;
351
+ /**
352
+ * Fix round 4 (I-G): a real, resolved filesystem path (e.g. `resolve(winterHome)`) can legitimately
353
+ * contain `[`, `]`, `*` or `\` -- none of which were glob-special under Winter's pre-fix-round-4
354
+ * grammar, but all four are now, since `matchFileRulesGrouped` compiles every pattern through the
355
+ * real `ignore` package. A caller building a rule PATTERN out of a real path (`buildBaselineDenyRules`,
356
+ * engine.ts) must escape these four before interpolating the path into pattern text, or a home
357
+ * directory literally named e.g. `/Users/name[wip]` would have its OWN floor's `[wip]` read back as
358
+ * a character class instead of the four literal characters it names on disk.
359
+ *
360
+ * `?` is DELIBERATELY LEFT RAW, per the controller's own ruling: claude's grammar has no working
361
+ * escape for `?` at all (this module's own `unanchorTrailingDoubleStar`/`\?`-quirk sibling
362
+ * documentation) -- an escaped `\?` would require a literal backslash the real path never has, so it
363
+ * would never match the floor's own intended directory at all. A bare `?` in the pattern instead acts
364
+ * as a single-character wildcard, which still MATCHES a real `?` in the path (a wildcard matches
365
+ * anything, including the literal character) -- over-matching by one character class is the safe
366
+ * direction for a DENY floor (WS-07 §3.1's own posture: a deny that reaches slightly too far is a
367
+ * false-negative-avoiding cost, never a hole), where an escape that matches NOTHING would be a hole.
368
+ */
369
+ export declare function escapeFileRulePathSegment(path: string): string;
370
+ /**
371
+ * A SINGLE pattern against a SINGLE path -- for a caller that is already iterating rule entries one
372
+ * at a time for a reason unrelated to C-1/SV-7 (e.g. evaluator.ts's own cross-tool
373
+ * `findFileDenyBlockingEdit`, a Winter-invented safety net with no claude analogue: claude's own
374
+ * Write decision never consults `Read(...)` rules at all, so "a Read deny also blocks a Write" is
375
+ * this codebase's own extension, not a ported behaviour). Grouping (this module's own header)
376
+ * therefore does not apply across DIFFERENT callers' unrelated single-pattern checks the way it does
377
+ * within one `matchFileRulesGrouped` call -- this is a thin, no-negation-support convenience, not a
378
+ * second matching engine.
379
+ */
380
+ export declare function matchesSingleFileRulePattern(pattern: string, path: string, opts: {
381
+ cwd: string;
382
+ home: string;
383
+ }, behavior: "allow" | "denyAsk"): boolean;
384
+ export {};
@@ -0,0 +1,113 @@
1
+ export type Specifier = {
2
+ kind: "wildcardAll";
3
+ } | {
4
+ kind: "pattern";
5
+ source: string;
6
+ } | {
7
+ kind: "param";
8
+ field: string;
9
+ value: string | boolean;
10
+ } | {
11
+ kind: "webFetchDomain";
12
+ source: string;
13
+ } | {
14
+ kind: "invalid";
15
+ reason: string;
16
+ };
17
+ export interface ParsedRule {
18
+ toolName: string;
19
+ specifier?: Specifier;
20
+ isBareEquivalent: boolean;
21
+ }
22
+ export declare const PARSE_LIMIT = 50000;
23
+ export declare const READ_ONLY_COMMANDS: ReadonlySet<string>;
24
+ export declare const DANGEROUS_ASSIGNMENT_NAMES: ReadonlySet<string>;
25
+ export declare const FILE_RULE_TOOLS: ReadonlySet<string>;
26
+ export declare function leadingWord(s: string): {
27
+ word: string | undefined;
28
+ afterWord: string;
29
+ };
30
+ /**
31
+ * Joins backslash-newline continuations the way bash does before it parses: an ODD run of
32
+ * backslashes before a newline ends in a continuation (the last backslash and the newline vanish);
33
+ * an even run is escaped backslashes followed by a real newline. Without this, `echo x >
34
+ * \<newline>.git/config` read its target as `\<newline>.git/config` -- a name with no `.git`
35
+ * segment -- while bash wrote `.git/config` (claude joins them before its own redirect scan).
36
+ */
37
+ export declare function joinLineContinuations(command: string): string;
38
+ export declare function splitCompound(rawCommand: string): string[] | null;
39
+ export declare function stripWrappers(rawCmd: string, direction: "allow" | "denyAsk"): string;
40
+ /** One word of a command: its text after quote removal, as written, and whether any of it was quoted. */
41
+ export interface ShellWord {
42
+ word: string;
43
+ raw: string;
44
+ quoted: boolean;
45
+ }
46
+ /**
47
+ * bash's quote removal (and, with `split`, its word splitting at unquoted blanks) over one command's
48
+ * text: single quotes, double quotes (a backslash there drops -- stricter than bash, which keeps it
49
+ * before an ordinary character, and never naming a DIFFERENT protected file), backslash escapes,
50
+ * ANSI-C `$'…'` (decoded) and locale `$"…"` (as double quotes). Expansions are left as written. An
51
+ * unterminated quote runs to the end.
52
+ */
53
+ export declare function shellWords(s: string, split?: boolean): ShellWord[];
54
+ /** `word` after bash's quote removal, as ONE word (blanks inside it are kept). */
55
+ export declare function dequoteShellWord(word: string): string;
56
+ /** One file-writing redirection: the target word as written (`raw`) and after bash's quote removal. */
57
+ export interface RedirectWrite {
58
+ raw: string;
59
+ target: string;
60
+ }
61
+ /**
62
+ * Every FILE-writing redirection at the top level of one (sub)command -- the operators bash writes a
63
+ * file through: `>`, `>>`, `>|` (noclobber override), `&>`, `&>>`, `<>` (read-write open), any of them
64
+ * fd-prefixed (`2>`), and `>&word` / `N>&word` whose word is NOT a descriptor (`>&file` is the old
65
+ * spelling of `&>file`; `2>&1`, `>&2`, `>&-` stay descriptor copies). `<<`/`<<<` feed input and
66
+ * `>(`/`<(` are process substitutions -- neither is a file target (the permission layer asks for a
67
+ * process substitution separately). Bash runs without history expansion here, so a target that
68
+ * begins with `!` is ALSO read with the `!` removed (zsh's `>!` clobber), which only adds a path.
69
+ *
70
+ * An unparseable command yields `[]` here; every security caller asks for such a command on its own
71
+ * (`shellWriteConstraint`), because a scan it could not complete proves nothing about its writes.
72
+ */
73
+ export declare function extractRedirectWrites(rawCommand: string): RedirectWrite[];
74
+ /** `extractRedirectWrites`, target paths only (quotes removed). */
75
+ export declare function extractRedirectTargets(command: string): string[];
76
+ export declare function isRecognizedReadOnly(command: string): boolean;
77
+ export declare function escapeRegExpLiteral(s: string): string;
78
+ /** The call's `url` as a parsed `URL`, or `undefined` when it is absent, not a string, or unparseable. NEVER throws. */
79
+ export declare function webFetchUrlOf(input: Record<string, unknown>): URL | undefined;
80
+ /**
81
+ * The hostname a `WebFetch(domain:...)` rule is compared against: `new URL(url).hostname`, lowercase
82
+ * (the URL parser already lowercases and punycodes it), minus one trailing dot.
83
+ *
84
+ * `undefined` -- which matches NO domain rule, on either direction -- for an absent/unparseable `url`
85
+ * and for a URL with an EMPTY host (`file:///etc/passwd`, `data:`): `domain:*` compiles to a pattern
86
+ * that matches the empty string, so without this an allow rule written for "any website" would
87
+ * pre-approve a URL that names no website at all.
88
+ *
89
+ * The trailing dot is stripped on BOTH sides (here and at parse) because `https://example.com./` is
90
+ * the same host as `https://example.com/` and the URL parser keeps the dot: an exact compare would
91
+ * let that spelling walk past a deny rule.
92
+ */
93
+ export declare function webFetchHostnameOf(input: Record<string, unknown>): string | undefined;
94
+ /**
95
+ * True when `rule` is a `WebFetch(domain:<host>)` rule that names `hostname` EXACTLY -- no `*`
96
+ * anywhere in it. This is what the evaluator means by "a rule naming that host": a glob
97
+ * (`domain:*`, `domain:*.corp`) matches a host without ever having named it, so it can allow a fetch
98
+ * but can never stand in for the user's consent to one specific address.
99
+ */
100
+ export declare function isExactWebFetchDomainRule(rule: ParsedRule, hostname: string): boolean;
101
+ export declare function parseRule(raw: string): ParsedRule;
102
+ export declare function matchesRule(rule: ParsedRule, call: {
103
+ toolName: string;
104
+ input: Record<string, unknown>;
105
+ }, opts: {
106
+ direction: "allow" | "denyAsk";
107
+ }): boolean;
108
+ export interface PermissionRuleValidation {
109
+ valid: boolean;
110
+ error?: string;
111
+ suggestion?: string;
112
+ }
113
+ export declare function validatePermissionRuleString(raw: string, direction: "allow" | "deny" | "ask"): PermissionRuleValidation;
@@ -0,0 +1,32 @@
1
+ import type { PermissionBehavior } from "@yanlinglabs/winter-agent-sdk";
2
+ export interface MatchFileRuleOptions {
3
+ path: string;
4
+ cwd: string;
5
+ sourceDir?: string;
6
+ home: string;
7
+ direction: "allow" | "denyAsk";
8
+ }
9
+ export declare function resolveTargetPath(path: string, cwd: string): string;
10
+ export declare const MAX_DOUBLE_STARS = 8;
11
+ export declare const MAX_STARS_PER_SEGMENT = 8;
12
+ export declare function exceedsStarsPerSegmentCap(pattern: string): boolean;
13
+ export declare function exceedsDoubleStarCap(pattern: string): boolean;
14
+ export declare function matchFileRule(pattern: string, opts: MatchFileRuleOptions): boolean;
15
+ export interface SymlinkBothEndsResult {
16
+ allowRequiresBoth: boolean;
17
+ denyIfEither: boolean;
18
+ }
19
+ export declare function resolveRealTarget(path: string): string;
20
+ export declare function resolveSymlinkTargetChain(path: string): string | undefined;
21
+ export declare function checkSymlinkBothEnds(path: string, matcher: (candidatePath: string) => boolean): SymlinkBothEndsResult;
22
+ export declare function matchFileRuleAtBothEnds(pattern: string, opts: MatchFileRuleOptions): boolean;
23
+ export interface FileRuleEntry {
24
+ toolName: string;
25
+ pattern: string;
26
+ behavior: PermissionBehavior;
27
+ sourceDir?: string;
28
+ }
29
+ export declare function readDenyBlocksEdit(rules: FileRuleEntry[], path: string, ctx: {
30
+ cwd: string;
31
+ home: string;
32
+ }): boolean;
@@ -0,0 +1,64 @@
1
+ import type { PermissionMode, PermissionUpdate, RuleSource } from "@yanlinglabs/winter-agent-sdk";
2
+ import { type SourcedRuleSet } from "./ruleset.js";
3
+ export type { AutoModeConfig } from "./auto/config.js";
4
+ import type { AutoModeConfig } from "./auto/config.js";
5
+ export interface PolicyState {
6
+ mode: PermissionMode;
7
+ version: number;
8
+ rules: SourcedRuleSet;
9
+ autoConfig?: AutoModeConfig;
10
+ }
11
+ export declare class WinterPermissionError extends Error {
12
+ constructor(message: string);
13
+ }
14
+ export declare const PERMISSION_MODES: ReadonlySet<PermissionMode>;
15
+ export declare function isPermissionMode(value: string): value is PermissionMode;
16
+ /**
17
+ * SDK 0.0.16 (P16-7): claude's fork agent (`Ex`) carries `permissionMode: "bubble"` -- NOT a member
18
+ * of `PERMISSION_MODES` and never widened into one (`PermissionMode` is a closed 6-value union read
19
+ * exhaustively elsewhere -- `classifyPermissionMode` in particular). "bubble" is an explicit ALIAS
20
+ * for "no override": the child keeps whatever mode the parent session is CURRENTLY running (never a
21
+ * fixed mode of its own), and its own approval prompts surface through the parent's approval path.
22
+ *
23
+ * The second half needs no new plumbing here -- every child's `PreToolUse`/hook control_requests
24
+ * already forward up to the real host and are answered there (`child-engine.ts`'s
25
+ * `registerChildResponseHandler`/`forwardedHostRequestIds`, Phase 4 Task 8 rider 19); "bubble" only
26
+ * NAMES, deliberately, the mode value that already produces "inherit the parent's live mode" instead
27
+ * of leaving it an accident of an unrecognized permissionMode string falling through
28
+ * `isPermissionMode`'s own false case. `engine.ts`'s `buildChildInheritance` treats this constant
29
+ * (never the general "value is not a known mode" branch) as that alias -- see its own comment.
30
+ */
31
+ export declare const BUBBLE_PERMISSION_MODE = "bubble";
32
+ export declare function assertKnownPermissionMode(mode: string | undefined): PermissionMode;
33
+ export interface BypassGateConfig {
34
+ allowDangerouslySkipPermissions: boolean;
35
+ disableBypassPermissionsMode: boolean;
36
+ }
37
+ export interface SetModeResult {
38
+ ok: true;
39
+ effectiveMode: PermissionMode;
40
+ }
41
+ export interface SetModeError {
42
+ ok: false;
43
+ error: {
44
+ code: string;
45
+ message: string;
46
+ };
47
+ }
48
+ export interface ApplyUpdateOk {
49
+ ok: true;
50
+ }
51
+ export declare class PolicyStateStore {
52
+ private state;
53
+ private readonly gate;
54
+ constructor(initial: {
55
+ mode: PermissionMode;
56
+ rules: SourcedRuleSet;
57
+ autoConfig?: AutoModeConfig;
58
+ }, gate: BypassGateConfig);
59
+ getState(): Readonly<PolicyState>;
60
+ setMode(mode: PermissionMode): SetModeResult | SetModeError;
61
+ applyUpdate(update: PermissionUpdate, opts: {
62
+ authority: RuleSource;
63
+ }): ApplyUpdateOk | SetModeError;
64
+ }
@@ -0,0 +1,3 @@
1
+ import type { RpcBridge } from "../rpc/bridge.js";
2
+ import type { PromptStage } from "./evaluator.js";
3
+ export declare function createBridgePromptStage(bridge: RpcBridge): PromptStage;