@smthrs/plan 0.0.0-stage → 1.0.0-rc.13

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 (209) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/LICENSE +21 -0
  3. package/README.md +230 -2
  4. package/THIRD_PARTY_NOTICES.md +48 -0
  5. package/dist/cjs/CachePolicy.d.ts +131 -0
  6. package/dist/cjs/CachePolicy.d.ts.map +1 -0
  7. package/dist/cjs/CachePolicy.js +50 -0
  8. package/dist/cjs/CachePolicy.js.map +7 -0
  9. package/dist/cjs/Effects.d.ts +258 -0
  10. package/dist/cjs/Effects.d.ts.map +1 -0
  11. package/dist/cjs/Effects.js +76 -0
  12. package/dist/cjs/Effects.js.map +7 -0
  13. package/dist/cjs/FileSet.d.ts +366 -0
  14. package/dist/cjs/FileSet.d.ts.map +1 -0
  15. package/dist/cjs/FileSet.js +196 -0
  16. package/dist/cjs/FileSet.js.map +7 -0
  17. package/dist/cjs/GraphBuildError.d.ts +120 -0
  18. package/dist/cjs/GraphBuildError.d.ts.map +1 -0
  19. package/dist/cjs/GraphBuildError.js +71 -0
  20. package/dist/cjs/GraphBuildError.js.map +7 -0
  21. package/dist/cjs/KeyMaterial.d.ts +107 -0
  22. package/dist/cjs/KeyMaterial.d.ts.map +1 -0
  23. package/dist/cjs/KeyMaterial.js +64 -0
  24. package/dist/cjs/KeyMaterial.js.map +7 -0
  25. package/dist/cjs/Node.d.ts +685 -0
  26. package/dist/cjs/Node.d.ts.map +1 -0
  27. package/dist/cjs/Node.js +230 -0
  28. package/dist/cjs/Node.js.map +7 -0
  29. package/dist/cjs/Placement.d.ts +117 -0
  30. package/dist/cjs/Placement.d.ts.map +1 -0
  31. package/dist/cjs/Placement.js +46 -0
  32. package/dist/cjs/Placement.js.map +7 -0
  33. package/dist/cjs/Plan.d.ts +489 -0
  34. package/dist/cjs/Plan.d.ts.map +1 -0
  35. package/dist/cjs/Plan.js +511 -0
  36. package/dist/cjs/Plan.js.map +7 -0
  37. package/dist/cjs/PlanDiff.d.ts +77 -0
  38. package/dist/cjs/PlanDiff.d.ts.map +1 -0
  39. package/dist/cjs/PlanDiff.js +149 -0
  40. package/dist/cjs/PlanDiff.js.map +7 -0
  41. package/dist/cjs/Planned.d.ts +121 -0
  42. package/dist/cjs/Planned.d.ts.map +1 -0
  43. package/dist/cjs/Planned.js +72 -0
  44. package/dist/cjs/Planned.js.map +7 -0
  45. package/dist/cjs/Repetition.d.ts +31 -0
  46. package/dist/cjs/Repetition.d.ts.map +1 -0
  47. package/dist/cjs/Repetition.js +36 -0
  48. package/dist/cjs/Repetition.js.map +7 -0
  49. package/dist/cjs/Scheduling.d.ts +89 -0
  50. package/dist/cjs/Scheduling.d.ts.map +1 -0
  51. package/dist/cjs/Scheduling.js +76 -0
  52. package/dist/cjs/Scheduling.js.map +7 -0
  53. package/dist/cjs/StepKey.d.ts +354 -0
  54. package/dist/cjs/StepKey.d.ts.map +1 -0
  55. package/dist/cjs/StepKey.js +313 -0
  56. package/dist/cjs/StepKey.js.map +7 -0
  57. package/dist/cjs/index.d.ts +91 -0
  58. package/dist/cjs/index.d.ts.map +1 -0
  59. package/dist/cjs/index.js +59 -0
  60. package/dist/cjs/index.js.map +7 -0
  61. package/dist/cjs/internal/ConflictAnnotation.d.ts +59 -0
  62. package/dist/cjs/internal/ConflictAnnotation.d.ts.map +1 -0
  63. package/dist/cjs/internal/ConflictAnnotation.js +247 -0
  64. package/dist/cjs/internal/ConflictAnnotation.js.map +7 -0
  65. package/dist/cjs/internal/EffectCandidates.d.ts +19 -0
  66. package/dist/cjs/internal/EffectCandidates.d.ts.map +1 -0
  67. package/dist/cjs/internal/EffectCandidates.js +92 -0
  68. package/dist/cjs/internal/EffectCandidates.js.map +7 -0
  69. package/dist/cjs/internal/JsonMirror.d.ts +34 -0
  70. package/dist/cjs/internal/JsonMirror.d.ts.map +1 -0
  71. package/dist/cjs/internal/JsonMirror.js +195 -0
  72. package/dist/cjs/internal/JsonMirror.js.map +7 -0
  73. package/dist/cjs/internal/SchemaIdentity.d.ts +140 -0
  74. package/dist/cjs/internal/SchemaIdentity.d.ts.map +1 -0
  75. package/dist/cjs/internal/SchemaIdentity.js +718 -0
  76. package/dist/cjs/internal/SchemaIdentity.js.map +7 -0
  77. package/dist/cjs/internal/effects.d.ts +245 -0
  78. package/dist/cjs/internal/effects.d.ts.map +1 -0
  79. package/dist/cjs/internal/effects.js +290 -0
  80. package/dist/cjs/internal/effects.js.map +7 -0
  81. package/dist/cjs/internal/node.d.ts +526 -0
  82. package/dist/cjs/internal/node.d.ts.map +1 -0
  83. package/dist/cjs/internal/node.js +313 -0
  84. package/dist/cjs/internal/node.js.map +7 -0
  85. package/dist/cjs/package.json +1 -0
  86. package/dist/cjs/test/PlanFixtures.d.ts +127 -0
  87. package/dist/cjs/test/PlanFixtures.d.ts.map +1 -0
  88. package/dist/cjs/test/PlanFixtures.js +59 -0
  89. package/dist/cjs/test/PlanFixtures.js.map +7 -0
  90. package/dist/esm/CachePolicy.d.ts +131 -0
  91. package/dist/esm/CachePolicy.d.ts.map +1 -0
  92. package/dist/esm/CachePolicy.js +117 -0
  93. package/dist/esm/CachePolicy.js.map +1 -0
  94. package/dist/esm/Effects.d.ts +258 -0
  95. package/dist/esm/Effects.d.ts.map +1 -0
  96. package/dist/esm/Effects.js +178 -0
  97. package/dist/esm/Effects.js.map +1 -0
  98. package/dist/esm/FileSet.d.ts +366 -0
  99. package/dist/esm/FileSet.d.ts.map +1 -0
  100. package/dist/esm/FileSet.js +398 -0
  101. package/dist/esm/FileSet.js.map +1 -0
  102. package/dist/esm/GraphBuildError.d.ts +120 -0
  103. package/dist/esm/GraphBuildError.d.ts.map +1 -0
  104. package/dist/esm/GraphBuildError.js +145 -0
  105. package/dist/esm/GraphBuildError.js.map +1 -0
  106. package/dist/esm/KeyMaterial.d.ts +107 -0
  107. package/dist/esm/KeyMaterial.d.ts.map +1 -0
  108. package/dist/esm/KeyMaterial.js +92 -0
  109. package/dist/esm/KeyMaterial.js.map +1 -0
  110. package/dist/esm/Node.d.ts +685 -0
  111. package/dist/esm/Node.d.ts.map +1 -0
  112. package/dist/esm/Node.js +591 -0
  113. package/dist/esm/Node.js.map +1 -0
  114. package/dist/esm/Placement.d.ts +117 -0
  115. package/dist/esm/Placement.d.ts.map +1 -0
  116. package/dist/esm/Placement.js +65 -0
  117. package/dist/esm/Placement.js.map +1 -0
  118. package/dist/esm/Plan.d.ts +489 -0
  119. package/dist/esm/Plan.d.ts.map +1 -0
  120. package/dist/esm/Plan.js +718 -0
  121. package/dist/esm/Plan.js.map +1 -0
  122. package/dist/esm/PlanDiff.d.ts +77 -0
  123. package/dist/esm/PlanDiff.d.ts.map +1 -0
  124. package/dist/esm/PlanDiff.js +205 -0
  125. package/dist/esm/PlanDiff.js.map +1 -0
  126. package/dist/esm/Planned.d.ts +121 -0
  127. package/dist/esm/Planned.d.ts.map +1 -0
  128. package/dist/esm/Planned.js +147 -0
  129. package/dist/esm/Planned.js.map +1 -0
  130. package/dist/esm/Repetition.d.ts +31 -0
  131. package/dist/esm/Repetition.d.ts.map +1 -0
  132. package/dist/esm/Repetition.js +24 -0
  133. package/dist/esm/Repetition.js.map +1 -0
  134. package/dist/esm/Scheduling.d.ts +89 -0
  135. package/dist/esm/Scheduling.d.ts.map +1 -0
  136. package/dist/esm/Scheduling.js +82 -0
  137. package/dist/esm/Scheduling.js.map +1 -0
  138. package/dist/esm/StepKey.d.ts +354 -0
  139. package/dist/esm/StepKey.d.ts.map +1 -0
  140. package/dist/esm/StepKey.js +503 -0
  141. package/dist/esm/StepKey.js.map +1 -0
  142. package/dist/esm/index.d.ts +91 -0
  143. package/dist/esm/index.d.ts.map +1 -0
  144. package/dist/esm/index.js +91 -0
  145. package/dist/esm/index.js.map +1 -0
  146. package/dist/esm/internal/ConflictAnnotation.d.ts +59 -0
  147. package/dist/esm/internal/ConflictAnnotation.d.ts.map +1 -0
  148. package/dist/esm/internal/ConflictAnnotation.js +332 -0
  149. package/dist/esm/internal/ConflictAnnotation.js.map +1 -0
  150. package/dist/esm/internal/EffectCandidates.d.ts +19 -0
  151. package/dist/esm/internal/EffectCandidates.d.ts.map +1 -0
  152. package/dist/esm/internal/EffectCandidates.js +86 -0
  153. package/dist/esm/internal/EffectCandidates.js.map +1 -0
  154. package/dist/esm/internal/JsonMirror.d.ts +34 -0
  155. package/dist/esm/internal/JsonMirror.d.ts.map +1 -0
  156. package/dist/esm/internal/JsonMirror.js +204 -0
  157. package/dist/esm/internal/JsonMirror.js.map +1 -0
  158. package/dist/esm/internal/SchemaIdentity.d.ts +140 -0
  159. package/dist/esm/internal/SchemaIdentity.d.ts.map +1 -0
  160. package/dist/esm/internal/SchemaIdentity.js +1002 -0
  161. package/dist/esm/internal/SchemaIdentity.js.map +1 -0
  162. package/dist/esm/internal/effects.d.ts +245 -0
  163. package/dist/esm/internal/effects.d.ts.map +1 -0
  164. package/dist/esm/internal/effects.js +459 -0
  165. package/dist/esm/internal/effects.js.map +1 -0
  166. package/dist/esm/internal/node.d.ts +526 -0
  167. package/dist/esm/internal/node.d.ts.map +1 -0
  168. package/dist/esm/internal/node.js +565 -0
  169. package/dist/esm/internal/node.js.map +1 -0
  170. package/dist/esm/test/PlanFixtures.d.ts +127 -0
  171. package/dist/esm/test/PlanFixtures.d.ts.map +1 -0
  172. package/dist/esm/test/PlanFixtures.js +60 -0
  173. package/dist/esm/test/PlanFixtures.js.map +1 -0
  174. package/docs/README.md +167 -0
  175. package/docs/api.md +1485 -0
  176. package/docs/concepts/authoring-ast.md +204 -0
  177. package/docs/concepts/effects-and-conflicts.md +135 -0
  178. package/docs/concepts/plan-value.md +168 -0
  179. package/docs/concepts/step-keys.md +179 -0
  180. package/docs/guides/author-a-node-graph.md +182 -0
  181. package/docs/guides/compile-a-plan.md +146 -0
  182. package/docs/guides/declare-file-effects.md +143 -0
  183. package/docs/guides/diff-two-plans.md +310 -0
  184. package/docs/installation.md +75 -0
  185. package/docs/quickstart.md +128 -0
  186. package/docs/testing.md +73 -0
  187. package/docs/troubleshooting.md +314 -0
  188. package/package.json +255 -3
  189. package/src/CachePolicy.ts +143 -0
  190. package/src/Effects.ts +302 -0
  191. package/src/FileSet.ts +493 -0
  192. package/src/GraphBuildError.ts +156 -0
  193. package/src/KeyMaterial.ts +111 -0
  194. package/src/Node.ts +974 -0
  195. package/src/Placement.ts +99 -0
  196. package/src/Plan.ts +911 -0
  197. package/src/PlanDiff.ts +244 -0
  198. package/src/Planned.ts +208 -0
  199. package/src/Repetition.ts +33 -0
  200. package/src/Scheduling.ts +154 -0
  201. package/src/StepKey.ts +736 -0
  202. package/src/index.ts +103 -0
  203. package/src/internal/ConflictAnnotation.ts +374 -0
  204. package/src/internal/EffectCandidates.ts +89 -0
  205. package/src/internal/JsonMirror.ts +255 -0
  206. package/src/internal/SchemaIdentity.ts +1096 -0
  207. package/src/internal/effects.ts +543 -0
  208. package/src/internal/node.ts +859 -0
  209. package/src/test/PlanFixtures.ts +76 -0
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Pure effect declarations used to describe flow read and write envelopes.
3
+ *
4
+ * This is the ONE effect-envelope model. `@smthrs/flow` enforces it while it
5
+ * builds a graph, `@smthrs/core` re-exports it, and `@smthrs/patterns` reads it
6
+ * to intersect a decorator's declaration with the flow it wraps. It lives here
7
+ * because `@smthrs/plan` is the lowest package all three depend on, beside the
8
+ * `tier` and `onConflict` vocabularies a plan already speaks.
9
+ *
10
+ * Two layers: the declaration API, which a flow author and a catalog use, and
11
+ * the prepared matching API below it, which a graph builder uses to check one
12
+ * envelope against many steps without re-reading the envelope each time.
13
+ *
14
+ * Governing contract: `packages/smithers/flows/plan/docs/api.md`, published as
15
+ * https://smithers.sh/docs/reference/api/plan.
16
+ *
17
+ * @since 0.0.0
18
+ */
19
+ import * as Context from "effect/Context";
20
+ import * as Schema from "effect/Schema";
21
+ import * as Index from "./internal/effects.js";
22
+ /**
23
+ * How reversible the work beneath a declaration is.
24
+ *
25
+ * This is the ONE tier vocabulary. `KeyMaterial.kind` is this schema, and so
26
+ * is `@smthrs/flow`'s `Action.Tier`: an action's durability and a declared
27
+ * envelope's ceiling are the same three words, and a fourth spelling of them
28
+ * in one of the three places would fork identity silently.
29
+ *
30
+ * @category schemas
31
+ * @since 1.0.0-rc.0
32
+ */
33
+ export const Tier = Schema.Literals(["sealed", "compensable", "irreversible"]);
34
+ /**
35
+ * How hermetic the work beneath a declaration is.
36
+ *
37
+ * This is the ONE mode vocabulary: the two words were written out in
38
+ * `Declaration`, in `MakeOptions`, and twice more inside the matcher.
39
+ *
40
+ * @category schemas
41
+ * @since 1.0.0-rc.0
42
+ */
43
+ export const Mode = Schema.Literals(["hermetic", "expected"]);
44
+ /**
45
+ * What a plan does when two nodes write the same path.
46
+ *
47
+ * This is the ONE conflict vocabulary: `Declaration.onConflict` declares it and
48
+ * `Plan.PairStrategy` is this same schema, resolved per pair by
49
+ * `Plan.compile`.
50
+ *
51
+ * @category schemas
52
+ * @since 1.0.0-rc.0
53
+ */
54
+ export const ConflictStrategy = Schema.Literals(["serialize", "lane", "fail"]);
55
+ /**
56
+ * The annotation key a flow's declared effect ENVELOPE is carried under.
57
+ *
58
+ * One key, here, because two graph builders read it: `@smthrs/flow`'s
59
+ * `Graph.build` enforces the envelope it names, and `@smthrs/core` re-exports
60
+ * this key as `Annotations.Effects`. While they were separate keys a flow
61
+ * annotated for one builder was invisible to the other.
62
+ *
63
+ * It is a `Context` key, not hashed material: annotating a flow with an
64
+ * envelope changes what a build ADMITS, and the declaration reaches identity
65
+ * only through `KeyMaterial.kind`.
66
+ *
67
+ * @category annotations
68
+ * @since 1.0.0-rc.0
69
+ */
70
+ export const Envelope = Context.Service("@smthrs/plan/Effects/Envelope");
71
+ /**
72
+ * The prepared matching API. See the type re-exports above for what each member
73
+ * is for.
74
+ *
75
+ * @category matching
76
+ * @since 1.0.0-rc.0
77
+ */
78
+ export { boundedEffects, indexPaths, maximumGlobs, maximumPathLength, narrowPrepared, overlapRanks, prepareEnvelope, rankPaths } from "./internal/effects.js";
79
+ const normalize = (paths) => [...new Set(paths)].sort();
80
+ /**
81
+ * Constructs a deterministic effect declaration: `reads` and `writes` are
82
+ * collected, deduplicated, and sorted; an absent `tier` is omitted. Paths are
83
+ * not validated or rewritten.
84
+ *
85
+ * @param input - The paths, mode, conflict strategy, and optional tier.
86
+ * @returns The normalized declaration.
87
+ * @category constructors
88
+ * @since 0.0.0
89
+ */
90
+ export const make = (input) => ({
91
+ reads: normalize(input.reads),
92
+ writes: normalize(input.writes),
93
+ mode: input.mode,
94
+ onConflict: input.onConflict,
95
+ ...(input.tier === undefined ? {} : { tier: input.tier })
96
+ });
97
+ /**
98
+ * Checks whether `path` is covered by an envelope entry.
99
+ *
100
+ * The grammar is exhaustive: an exact path matches itself; `*` and `**` match
101
+ * everything; `prefix*` matches by string prefix; and `prefix/**` matches
102
+ * `prefix/` and everything below it, but not bare `prefix`. This is
103
+ * intentionally not full minimatch syntax. Envelope entries and declared paths
104
+ * must be normalized. A path containing a whole `.` or `..` segment is never
105
+ * covered, so {@link narrow} reports it as `effect_outside_envelope` rather
106
+ * than silently accepting an escape.
107
+ *
108
+ * @param envelope - One envelope entry.
109
+ * @param path - One declared path.
110
+ * @returns `true` when the entry covers the path.
111
+ * @category predicates
112
+ * @since 0.0.0
113
+ */
114
+ export const covers = (envelope, path) => {
115
+ if (Index.hasDotSegment(path))
116
+ return false;
117
+ return envelope === path || (Index.isGlob(envelope) && path.startsWith(Index.globPrefix(envelope)));
118
+ };
119
+ /**
120
+ * Verifies that a step declaration stays within an enclosing flow envelope.
121
+ *
122
+ * Read and write paths must be covered independently. A step may tighten
123
+ * `expected` to `hermetic`, but cannot widen `hermetic` to `expected`.
124
+ * Effect tiers narrow from irreversible to compensable to sealed.
125
+ *
126
+ * The envelope's lists are prepared once: exact entries go into a set and
127
+ * covering patterns collapse to their outermost prefixes, sorted, so each step
128
+ * path costs one dot-segment scan, one lookup, and one binary search ending in
129
+ * one prefix comparison, whatever the envelope's width or how many of its
130
+ * patterns nest. A graph build prepares each envelope once for every node it
131
+ * encloses.
132
+ *
133
+ * @param envelope - The flow's declaration.
134
+ * @param step - The step's declaration.
135
+ * @returns `{ ok: true }`, or the first rule the step breaks.
136
+ * @category validation
137
+ * @since 0.0.0
138
+ */
139
+ export const narrow = (envelope, step) => Index.narrowPrepared(Index.prepareEnvelope(envelope), step);
140
+ /**
141
+ * Returns the concrete or narrower write declarations shared by two effect
142
+ * declarations. The result is sorted and duplicate-free.
143
+ *
144
+ * Two declarations of the same literal path always overlap, including a path
145
+ * {@link covers} refuses to match because it carries a `.` or `..` segment.
146
+ * Glob coverage stays strict for those paths, so an unnormalized declaration
147
+ * still escapes no envelope, but two writers naming the same unnormalized path
148
+ * are still detected as writing the same resource.
149
+ *
150
+ * The union of both declarations is indexed once: the distinct paths are
151
+ * sorted, each is scanned once for a dot segment, and each pattern's prefix
152
+ * is located by binary search. Exact paths then match through a merge of two
153
+ * rank lists and each covering pattern enumerates the other declaration's
154
+ * ranks inside its interval, so the cost is linear in the two declarations
155
+ * plus the matches, whatever the paths' lengths or how many patterns nest.
156
+ *
157
+ * @param a - One declaration.
158
+ * @param b - The other declaration.
159
+ * @returns The shared write paths; empty when the writes are disjoint.
160
+ * @category analysis
161
+ * @since 0.0.0
162
+ */
163
+ export const overlaps = (a, b) => {
164
+ const indexed = Index.indexPaths([a.writes, b.writes]);
165
+ return Index.overlapRanks(indexed, Index.rankPaths(indexed, a.writes), Index.rankPaths(indexed, b.writes))
166
+ .map((rank) => indexed.paths[rank]);
167
+ };
168
+ /**
169
+ * Returns a sealed, hermetic copy of an effect declaration, normalized by
170
+ * {@link make}. Paths and `onConflict` are kept.
171
+ *
172
+ * @param declaration - The declaration to copy.
173
+ * @returns The copy with `mode: "hermetic"` and `tier: "sealed"`.
174
+ * @category constructors
175
+ * @since 0.0.0
176
+ */
177
+ export const sealed = (declaration) => make({ ...declaration, mode: "hermetic", tier: "sealed" });
178
+ //# sourceMappingURL=Effects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Effects.js","sourceRoot":"","sources":["../../src/Effects.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure effect declarations used to describe flow read and write envelopes.\n *\n * This is the ONE effect-envelope model. `@smthrs/flow` enforces it while it\n * builds a graph, `@smthrs/core` re-exports it, and `@smthrs/patterns` reads it\n * to intersect a decorator's declaration with the flow it wraps. It lives here\n * because `@smthrs/plan` is the lowest package all three depend on, beside the\n * `tier` and `onConflict` vocabularies a plan already speaks.\n *\n * Two layers: the declaration API, which a flow author and a catalog use, and\n * the prepared matching API below it, which a graph builder uses to check one\n * envelope against many steps without re-reading the envelope each time.\n *\n * Governing contract: `packages/smithers/flows/plan/docs/api.md`, published as\n * https://smithers.sh/docs/reference/api/plan.\n *\n * @since 0.0.0\n */\n\nimport * as Context from \"effect/Context\"\nimport * as Schema from \"effect/Schema\"\nimport * as Index from \"./internal/effects.ts\"\n\n/**\n * How reversible the work beneath a declaration is.\n *\n * This is the ONE tier vocabulary. `KeyMaterial.kind` is this schema, and so\n * is `@smthrs/flow`'s `Action.Tier`: an action's durability and a declared\n * envelope's ceiling are the same three words, and a fourth spelling of them\n * in one of the three places would fork identity silently.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Tier = Schema.Literals([\"sealed\", \"compensable\", \"irreversible\"])\n\n/**\n * The value form of {@link Tier}.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Tier = typeof Tier.Type\n\n/**\n * How hermetic the work beneath a declaration is.\n *\n * This is the ONE mode vocabulary: the two words were written out in\n * `Declaration`, in `MakeOptions`, and twice more inside the matcher.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const Mode = Schema.Literals([\"hermetic\", \"expected\"])\n\n/**\n * The value form of {@link Mode}.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type Mode = typeof Mode.Type\n\n/**\n * What a plan does when two nodes write the same path.\n *\n * This is the ONE conflict vocabulary: `Declaration.onConflict` declares it and\n * `Plan.PairStrategy` is this same schema, resolved per pair by\n * `Plan.compile`.\n *\n * @category schemas\n * @since 1.0.0-rc.0\n */\nexport const ConflictStrategy = Schema.Literals([\"serialize\", \"lane\", \"fail\"])\n\n/**\n * The value form of {@link ConflictStrategy}.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport type ConflictStrategy = typeof ConflictStrategy.Type\n\n/**\n * The annotation key a flow's declared effect ENVELOPE is carried under.\n *\n * One key, here, because two graph builders read it: `@smthrs/flow`'s\n * `Graph.build` enforces the envelope it names, and `@smthrs/core` re-exports\n * this key as `Annotations.Effects`. While they were separate keys a flow\n * annotated for one builder was invisible to the other.\n *\n * It is a `Context` key, not hashed material: annotating a flow with an\n * envelope changes what a build ADMITS, and the declaration reaches identity\n * only through `KeyMaterial.kind`.\n *\n * @category annotations\n * @since 1.0.0-rc.0\n */\nexport const Envelope = Context.Service<Declaration>(\"@smthrs/plan/Effects/Envelope\")\n\n/**\n * The prepared matching API: what a graph builder needs to check one envelope\n * against every step it encloses, and to find the write overlaps between two\n * declarations, at the cost the public functions above pay once rather than\n * once per step.\n *\n * {@link prepareEnvelope} reads an envelope once into the form\n * {@link narrowPrepared} answers from, which is what makes a wide envelope cost\n * its size per build rather than per node. {@link indexPaths},\n * {@link rankPaths} and {@link overlapRanks} are the same decomposition for\n * write overlap, which {@link overlaps} wraps for the pairwise case.\n * {@link boundedEffects} snapshots a declaration into builder-owned data,\n * refusing through the caller's own error before the copy grows past its limit,\n * and {@link maximumPathLength} and {@link maximumGlobs} are the per-path bounds\n * that refusal enforces.\n *\n * @category matching\n * @since 1.0.0-rc.0\n */\nexport type { PathIndex, PreparedEnvelope, Ranked } from \"./internal/effects.ts\"\n\n/**\n * The prepared matching API. See the type re-exports above for what each member\n * is for.\n *\n * @category matching\n * @since 1.0.0-rc.0\n */\nexport {\n boundedEffects,\n indexPaths,\n maximumGlobs,\n maximumPathLength,\n narrowPrepared,\n overlapRanks,\n prepareEnvelope,\n rankPaths\n} from \"./internal/effects.ts\"\n\n/**\n * A normalized description of the resources a flow or step may read and\n * write. Build one with {@link make}.\n *\n * @category models\n * @since 0.0.0\n */\nexport interface Declaration {\n /** Readable paths or envelope patterns, sorted and duplicate-free. */\n readonly reads: ReadonlyArray<string>\n /** Writable paths or envelope patterns, sorted and duplicate-free. */\n readonly writes: ReadonlyArray<string>\n /** `hermetic` or `expected` enforcement. */\n readonly mode: Mode\n /** What a plan does when another node writes an overlapping path. */\n readonly onConflict: ConflictStrategy\n /** The effect tier. Absent means `sealed`. */\n readonly tier?: Tier | undefined\n}\n\n/**\n * Input accepted by {@link make}. Iterables are normalized into sorted,\n * duplicate-free arrays so declarations are deterministic key material.\n * Envelope entries and declared paths must already be path-normalized: no\n * separator or dot-segment rewriting is performed. A declared path containing\n * a whole `.` or `..` segment is never covered and therefore surfaces from\n * {@link narrow} as an `effect_outside_envelope` diagnostic.\n *\n * @category models\n * @since 0.0.0\n */\nexport interface MakeOptions {\n readonly reads: Iterable<string>\n readonly writes: Iterable<string>\n readonly mode: Mode\n readonly onConflict: ConflictStrategy\n readonly tier?: Tier | undefined\n}\n\n/**\n * A result of checking that a step declaration narrows a flow envelope.\n *\n * On failure, `code` names the first rule broken, checked in this order:\n * `effect_outside_envelope` (with the uncovered read and write paths, sorted),\n * `effect_mode_widening`, then `effect_tier_widening` (both with empty\n * `paths`).\n *\n * @category models\n * @since 0.0.0\n */\nexport type NarrowResult =\n | { readonly ok: true }\n | {\n readonly ok: false\n readonly code: \"effect_outside_envelope\" | \"effect_mode_widening\" | \"effect_tier_widening\"\n readonly paths: ReadonlyArray<string>\n }\n\nconst normalize = (paths: Iterable<string>): ReadonlyArray<string> => [...new Set(paths)].sort()\n\n/**\n * Constructs a deterministic effect declaration: `reads` and `writes` are\n * collected, deduplicated, and sorted; an absent `tier` is omitted. Paths are\n * not validated or rewritten.\n *\n * @param input - The paths, mode, conflict strategy, and optional tier.\n * @returns The normalized declaration.\n * @category constructors\n * @since 0.0.0\n */\nexport const make = (input: MakeOptions): Declaration => ({\n reads: normalize(input.reads),\n writes: normalize(input.writes),\n mode: input.mode,\n onConflict: input.onConflict,\n ...(input.tier === undefined ? {} : { tier: input.tier })\n})\n\n/**\n * Checks whether `path` is covered by an envelope entry.\n *\n * The grammar is exhaustive: an exact path matches itself; `*` and `**` match\n * everything; `prefix*` matches by string prefix; and `prefix/**` matches\n * `prefix/` and everything below it, but not bare `prefix`. This is\n * intentionally not full minimatch syntax. Envelope entries and declared paths\n * must be normalized. A path containing a whole `.` or `..` segment is never\n * covered, so {@link narrow} reports it as `effect_outside_envelope` rather\n * than silently accepting an escape.\n *\n * @param envelope - One envelope entry.\n * @param path - One declared path.\n * @returns `true` when the entry covers the path.\n * @category predicates\n * @since 0.0.0\n */\nexport const covers = (envelope: string, path: string): boolean => {\n if (Index.hasDotSegment(path)) return false\n return envelope === path || (Index.isGlob(envelope) && path.startsWith(Index.globPrefix(envelope)))\n}\n\n/**\n * Verifies that a step declaration stays within an enclosing flow envelope.\n *\n * Read and write paths must be covered independently. A step may tighten\n * `expected` to `hermetic`, but cannot widen `hermetic` to `expected`.\n * Effect tiers narrow from irreversible to compensable to sealed.\n *\n * The envelope's lists are prepared once: exact entries go into a set and\n * covering patterns collapse to their outermost prefixes, sorted, so each step\n * path costs one dot-segment scan, one lookup, and one binary search ending in\n * one prefix comparison, whatever the envelope's width or how many of its\n * patterns nest. A graph build prepares each envelope once for every node it\n * encloses.\n *\n * @param envelope - The flow's declaration.\n * @param step - The step's declaration.\n * @returns `{ ok: true }`, or the first rule the step breaks.\n * @category validation\n * @since 0.0.0\n */\nexport const narrow = (envelope: Declaration, step: Declaration): NarrowResult =>\n Index.narrowPrepared(Index.prepareEnvelope(envelope), step)\n\n/**\n * Returns the concrete or narrower write declarations shared by two effect\n * declarations. The result is sorted and duplicate-free.\n *\n * Two declarations of the same literal path always overlap, including a path\n * {@link covers} refuses to match because it carries a `.` or `..` segment.\n * Glob coverage stays strict for those paths, so an unnormalized declaration\n * still escapes no envelope, but two writers naming the same unnormalized path\n * are still detected as writing the same resource.\n *\n * The union of both declarations is indexed once: the distinct paths are\n * sorted, each is scanned once for a dot segment, and each pattern's prefix\n * is located by binary search. Exact paths then match through a merge of two\n * rank lists and each covering pattern enumerates the other declaration's\n * ranks inside its interval, so the cost is linear in the two declarations\n * plus the matches, whatever the paths' lengths or how many patterns nest.\n *\n * @param a - One declaration.\n * @param b - The other declaration.\n * @returns The shared write paths; empty when the writes are disjoint.\n * @category analysis\n * @since 0.0.0\n */\nexport const overlaps = (a: Declaration, b: Declaration): ReadonlyArray<string> => {\n const indexed = Index.indexPaths([a.writes, b.writes])\n return Index.overlapRanks(indexed, Index.rankPaths(indexed, a.writes), Index.rankPaths(indexed, b.writes))\n .map((rank) => indexed.paths[rank]!)\n}\n\n/**\n * Returns a sealed, hermetic copy of an effect declaration, normalized by\n * {@link make}. Paths and `onConflict` are kept.\n *\n * @param declaration - The declaration to copy.\n * @returns The copy with `mode: \"hermetic\"` and `tier: \"sealed\"`.\n * @category constructors\n * @since 0.0.0\n */\nexport const sealed = (declaration: Declaration): Declaration =>\n make({ ...declaration, mode: \"hermetic\", tier: \"sealed\" })\n"]}
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Static filesystem declaration vocabulary shared by planning and execution.
3
+ *
4
+ * Declared paths use `/` as their canonical separator and normalize Unicode
5
+ * to NFC. Workspace-relative paths reject C0 controls (U+0000 through U+001F)
6
+ * and DEL (U+007F), which name nothing a supported filesystem can open. C1
7
+ * controls (U+0080 through U+009F) remain accepted because those bytes are
8
+ * legal in a POSIX file name.
9
+ *
10
+ * @since 0.1.0
11
+ */
12
+ import * as Schema from "effect/Schema";
13
+ /**
14
+ * How strictly a declared file set is enforced at the boundary.
15
+ *
16
+ * `hard` rejects undeclared access. `expected` records access for validation
17
+ * after execution without requiring the sandbox to reject it immediately.
18
+ *
19
+ * This is the ONE spelling of the pair. `Plan.NodeEffects.boundaryMode` is this
20
+ * schema and so is `@smthrs/flow`'s `Action.BoundaryMode`; the literal used to
21
+ * be written out in all three places.
22
+ *
23
+ * @category schemas
24
+ * @since 1.0.0-rc.0
25
+ */
26
+ export declare const BoundaryMode: Schema.Literals<readonly ["hard", "expected"]>;
27
+ /**
28
+ * The value form of {@link BoundaryMode}.
29
+ *
30
+ * @category models
31
+ * @since 1.0.0-rc.0
32
+ */
33
+ export type BoundaryMode = typeof BoundaryMode.Type;
34
+ /**
35
+ * The canonical spelling of a declared path or pattern: every separator is
36
+ * `/`, and Unicode is normalized to NFC.
37
+ *
38
+ * {@link workspaceRelative} accepts a backslash as a separator, so
39
+ * `dist\same.js` and `dist/same.js` are two spellings of ONE workspace path.
40
+ * Every exact-path comparison in this module goes through this form, because
41
+ * comparing the raw spellings would let the separator alias defeat overlap
42
+ * detection exactly as `.` segments and empty segments would.
43
+ *
44
+ * @category accessors
45
+ * @since 0.1.0
46
+ */
47
+ export declare const canonical: (path: string) => string;
48
+ /**
49
+ * The {@link canonical} spelling with letter case folded away.
50
+ *
51
+ * A case-insensitive filesystem (default macOS APFS, Windows NTFS) opens
52
+ * `src/A.ts` and `src/a.ts` as one file, so static overlap compares this form:
53
+ * two declarations that differ only in case must serialize. Folding goes
54
+ * through upper case because that mapping is context-free, so it folds each
55
+ * character alone and commutes with splitting a path into segments.
56
+ *
57
+ * @category accessors
58
+ * @since 1.0.0-rc.0
59
+ */
60
+ export declare const folded: (path: string) => string;
61
+ /**
62
+ * A non-empty workspace-relative path or pattern.
63
+ *
64
+ * Decoding fails with a `SchemaError` when {@link workspaceRelative} refuses
65
+ * the string. A bare `Pattern` in a declaration names one literal path; only a
66
+ * {@link Glob} gives `*` and `**` wildcard meaning.
67
+ *
68
+ * @category schemas
69
+ * @since 0.1.0
70
+ */
71
+ export declare const Pattern: Schema.NonEmptyString;
72
+ /**
73
+ * Whether a declared path or pattern stays inside the workspace and names it
74
+ * one way only. Refuses absolute paths (POSIX and drive-letter), upward
75
+ * traversal, and the aliasing forms — `.` segments, empty segments — that
76
+ * would let two spellings of one file defeat exact-string overlap detection.
77
+ *
78
+ * C0 controls and DEL are refused as well.
79
+ *
80
+ * @category predicates
81
+ * @since 0.1.0
82
+ */
83
+ export declare const workspaceRelative: (pattern: string) => boolean;
84
+ /**
85
+ * A Bazel-style file glob: the paths matching any `include` pattern and no
86
+ * `exclude` pattern.
87
+ *
88
+ * In a pattern, `*` matches within one path segment and a `**` segment
89
+ * matches zero or more whole segments. A trailing `**` needs its separator,
90
+ * so `src/**` does not match `src` itself.
91
+ *
92
+ * @category schemas
93
+ * @since 0.1.0
94
+ */
95
+ export declare const Glob: Schema.TaggedStruct<"Glob", {
96
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
97
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
98
+ }>;
99
+ /**
100
+ * The value form of {@link Glob}.
101
+ *
102
+ * @category models
103
+ * @since 0.1.0
104
+ */
105
+ export type Glob = typeof Glob.Type;
106
+ /**
107
+ * A directory output captured and replayed as one tree artifact.
108
+ *
109
+ * It covers `path` and every path beneath it, compared in {@link folded}
110
+ * form.
111
+ *
112
+ * @category schemas
113
+ * @since 0.1.0
114
+ */
115
+ export declare const TreeArtifact: Schema.TaggedStruct<"TreeArtifact", {
116
+ readonly path: Schema.NonEmptyString;
117
+ }>;
118
+ /**
119
+ * The value form of {@link TreeArtifact}.
120
+ *
121
+ * @category models
122
+ * @since 0.1.0
123
+ */
124
+ export type TreeArtifact = typeof TreeArtifact.Type;
125
+ /**
126
+ * One leaf declaration: a literal path, a {@link Glob}, or a
127
+ * {@link TreeArtifact}. Write sets and filegroups hold entries.
128
+ *
129
+ * @category schemas
130
+ * @since 0.1.0
131
+ */
132
+ export declare const Entry: Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
133
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
134
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
135
+ }>, Schema.TaggedStruct<"TreeArtifact", {
136
+ readonly path: Schema.NonEmptyString;
137
+ }>]>;
138
+ /**
139
+ * The value form of {@link Entry}.
140
+ *
141
+ * @category models
142
+ * @since 0.1.0
143
+ */
144
+ export type Entry = typeof Entry.Type;
145
+ /**
146
+ * One leaf declaration valid in a read set: a literal path or a {@link Glob}.
147
+ * A read set cannot name a {@link TreeArtifact}, which is an output form.
148
+ *
149
+ * @category schemas
150
+ * @since 0.1.0
151
+ */
152
+ export declare const ReadEntry: Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
153
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
154
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
155
+ }>]>;
156
+ /**
157
+ * The value form of {@link ReadEntry}.
158
+ *
159
+ * @category models
160
+ * @since 0.1.0
161
+ */
162
+ export type ReadEntry = typeof ReadEntry.Type;
163
+ /**
164
+ * A named, reusable list of {@link Entry} declarations.
165
+ *
166
+ * {@link expand} replaces a filegroup with its entries in place before any
167
+ * overlap check or measurement, so the name never reaches the boundary.
168
+ * Filegroups do not nest.
169
+ *
170
+ * @category schemas
171
+ * @since 0.1.0
172
+ */
173
+ export declare const Filegroup: Schema.TaggedStruct<"Filegroup", {
174
+ readonly name: Schema.NonEmptyString;
175
+ readonly entries: Schema.$Array<Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
176
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
177
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
178
+ }>, Schema.TaggedStruct<"TreeArtifact", {
179
+ readonly path: Schema.NonEmptyString;
180
+ }>]>>;
181
+ }>;
182
+ /**
183
+ * The value form of {@link Filegroup}.
184
+ *
185
+ * @category models
186
+ * @since 0.1.0
187
+ */
188
+ export type Filegroup = typeof Filegroup.Type;
189
+ /**
190
+ * A {@link Filegroup} restricted to {@link ReadEntry} declarations, for use
191
+ * in a read set. It shares the `"Filegroup"` tag.
192
+ *
193
+ * @category schemas
194
+ * @since 0.1.0
195
+ */
196
+ export declare const ReadFilegroup: Schema.TaggedStruct<"Filegroup", {
197
+ readonly name: Schema.NonEmptyString;
198
+ readonly entries: Schema.$Array<Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
199
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
200
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
201
+ }>]>>;
202
+ }>;
203
+ /**
204
+ * The value form of {@link ReadFilegroup}.
205
+ *
206
+ * @category models
207
+ * @since 0.1.0
208
+ */
209
+ export type ReadFilegroup = typeof ReadFilegroup.Type;
210
+ /**
211
+ * Any declaration accepted in a write set: an {@link Entry} or a
212
+ * {@link Filegroup}.
213
+ *
214
+ * @category schemas
215
+ * @since 0.1.0
216
+ */
217
+ export declare const Declaration: Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
218
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
219
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
220
+ }>, Schema.TaggedStruct<"TreeArtifact", {
221
+ readonly path: Schema.NonEmptyString;
222
+ }>]>, Schema.TaggedStruct<"Filegroup", {
223
+ readonly name: Schema.NonEmptyString;
224
+ readonly entries: Schema.$Array<Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
225
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
226
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
227
+ }>, Schema.TaggedStruct<"TreeArtifact", {
228
+ readonly path: Schema.NonEmptyString;
229
+ }>]>>;
230
+ }>]>;
231
+ /**
232
+ * The value form of {@link Declaration}.
233
+ *
234
+ * @category models
235
+ * @since 0.1.0
236
+ */
237
+ export type Declaration = typeof Declaration.Type;
238
+ /**
239
+ * Any declaration accepted in a read set: a {@link ReadEntry} or a
240
+ * {@link ReadFilegroup}.
241
+ *
242
+ * @category schemas
243
+ * @since 0.1.0
244
+ */
245
+ export declare const ReadDeclaration: Schema.Union<readonly [Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
246
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
247
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
248
+ }>]>, Schema.TaggedStruct<"Filegroup", {
249
+ readonly name: Schema.NonEmptyString;
250
+ readonly entries: Schema.$Array<Schema.Union<readonly [Schema.NonEmptyString, Schema.TaggedStruct<"Glob", {
251
+ readonly include: Schema.NonEmptyArray<Schema.NonEmptyString>;
252
+ readonly exclude: Schema.optional<Schema.$Array<Schema.NonEmptyString>>;
253
+ }>]>>;
254
+ }>]>;
255
+ /**
256
+ * The value form of {@link ReadDeclaration}.
257
+ *
258
+ * @category models
259
+ * @since 0.1.0
260
+ */
261
+ export type ReadDeclaration = typeof ReadDeclaration.Type;
262
+ /**
263
+ * Creates a {@link Filegroup}. It does not validate `name` or `entries`;
264
+ * decode through {@link Filegroup} when the input is untrusted.
265
+ *
266
+ * @param name - The filegroup name.
267
+ * @param entries - The entries the filegroup expands to, in order.
268
+ * @returns The filegroup value.
269
+ * @category constructors
270
+ * @since 0.1.0
271
+ */
272
+ export declare const makeFilegroup: (name: string, entries: ReadonlyArray<Entry>) => Filegroup;
273
+ /**
274
+ * Replaces each {@link Filegroup} with its entries, in place, and keeps every
275
+ * other declaration as it is. Order is preserved and duplicates are kept.
276
+ *
277
+ * @param declarations - Write-set declarations, possibly holding filegroups.
278
+ * @returns The flat list of entries.
279
+ * @category accessors
280
+ * @since 0.1.0
281
+ */
282
+ export declare const expand: (declarations: ReadonlyArray<Declaration>) => ReadonlyArray<Entry>;
283
+ /**
284
+ * {@link expand} for read sets: replaces each {@link ReadFilegroup} with its
285
+ * entries, in place, preserving order and duplicates.
286
+ *
287
+ * @param declarations - Read-set declarations, possibly holding filegroups.
288
+ * @returns The flat list of read entries.
289
+ * @category accessors
290
+ * @since 0.1.0
291
+ */
292
+ export declare const expandReads: (declarations: ReadonlyArray<ReadDeclaration>) => ReadonlyArray<ReadEntry>;
293
+ /**
294
+ * Whether a value carries the `"Glob"` tag. It checks only the tag, not the
295
+ * patterns.
296
+ *
297
+ * @param value - Any value.
298
+ * @returns `true` for an object whose `_tag` is `"Glob"`.
299
+ * @category guards
300
+ * @since 0.1.0
301
+ */
302
+ export declare const isGlob: (value: unknown) => value is Glob;
303
+ /**
304
+ * Whether a value carries the `"TreeArtifact"` tag. It checks only the tag,
305
+ * not the path.
306
+ *
307
+ * @param value - Any value.
308
+ * @returns `true` for an object whose `_tag` is `"TreeArtifact"`.
309
+ * @category guards
310
+ * @since 0.1.0
311
+ */
312
+ export declare const isTreeArtifact: (value: unknown) => value is TreeArtifact;
313
+ /**
314
+ * Whether `path` matches `pattern` under {@link Glob} wildcard rules.
315
+ *
316
+ * The pattern is read in its {@link canonical} spelling; the path is matched
317
+ * as given, case-sensitively, with `/` as its only separator.
318
+ *
319
+ * @param pattern - A Bazel-style pattern such as `src/*.ts` or `docs/**`.
320
+ * @param path - A workspace-relative path.
321
+ * @returns `true` when the path matches.
322
+ * @category predicates
323
+ * @since 0.1.0
324
+ */
325
+ export declare const matchesPattern: (pattern: string, path: string) => boolean;
326
+ /**
327
+ * Whether `path` matches some `include` pattern of `glob` and no `exclude`
328
+ * pattern, each tested with {@link matchesPattern}. Case-sensitive.
329
+ *
330
+ * @param glob - The glob to test.
331
+ * @param path - A workspace-relative path.
332
+ * @returns `true` when the glob selects the path.
333
+ * @category predicates
334
+ * @since 0.1.0
335
+ */
336
+ export declare const matchesGlob: (glob: Glob, path: string) => boolean;
337
+ /**
338
+ * Whether a canonical path is inside a declaration, case-sensitively.
339
+ * Unlike {@link overlaps}, this predicate establishes replay authority.
340
+ *
341
+ * @category predicates
342
+ * @since 1.0.0-rc.0
343
+ */
344
+ export declare const contains: (entry: Entry, path: string) => boolean;
345
+ /**
346
+ * Conservative static overlap. `true` may over-serialize; `false` proves that
347
+ * no path can belong to both declarations.
348
+ *
349
+ * A plain string is a literal path, even when it contains `*` or `**`, as it
350
+ * is at execution (sandbox admission, capture, removal, and replay); wildcard
351
+ * matching belongs to a Glob.
352
+ *
353
+ * Exact paths and tree roots compare in their
354
+ * {@link folded} form, so separator aliases, canonically equivalent Unicode
355
+ * spellings, and spellings that differ only in letter case overlap. A Glob
356
+ * against an exact path folds its includes and ignores exclusions: an excluded
357
+ * spelling may alias an included spelling on another filesystem. {@link matchesGlob} itself stays case-sensitive and tests the path bytes it
358
+ * is handed; its property suite pins a backslash inside a path segment as
359
+ * literal text, so canonicalizing a measured path before matching is its
360
+ * caller's decision, not this module's.
361
+ *
362
+ * @category predicates
363
+ * @since 0.1.0
364
+ */
365
+ export declare const overlaps: (left: Entry, right: Entry) => boolean;
366
+ //# sourceMappingURL=FileSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileSet.d.ts","sourceRoot":"","sources":["../../src/FileSet.ts"],"names":[],"mappings":"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"}