@descent-vtt/spec-harness 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +17 -0
  3. package/.mcp.json +12 -0
  4. package/CHANGELOG.md +46 -0
  5. package/README.md +127 -9
  6. package/bin/spec-harness.js +19 -0
  7. package/dist/audit.d.ts +69 -0
  8. package/dist/audit.js +93 -0
  9. package/dist/audit.js.map +1 -0
  10. package/dist/branch.d.ts +26 -0
  11. package/dist/branch.js +100 -0
  12. package/dist/branch.js.map +1 -0
  13. package/dist/briefs.d.ts +49 -0
  14. package/dist/briefs.js +111 -0
  15. package/dist/briefs.js.map +1 -0
  16. package/dist/cli.d.ts +14 -0
  17. package/dist/cli.js +245 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/commands.d.ts +18 -0
  20. package/dist/commands.js +224 -0
  21. package/dist/commands.js.map +1 -0
  22. package/dist/config.d.ts +57 -0
  23. package/dist/config.js +167 -0
  24. package/dist/config.js.map +1 -0
  25. package/dist/context.d.ts +56 -0
  26. package/dist/context.js +125 -0
  27. package/dist/context.js.map +1 -0
  28. package/dist/document.d.ts +33 -0
  29. package/dist/document.js +9 -0
  30. package/dist/document.js.map +1 -0
  31. package/dist/fs.d.ts +29 -0
  32. package/dist/fs.js +85 -0
  33. package/dist/fs.js.map +1 -0
  34. package/dist/git.d.ts +57 -0
  35. package/dist/git.js +129 -0
  36. package/dist/git.js.map +1 -0
  37. package/dist/guard.d.ts +43 -0
  38. package/dist/guard.js +120 -0
  39. package/dist/guard.js.map +1 -0
  40. package/dist/hooks.d.ts +50 -0
  41. package/dist/hooks.js +109 -0
  42. package/dist/hooks.js.map +1 -0
  43. package/dist/index.d.ts +31 -0
  44. package/dist/index.js +20 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/junit.d.ts +30 -0
  47. package/dist/junit.js +166 -0
  48. package/dist/junit.js.map +1 -0
  49. package/dist/manifests.d.ts +52 -0
  50. package/dist/manifests.js +346 -0
  51. package/dist/manifests.js.map +1 -0
  52. package/dist/plugin.d.ts +45 -0
  53. package/dist/plugin.js +79 -0
  54. package/dist/plugin.js.map +1 -0
  55. package/dist/premises.d.ts +16 -0
  56. package/dist/premises.js +71 -0
  57. package/dist/premises.js.map +1 -0
  58. package/dist/probe.d.ts +108 -0
  59. package/dist/probe.js +203 -0
  60. package/dist/probe.js.map +1 -0
  61. package/dist/reader.d.ts +8 -0
  62. package/dist/reader.js +105 -0
  63. package/dist/reader.js.map +1 -0
  64. package/dist/round.d.ts +68 -0
  65. package/dist/round.js +339 -0
  66. package/dist/round.js.map +1 -0
  67. package/dist/rulings.d.ts +92 -0
  68. package/dist/rulings.js +160 -0
  69. package/dist/rulings.js.map +1 -0
  70. package/dist/sandbox.d.ts +28 -0
  71. package/dist/sandbox.js +110 -0
  72. package/dist/sandbox.js.map +1 -0
  73. package/dist/server.d.ts +13 -0
  74. package/dist/server.js +212 -0
  75. package/dist/server.js.map +1 -0
  76. package/dist/setup.d.ts +32 -0
  77. package/dist/setup.js +218 -0
  78. package/dist/setup.js.map +1 -0
  79. package/dist/siblings.d.ts +66 -0
  80. package/dist/siblings.js +134 -0
  81. package/dist/siblings.js.map +1 -0
  82. package/dist/types.d.ts +38 -0
  83. package/dist/types.js +3 -0
  84. package/dist/types.js.map +1 -0
  85. package/dist/vendor/spec-core/jsonrpc/index.d.ts +2 -0
  86. package/dist/vendor/spec-core/jsonrpc/index.js +2 -0
  87. package/dist/vendor/spec-core/jsonrpc/index.js.map +1 -0
  88. package/dist/vendor/spec-core/jsonrpc/mcp.d.ts +157 -0
  89. package/dist/vendor/spec-core/jsonrpc/mcp.js +353 -0
  90. package/dist/vendor/spec-core/jsonrpc/mcp.js.map +1 -0
  91. package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
  92. package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
  93. package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
  94. package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
  95. package/dist/vendor/spec-core/markdown/headings.js +199 -0
  96. package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
  97. package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
  98. package/dist/vendor/spec-core/markdown/index.js +4 -0
  99. package/dist/vendor/spec-core/markdown/index.js.map +1 -0
  100. package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
  101. package/dist/vendor/spec-core/markdown/layout.js +28 -0
  102. package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
  103. package/dist/vendor/spec-core/markdown/links.d.ts +22 -0
  104. package/dist/vendor/spec-core/markdown/links.js +364 -0
  105. package/dist/vendor/spec-core/markdown/links.js.map +1 -0
  106. package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
  107. package/dist/vendor/spec-core/markdown/lists.js +127 -0
  108. package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
  109. package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
  110. package/dist/vendor/spec-core/markdown/scan.js +439 -0
  111. package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
  112. package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
  113. package/dist/vendor/spec-core/markdown/syntax.js +181 -0
  114. package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
  115. package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
  116. package/dist/vendor/spec-core/markdown/tables.js +86 -0
  117. package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
  118. package/dist/vendor/spec-core/markdown/types.d.ts +287 -0
  119. package/dist/vendor/spec-core/markdown/types.js +9 -0
  120. package/dist/vendor/spec-core/markdown/types.js.map +1 -0
  121. package/dist/vendor/spec-core/path/index.d.ts +1 -0
  122. package/dist/vendor/spec-core/path/index.js +2 -0
  123. package/dist/vendor/spec-core/path/index.js.map +1 -0
  124. package/dist/vendor/spec-core/path/posix.d.ts +83 -0
  125. package/dist/vendor/spec-core/path/posix.js +150 -0
  126. package/dist/vendor/spec-core/path/posix.js.map +1 -0
  127. package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
  128. package/dist/vendor/spec-core/pattern/automaton.js +340 -0
  129. package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
  130. package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
  131. package/dist/vendor/spec-core/pattern/charset.js +116 -0
  132. package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
  133. package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
  134. package/dist/vendor/spec-core/pattern/glob.js +481 -0
  135. package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
  136. package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
  137. package/dist/vendor/spec-core/pattern/index.js +4 -0
  138. package/dist/vendor/spec-core/pattern/index.js.map +1 -0
  139. package/dist/vendor/spec-core/pattern/regex.d.ts +67 -0
  140. package/dist/vendor/spec-core/pattern/regex.js +813 -0
  141. package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
  142. package/dist/vendor/spec-core/text/index.d.ts +2 -0
  143. package/dist/vendor/spec-core/text/index.js +2 -0
  144. package/dist/vendor/spec-core/text/index.js.map +1 -0
  145. package/dist/vendor/spec-core/text/lines.d.ts +72 -0
  146. package/dist/vendor/spec-core/text/lines.js +156 -0
  147. package/dist/vendor/spec-core/text/lines.js.map +1 -0
  148. package/dist/versions.d.ts +42 -0
  149. package/dist/versions.js +57 -0
  150. package/dist/versions.js.map +1 -0
  151. package/dist/workspace.d.ts +77 -0
  152. package/dist/workspace.js +138 -0
  153. package/dist/workspace.js.map +1 -0
  154. package/hooks/hooks.json +28 -0
  155. package/package.json +86 -6
  156. package/skills/close-round/SKILL.md +38 -0
  157. package/skills/draft-brief/SKILL.md +64 -0
  158. package/skills/run-round/SKILL.md +46 -0
  159. package/skills/split-goal/SKILL.md +42 -0
  160. package/src/vendor/spec-core/LICENSE +21 -0
  161. package/src/vendor/spec-core/README.md +8 -0
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Non-deterministic finite automata over code points: built by Thompson's
3
+ * construction, run by keeping a set of live states, and searched for a
4
+ * shortest string several of them accept and several others refuse.
5
+ *
6
+ * Why an automaton rather than a `RegExp`: a glob such as `*-*-*-*-*-*x`
7
+ * handed to a backtracking engine tries every way of dividing a long name
8
+ * between its stars, and one spec-* tool measured 28 seconds for one path. A
9
+ * set of live states visits each state at most once per character, so a match
10
+ * costs at most the pattern's size times the path's length, whatever the
11
+ * pattern says.
12
+ *
13
+ * Why the same automaton for the witness: whether two scopes can name the same
14
+ * file, and whether one lies wholly inside another, are questions about the
15
+ * languages the patterns accept. Asked of the automata that do the matching,
16
+ * the answers cannot drift from what matching does.
17
+ */
18
+ import { accepts, acceptsIgnoringCase, boundaryPoints, DOT, SLASH } from './charset.js';
19
+ const CHAR = 0;
20
+ const SPLIT = 1;
21
+ const JUMP = 2;
22
+ const MATCH = 3;
23
+ /**
24
+ * Ceiling on the size of one automaton.
25
+ *
26
+ * Brace alternatives are compiled side by side, so a pattern's size is the
27
+ * sum of its alternatives'. Far above anything a scope list says; it exists
28
+ * so that a pathological pattern is refused while compiling rather than
29
+ * matched slowly.
30
+ */
31
+ export const MAX_STATES = 65_536;
32
+ export class AutomatonTooLarge extends Error {
33
+ constructor() {
34
+ super(`the pattern compiles to more than ${MAX_STATES} states`);
35
+ this.name = 'AutomatonTooLarge';
36
+ }
37
+ }
38
+ /** Thompson's construction, one fragment at a time. */
39
+ export class Builder {
40
+ kinds = [];
41
+ first = [];
42
+ second = [];
43
+ sets = [];
44
+ add(kind, set, first, second) {
45
+ if (this.kinds.length >= MAX_STATES)
46
+ throw new AutomatonTooLarge();
47
+ this.kinds.push(kind);
48
+ this.first.push(first);
49
+ this.second.push(second);
50
+ this.sets.push(set);
51
+ return this.kinds.length - 1;
52
+ }
53
+ patch(holes, target) {
54
+ for (const hole of holes) {
55
+ if (hole.slot === 1)
56
+ this.first[hole.state] = target;
57
+ else
58
+ this.second[hole.state] = target;
59
+ }
60
+ }
61
+ /** One character from a set. */
62
+ char(set) {
63
+ const state = this.add(CHAR, set, -1, -1);
64
+ return { start: state, holes: [{ state, slot: 1 }] };
65
+ }
66
+ /** The empty string. */
67
+ empty() {
68
+ const state = this.add(JUMP, null, -1, -1);
69
+ return { start: state, holes: [{ state, slot: 1 }] };
70
+ }
71
+ /** Each fragment after the one before it. */
72
+ sequence(parts) {
73
+ if (parts.length === 0)
74
+ return this.empty();
75
+ let current = parts[0];
76
+ for (let i = 1; i < parts.length; i += 1) {
77
+ const next = parts[i];
78
+ this.patch(current.holes, next.start);
79
+ current = { start: current.start, holes: next.holes };
80
+ }
81
+ return current;
82
+ }
83
+ /** Any one of the fragments. */
84
+ either(options) {
85
+ if (options.length === 0)
86
+ throw new Error('an alternation needs at least one option');
87
+ let current = options[options.length - 1];
88
+ for (let i = options.length - 2; i >= 0; i -= 1) {
89
+ const option = options[i];
90
+ const split = this.add(SPLIT, null, option.start, current.start);
91
+ current = { start: split, holes: [...option.holes, ...current.holes] };
92
+ }
93
+ return current;
94
+ }
95
+ /** Zero or more of a fragment. */
96
+ star(body) {
97
+ const split = this.add(SPLIT, null, body.start, -1);
98
+ this.patch(body.holes, split);
99
+ return { start: split, holes: [{ state: split, slot: 2 }] };
100
+ }
101
+ /** One or more of a fragment. */
102
+ plus(body) {
103
+ const split = this.add(SPLIT, null, body.start, -1);
104
+ this.patch(body.holes, split);
105
+ return { start: body.start, holes: [{ state: split, slot: 2 }] };
106
+ }
107
+ /** Zero or one of a fragment. */
108
+ optional(body) {
109
+ const empty = this.empty();
110
+ return this.either([body, empty]);
111
+ }
112
+ /** Closes the automaton: every unaimed arrow reaches acceptance. */
113
+ finish(body, caseSensitive) {
114
+ const match = this.add(MATCH, null, -1, -1);
115
+ this.patch(body.holes, match);
116
+ return {
117
+ kinds: Uint8Array.from(this.kinds),
118
+ first: Int32Array.from(this.first),
119
+ second: Int32Array.from(this.second),
120
+ sets: [...this.sets],
121
+ start: body.start,
122
+ caseSensitive,
123
+ };
124
+ }
125
+ }
126
+ /**
127
+ * Follows every empty arrow out of the states on a stack, appending each
128
+ * CHAR or MATCH state reached to `into`. `visited[state] === stamp` marks a
129
+ * state already taken this round, which is what bounds the work.
130
+ */
131
+ function close(automaton, stack, visited, stamp, into) {
132
+ const { kinds, first, second } = automaton;
133
+ while (stack.length > 0) {
134
+ const state = stack.pop();
135
+ if (visited[state] === stamp)
136
+ continue;
137
+ visited[state] = stamp;
138
+ switch (kinds[state]) {
139
+ case SPLIT:
140
+ stack.push(second[state], first[state]);
141
+ break;
142
+ case JUMP:
143
+ stack.push(first[state]);
144
+ break;
145
+ default:
146
+ into.push(state);
147
+ }
148
+ }
149
+ }
150
+ /**
151
+ * A reusable matcher over one automaton.
152
+ *
153
+ * Holds its buffers between subjects; it is not reentrant, and nothing needs
154
+ * it to be - matching calls out to nothing.
155
+ */
156
+ export class Matcher {
157
+ automaton;
158
+ visited;
159
+ stamp = 0;
160
+ stack = [];
161
+ live = [];
162
+ next = [];
163
+ constructor(automaton) {
164
+ this.automaton = automaton;
165
+ this.visited = new Int32Array(automaton.kinds.length).fill(-1);
166
+ }
167
+ /** Whether the automaton accepts the whole of a subject. */
168
+ test(subject) {
169
+ const { automaton } = this;
170
+ const accept = automaton.caseSensitive ? accepts : acceptsIgnoringCase;
171
+ this.live.length = 0;
172
+ this.stack.length = 0;
173
+ this.stack.push(automaton.start);
174
+ this.stamp += 1;
175
+ close(automaton, this.stack, this.visited, this.stamp, this.live);
176
+ for (let i = 0; i < subject.length; i += 1) {
177
+ const point = subject.codePointAt(i);
178
+ if (point > 0xffff)
179
+ i += 1;
180
+ this.next.length = 0;
181
+ this.stamp += 1;
182
+ for (const state of this.live) {
183
+ if (automaton.kinds[state] !== CHAR)
184
+ continue;
185
+ if (!accept(automaton.sets[state], point))
186
+ continue;
187
+ this.stack.push(automaton.first[state]);
188
+ close(automaton, this.stack, this.visited, this.stamp, this.next);
189
+ }
190
+ if (this.next.length === 0)
191
+ return false;
192
+ const spent = this.live;
193
+ this.live = this.next;
194
+ this.next = spent;
195
+ }
196
+ return this.live.some((state) => automaton.kinds[state] === MATCH);
197
+ }
198
+ }
199
+ /**
200
+ * How many distinct search states a witness search may visit. The search is
201
+ * polynomial in the sizes of the automata it must satisfy and, for the ones
202
+ * it must avoid, bounded by the subsets of their states it reaches; scope
203
+ * patterns reach a handful. The bound turns a pathological input into an
204
+ * `undecided` rather than a hang.
205
+ */
206
+ export const WITNESS_BUDGET = 200_000;
207
+ /**
208
+ * Path validity as a four-state machine: at the start of a segment, inside a
209
+ * segment reading `.` or `..` so far, or inside a segment that is a name. A
210
+ * witness must end inside a name, and a `/` is only legal after one, so no
211
+ * witness has an empty segment, a `.` or `..` segment, or a slash at either
212
+ * end - which a pattern such as `a/*\/b` would otherwise produce as `a//b`.
213
+ * NUL is refused outright: no filesystem and no git tree holds a path with one.
214
+ */
215
+ const SEGMENT_START = 0;
216
+ const ONE_DOT = 1;
217
+ const TWO_DOTS = 2;
218
+ const IN_NAME = 3;
219
+ const INVALID = -1;
220
+ const NUL = 0;
221
+ function stepValidity(state, point) {
222
+ if (point === NUL)
223
+ return INVALID;
224
+ if (point === SLASH)
225
+ return state === IN_NAME ? SEGMENT_START : INVALID;
226
+ if (point === DOT)
227
+ return state === SEGMENT_START ? ONE_DOT : state === ONE_DOT ? TWO_DOTS : IN_NAME;
228
+ return IN_NAME;
229
+ }
230
+ function closureOf(automaton, seeds) {
231
+ const visited = new Int32Array(automaton.kinds.length).fill(-1);
232
+ const out = [];
233
+ close(automaton, [...seeds], visited, 0, out);
234
+ return out;
235
+ }
236
+ function stepSet(automaton, states, point) {
237
+ const seeds = [];
238
+ for (const state of states) {
239
+ if (automaton.kinds[state] === CHAR && accepts(automaton.sets[state], point)) {
240
+ seeds.push(automaton.first[state]);
241
+ }
242
+ }
243
+ return closureOf(automaton, seeds).sort((a, b) => a - b);
244
+ }
245
+ /** Every way of choosing one element from each list. */
246
+ function combinations(lists) {
247
+ let out = [[]];
248
+ for (const list of lists) {
249
+ const grown = [];
250
+ for (const prefix of out)
251
+ for (const state of list)
252
+ grown.push([...prefix, state]);
253
+ out = grown;
254
+ }
255
+ return out;
256
+ }
257
+ function isMatch(automaton, state) {
258
+ return automaton.kinds[state] === MATCH;
259
+ }
260
+ /**
261
+ * A shortest path every automaton in `include` accepts and none in `exclude`
262
+ * does, spelled with readable characters where there is a choice.
263
+ *
264
+ * Breadth-first over the product of one live state per included automaton
265
+ * (existential: some run of each must accept) and the whole live set per
266
+ * excluded one (universal: no run of it may). Characters are tried at the
267
+ * boundary points of every set in play, which meets every combination of
268
+ * answers those sets can give, so the search is exact: `none` means no path
269
+ * exists, not that none was found. The first path reached is a shortest one.
270
+ *
271
+ * Case-sensitive automata only. Every scope comparison in the family is
272
+ * case-sensitive, and folding case exactly would need every set's closure
273
+ * under case mapping.
274
+ */
275
+ export function findWitness(include, exclude = [], budget = WITNESS_BUDGET) {
276
+ if (include.length === 0)
277
+ throw new Error('a witness search needs at least one automaton to satisfy');
278
+ for (const automaton of [...include, ...exclude]) {
279
+ if (!automaton.caseSensitive)
280
+ throw new Error('a witness search is defined for case-sensitive patterns only');
281
+ }
282
+ const startPositive = include.map((automaton) => closureOf(automaton, [automaton.start]));
283
+ const startNegative = exclude.map((automaton) => closureOf(automaton, [automaton.start]).sort((a, b) => a - b));
284
+ const nodes = [];
285
+ const seen = new Set();
286
+ const key = (positive, negative, validity) => `${positive.join(',')}|${validity}|${negative.map((set) => set.join(',')).join('|')}`;
287
+ const enqueue = (positive, negative, validity, parent, point) => {
288
+ const id = key(positive, negative, validity);
289
+ if (seen.has(id))
290
+ return;
291
+ seen.add(id);
292
+ nodes.push({ positive, negative, validity, parent, point });
293
+ };
294
+ for (const positive of combinations(startPositive))
295
+ enqueue(positive, startNegative, SEGMENT_START, -1, 0);
296
+ for (let cursor = 0; cursor < nodes.length; cursor += 1) {
297
+ if (cursor >= budget)
298
+ return { kind: 'undecided' };
299
+ const node = nodes[cursor];
300
+ const accepted = node.positive.every((state, i) => isMatch(include[i], state));
301
+ const refused = node.negative.every((set, i) => !set.some((state) => isMatch(exclude[i], state)));
302
+ if (accepted && refused && node.validity === IN_NAME)
303
+ return { kind: 'found', path: spell(nodes, cursor) };
304
+ // A MATCH state reads nothing more: an included automaton sitting on one
305
+ // can only accept here, so no longer path extends this node.
306
+ if (node.positive.some((state, i) => include[i].kinds[state] !== CHAR))
307
+ continue;
308
+ const sets = [];
309
+ node.positive.forEach((state, i) => sets.push(include[i].sets[state]));
310
+ node.negative.forEach((set, i) => {
311
+ const automaton = exclude[i];
312
+ for (const state of set)
313
+ if (automaton.kinds[state] === CHAR)
314
+ sets.push(automaton.sets[state]);
315
+ });
316
+ // Where each included automaton goes next does not depend on the
317
+ // character, only whether it may go; what the excluded ones reach does.
318
+ const successors = combinations(node.positive.map((state, i) => closureOf(include[i], [include[i].first[state]])));
319
+ for (const point of boundaryPoints(sets)) {
320
+ const validity = stepValidity(node.validity, point);
321
+ if (validity === INVALID)
322
+ continue;
323
+ if (!node.positive.every((state, i) => accepts(include[i].sets[state], point))) {
324
+ continue;
325
+ }
326
+ const negative = node.negative.map((set, i) => stepSet(exclude[i], set, point));
327
+ for (const positive of successors)
328
+ enqueue(positive, negative, validity, cursor, point);
329
+ }
330
+ }
331
+ return { kind: 'none' };
332
+ }
333
+ function spell(nodes, index) {
334
+ const points = [];
335
+ for (let i = index; nodes[i].parent >= 0; i = nodes[i].parent) {
336
+ points.push(nodes[i].point);
337
+ }
338
+ return String.fromCodePoint(...points.reverse());
339
+ }
340
+ //# sourceMappingURL=automaton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automaton.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/pattern/automaton.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Non-deterministic finite automata over code points: built by Thompson's\n * construction, run by keeping a set of live states, and searched for a\n * shortest string several of them accept and several others refuse.\n *\n * Why an automaton rather than a `RegExp`: a glob such as `*-*-*-*-*-*x`\n * handed to a backtracking engine tries every way of dividing a long name\n * between its stars, and one spec-* tool measured 28 seconds for one path. A\n * set of live states visits each state at most once per character, so a match\n * costs at most the pattern's size times the path's length, whatever the\n * pattern says.\n *\n * Why the same automaton for the witness: whether two scopes can name the same\n * file, and whether one lies wholly inside another, are questions about the\n * languages the patterns accept. Asked of the automata that do the matching,\n * the answers cannot drift from what matching does.\n */\n\nimport { accepts, acceptsIgnoringCase, boundaryPoints, DOT, SLASH, type CharSet } from './charset.js';\n\nconst CHAR = 0;\nconst SPLIT = 1;\nconst JUMP = 2;\nconst MATCH = 3;\n\n/** A compiled automaton. Immutable once built, and safe to share. */\nexport interface Automaton {\n readonly kinds: Uint8Array;\n /** A CHAR's next state, a SPLIT's first branch, a JUMP's target. */\n readonly first: Int32Array;\n /** A SPLIT's second branch. */\n readonly second: Int32Array;\n /** A CHAR's set; unused for the others. */\n readonly sets: readonly (CharSet | null)[];\n readonly start: number;\n readonly caseSensitive: boolean;\n}\n\n/** A piece of an automaton under construction: where it starts, and the arrows still unaimed. */\nexport interface Fragment {\n readonly start: number;\n readonly holes: readonly Hole[];\n}\n\ninterface Hole {\n readonly state: number;\n readonly slot: 1 | 2;\n}\n\n/**\n * Ceiling on the size of one automaton.\n *\n * Brace alternatives are compiled side by side, so a pattern's size is the\n * sum of its alternatives'. Far above anything a scope list says; it exists\n * so that a pathological pattern is refused while compiling rather than\n * matched slowly.\n */\nexport const MAX_STATES = 65_536;\n\nexport class AutomatonTooLarge extends Error {\n constructor() {\n super(`the pattern compiles to more than ${MAX_STATES} states`);\n this.name = 'AutomatonTooLarge';\n }\n}\n\n/** Thompson's construction, one fragment at a time. */\nexport class Builder {\n private readonly kinds: number[] = [];\n private readonly first: number[] = [];\n private readonly second: number[] = [];\n private readonly sets: (CharSet | null)[] = [];\n\n private add(kind: number, set: CharSet | null, first: number, second: number): number {\n if (this.kinds.length >= MAX_STATES) throw new AutomatonTooLarge();\n this.kinds.push(kind);\n this.first.push(first);\n this.second.push(second);\n this.sets.push(set);\n return this.kinds.length - 1;\n }\n\n private patch(holes: readonly Hole[], target: number): void {\n for (const hole of holes) {\n if (hole.slot === 1) this.first[hole.state] = target;\n else this.second[hole.state] = target;\n }\n }\n\n /** One character from a set. */\n char(set: CharSet): Fragment {\n const state = this.add(CHAR, set, -1, -1);\n return { start: state, holes: [{ state, slot: 1 }] };\n }\n\n /** The empty string. */\n empty(): Fragment {\n const state = this.add(JUMP, null, -1, -1);\n return { start: state, holes: [{ state, slot: 1 }] };\n }\n\n /** Each fragment after the one before it. */\n sequence(parts: readonly Fragment[]): Fragment {\n if (parts.length === 0) return this.empty();\n let current = parts[0] as Fragment;\n for (let i = 1; i < parts.length; i += 1) {\n const next = parts[i] as Fragment;\n this.patch(current.holes, next.start);\n current = { start: current.start, holes: next.holes };\n }\n return current;\n }\n\n /** Any one of the fragments. */\n either(options: readonly Fragment[]): Fragment {\n if (options.length === 0) throw new Error('an alternation needs at least one option');\n let current = options[options.length - 1] as Fragment;\n for (let i = options.length - 2; i >= 0; i -= 1) {\n const option = options[i] as Fragment;\n const split = this.add(SPLIT, null, option.start, current.start);\n current = { start: split, holes: [...option.holes, ...current.holes] };\n }\n return current;\n }\n\n /** Zero or more of a fragment. */\n star(body: Fragment): Fragment {\n const split = this.add(SPLIT, null, body.start, -1);\n this.patch(body.holes, split);\n return { start: split, holes: [{ state: split, slot: 2 }] };\n }\n\n /** One or more of a fragment. */\n plus(body: Fragment): Fragment {\n const split = this.add(SPLIT, null, body.start, -1);\n this.patch(body.holes, split);\n return { start: body.start, holes: [{ state: split, slot: 2 }] };\n }\n\n /** Zero or one of a fragment. */\n optional(body: Fragment): Fragment {\n const empty = this.empty();\n return this.either([body, empty]);\n }\n\n /** Closes the automaton: every unaimed arrow reaches acceptance. */\n finish(body: Fragment, caseSensitive: boolean): Automaton {\n const match = this.add(MATCH, null, -1, -1);\n this.patch(body.holes, match);\n return {\n kinds: Uint8Array.from(this.kinds),\n first: Int32Array.from(this.first),\n second: Int32Array.from(this.second),\n sets: [...this.sets],\n start: body.start,\n caseSensitive,\n };\n }\n}\n\n/**\n * Follows every empty arrow out of the states on a stack, appending each\n * CHAR or MATCH state reached to `into`. `visited[state] === stamp` marks a\n * state already taken this round, which is what bounds the work.\n */\nfunction close(\n automaton: Automaton,\n stack: number[],\n visited: Int32Array,\n stamp: number,\n into: number[],\n): void {\n const { kinds, first, second } = automaton;\n while (stack.length > 0) {\n const state = stack.pop() as number;\n if (visited[state] === stamp) continue;\n visited[state] = stamp;\n switch (kinds[state]) {\n case SPLIT:\n stack.push(second[state] as number, first[state] as number);\n break;\n case JUMP:\n stack.push(first[state] as number);\n break;\n default:\n into.push(state);\n }\n }\n}\n\n/**\n * A reusable matcher over one automaton.\n *\n * Holds its buffers between subjects; it is not reentrant, and nothing needs\n * it to be - matching calls out to nothing.\n */\nexport class Matcher {\n private readonly automaton: Automaton;\n private readonly visited: Int32Array;\n private stamp = 0;\n private readonly stack: number[] = [];\n private live: number[] = [];\n private next: number[] = [];\n\n constructor(automaton: Automaton) {\n this.automaton = automaton;\n this.visited = new Int32Array(automaton.kinds.length).fill(-1);\n }\n\n /** Whether the automaton accepts the whole of a subject. */\n test(subject: string): boolean {\n const { automaton } = this;\n const accept = automaton.caseSensitive ? accepts : acceptsIgnoringCase;\n this.live.length = 0;\n this.stack.length = 0;\n this.stack.push(automaton.start);\n this.stamp += 1;\n close(automaton, this.stack, this.visited, this.stamp, this.live);\n\n for (let i = 0; i < subject.length; i += 1) {\n const point = subject.codePointAt(i) as number;\n if (point > 0xffff) i += 1;\n this.next.length = 0;\n this.stamp += 1;\n for (const state of this.live) {\n if (automaton.kinds[state] !== CHAR) continue;\n if (!accept(automaton.sets[state] as CharSet, point)) continue;\n this.stack.push(automaton.first[state] as number);\n close(automaton, this.stack, this.visited, this.stamp, this.next);\n }\n if (this.next.length === 0) return false;\n const spent = this.live;\n this.live = this.next;\n this.next = spent;\n }\n return this.live.some((state) => automaton.kinds[state] === MATCH);\n }\n}\n\n/** The answer to a witness search. */\nexport type Witness =\n | { readonly kind: 'found'; readonly path: string }\n | { readonly kind: 'none' }\n /** The search met its budget before deciding. Rare, and never a guess either way. */\n | { readonly kind: 'undecided' };\n\n/**\n * How many distinct search states a witness search may visit. The search is\n * polynomial in the sizes of the automata it must satisfy and, for the ones\n * it must avoid, bounded by the subsets of their states it reaches; scope\n * patterns reach a handful. The bound turns a pathological input into an\n * `undecided` rather than a hang.\n */\nexport const WITNESS_BUDGET = 200_000;\n\n/**\n * Path validity as a four-state machine: at the start of a segment, inside a\n * segment reading `.` or `..` so far, or inside a segment that is a name. A\n * witness must end inside a name, and a `/` is only legal after one, so no\n * witness has an empty segment, a `.` or `..` segment, or a slash at either\n * end - which a pattern such as `a/*\\/b` would otherwise produce as `a//b`.\n * NUL is refused outright: no filesystem and no git tree holds a path with one.\n */\nconst SEGMENT_START = 0;\nconst ONE_DOT = 1;\nconst TWO_DOTS = 2;\nconst IN_NAME = 3;\nconst INVALID = -1;\nconst NUL = 0;\n\nfunction stepValidity(state: number, point: number): number {\n if (point === NUL) return INVALID;\n if (point === SLASH) return state === IN_NAME ? SEGMENT_START : INVALID;\n if (point === DOT) return state === SEGMENT_START ? ONE_DOT : state === ONE_DOT ? TWO_DOTS : IN_NAME;\n return IN_NAME;\n}\n\ninterface SearchNode {\n /** One live CHAR/MATCH state per automaton that must accept. */\n readonly positive: readonly number[];\n /** Every live state, sorted, per automaton that must refuse. */\n readonly negative: readonly (readonly number[])[];\n readonly validity: number;\n readonly parent: number;\n readonly point: number;\n}\n\nfunction closureOf(automaton: Automaton, seeds: readonly number[]): number[] {\n const visited = new Int32Array(automaton.kinds.length).fill(-1);\n const out: number[] = [];\n close(automaton, [...seeds], visited, 0, out);\n return out;\n}\n\nfunction stepSet(automaton: Automaton, states: readonly number[], point: number): number[] {\n const seeds: number[] = [];\n for (const state of states) {\n if (automaton.kinds[state] === CHAR && accepts(automaton.sets[state] as CharSet, point)) {\n seeds.push(automaton.first[state] as number);\n }\n }\n return closureOf(automaton, seeds).sort((a, b) => a - b);\n}\n\n/** Every way of choosing one element from each list. */\nfunction combinations(lists: readonly (readonly number[])[]): number[][] {\n let out: number[][] = [[]];\n for (const list of lists) {\n const grown: number[][] = [];\n for (const prefix of out) for (const state of list) grown.push([...prefix, state]);\n out = grown;\n }\n return out;\n}\n\nfunction isMatch(automaton: Automaton, state: number): boolean {\n return automaton.kinds[state] === MATCH;\n}\n\n/**\n * A shortest path every automaton in `include` accepts and none in `exclude`\n * does, spelled with readable characters where there is a choice.\n *\n * Breadth-first over the product of one live state per included automaton\n * (existential: some run of each must accept) and the whole live set per\n * excluded one (universal: no run of it may). Characters are tried at the\n * boundary points of every set in play, which meets every combination of\n * answers those sets can give, so the search is exact: `none` means no path\n * exists, not that none was found. The first path reached is a shortest one.\n *\n * Case-sensitive automata only. Every scope comparison in the family is\n * case-sensitive, and folding case exactly would need every set's closure\n * under case mapping.\n */\nexport function findWitness(\n include: readonly Automaton[],\n exclude: readonly Automaton[] = [],\n budget: number = WITNESS_BUDGET,\n): Witness {\n if (include.length === 0) throw new Error('a witness search needs at least one automaton to satisfy');\n for (const automaton of [...include, ...exclude]) {\n if (!automaton.caseSensitive) throw new Error('a witness search is defined for case-sensitive patterns only');\n }\n\n const startPositive = include.map((automaton) => closureOf(automaton, [automaton.start]));\n const startNegative = exclude.map((automaton) => closureOf(automaton, [automaton.start]).sort((a, b) => a - b));\n\n const nodes: SearchNode[] = [];\n const seen = new Set<string>();\n const key = (positive: readonly number[], negative: readonly (readonly number[])[], validity: number): string =>\n `${positive.join(',')}|${validity}|${negative.map((set) => set.join(',')).join('|')}`;\n\n const enqueue = (\n positive: readonly number[],\n negative: readonly (readonly number[])[],\n validity: number,\n parent: number,\n point: number,\n ): void => {\n const id = key(positive, negative, validity);\n if (seen.has(id)) return;\n seen.add(id);\n nodes.push({ positive, negative, validity, parent, point });\n };\n\n for (const positive of combinations(startPositive)) enqueue(positive, startNegative, SEGMENT_START, -1, 0);\n\n for (let cursor = 0; cursor < nodes.length; cursor += 1) {\n if (cursor >= budget) return { kind: 'undecided' };\n const node = nodes[cursor] as SearchNode;\n\n const accepted = node.positive.every((state, i) => isMatch(include[i] as Automaton, state));\n const refused = node.negative.every((set, i) => !set.some((state) => isMatch(exclude[i] as Automaton, state)));\n if (accepted && refused && node.validity === IN_NAME) return { kind: 'found', path: spell(nodes, cursor) };\n\n // A MATCH state reads nothing more: an included automaton sitting on one\n // can only accept here, so no longer path extends this node.\n if (node.positive.some((state, i) => (include[i] as Automaton).kinds[state] !== CHAR)) continue;\n\n const sets: CharSet[] = [];\n node.positive.forEach((state, i) => sets.push((include[i] as Automaton).sets[state] as CharSet));\n node.negative.forEach((set, i) => {\n const automaton = exclude[i] as Automaton;\n for (const state of set) if (automaton.kinds[state] === CHAR) sets.push(automaton.sets[state] as CharSet);\n });\n\n // Where each included automaton goes next does not depend on the\n // character, only whether it may go; what the excluded ones reach does.\n const successors = combinations(\n node.positive.map((state, i) => closureOf(include[i] as Automaton, [(include[i] as Automaton).first[state] as number])),\n );\n for (const point of boundaryPoints(sets)) {\n const validity = stepValidity(node.validity, point);\n if (validity === INVALID) continue;\n if (!node.positive.every((state, i) => accepts((include[i] as Automaton).sets[state] as CharSet, point))) {\n continue;\n }\n const negative = node.negative.map((set, i) => stepSet(exclude[i] as Automaton, set, point));\n for (const positive of successors) enqueue(positive, negative, validity, cursor, point);\n }\n }\n return { kind: 'none' };\n}\n\nfunction spell(nodes: readonly SearchNode[], index: number): string {\n const points: number[] = [];\n for (let i = index; (nodes[i] as SearchNode).parent >= 0; i = (nodes[i] as SearchNode).parent) {\n points.push((nodes[i] as SearchNode).point);\n }\n return String.fromCodePoint(...points.reverse());\n}\n"]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Sets of characters a glob position accepts, over Unicode code points.
3
+ *
4
+ * A glob matches a path one character at a time, and a character is a code
5
+ * point: `?` matches `é` whether it is stored as one UTF-16 unit or not, and an
6
+ * emoji as one. That is what a person counting characters in a file name
7
+ * expects, and it is the same on every host.
8
+ *
9
+ * No set but the separator's accepts `/`. A path is matched a segment at a
10
+ * time, and a `*` or a `[!a]` that swallowed a slash would let one segment of
11
+ * a pattern match two of a path.
12
+ */
13
+ /** An inclusive range of code points. */
14
+ export type CodeRange = readonly [number, number];
15
+ export interface CharSet {
16
+ readonly negated: boolean;
17
+ readonly ranges: readonly CodeRange[];
18
+ /** True only for the path separator itself. */
19
+ readonly separator: boolean;
20
+ }
21
+ export declare const SLASH = 47;
22
+ export declare const DOT = 46;
23
+ export declare const MAX_CODE_POINT = 1114111;
24
+ /** The separator, and nothing else. */
25
+ export declare const SEPARATOR: CharSet;
26
+ /** Any character but the separator: `?`, and the body of `*`. */
27
+ export declare const ANY: CharSet;
28
+ export declare function literalSet(point: number): CharSet;
29
+ export declare function classSet(ranges: readonly CodeRange[], negated: boolean): CharSet;
30
+ /** Whether a set accepts a code point as written. */
31
+ export declare function accepts(set: CharSet, point: number): boolean;
32
+ /**
33
+ * The code points a code point is the same letter as, ignoring case: itself,
34
+ * and its lower- and upper-case forms where each is a single code point.
35
+ *
36
+ * Simple case mapping, which is what `toLowerCase` and `toUpperCase` give one
37
+ * character at a time. It is locale-free, so two hosts agree; `ß` has no single
38
+ * upper-case code point and so matches only itself.
39
+ */
40
+ export declare function caseVariants(point: number): readonly number[];
41
+ /**
42
+ * Whether a set accepts a code point with case ignored: whether it accepts
43
+ * the point or one of its case variants. A negated set is negated over the
44
+ * same question, so `[!a]` refuses `A` as well as `a`.
45
+ */
46
+ export declare function acceptsIgnoringCase(set: CharSet, point: number): boolean;
47
+ /**
48
+ * Every code point at which the answer "which of these sets accept it" can
49
+ * change, readable ones first.
50
+ *
51
+ * Each set accepts a union of intervals, so the sets' memberships are constant
52
+ * between consecutive interval ends. The start of each interval and the point
53
+ * after its end therefore meet every distinct combination of answers, and
54
+ * trying them all decides every question a witness search can ask of one
55
+ * character. The separator and the dot are always included: path validity
56
+ * turns on them.
57
+ */
58
+ export declare function boundaryPoints(sets: readonly CharSet[]): number[];
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Sets of characters a glob position accepts, over Unicode code points.
3
+ *
4
+ * A glob matches a path one character at a time, and a character is a code
5
+ * point: `?` matches `é` whether it is stored as one UTF-16 unit or not, and an
6
+ * emoji as one. That is what a person counting characters in a file name
7
+ * expects, and it is the same on every host.
8
+ *
9
+ * No set but the separator's accepts `/`. A path is matched a segment at a
10
+ * time, and a `*` or a `[!a]` that swallowed a slash would let one segment of
11
+ * a pattern match two of a path.
12
+ */
13
+ export const SLASH = 0x2f;
14
+ export const DOT = 0x2e;
15
+ export const MAX_CODE_POINT = 0x10ffff;
16
+ /** The separator, and nothing else. */
17
+ export const SEPARATOR = { negated: false, ranges: [[SLASH, SLASH]], separator: true };
18
+ /** Any character but the separator: `?`, and the body of `*`. */
19
+ export const ANY = { negated: true, ranges: [], separator: false };
20
+ export function literalSet(point) {
21
+ return { negated: false, ranges: [[point, point]], separator: point === SLASH };
22
+ }
23
+ export function classSet(ranges, negated) {
24
+ return { negated, ranges, separator: false };
25
+ }
26
+ function within(ranges, point) {
27
+ for (let i = 0; i < ranges.length; i += 1) {
28
+ const range = ranges[i];
29
+ if (point >= range[0] && point <= range[1])
30
+ return true;
31
+ }
32
+ return false;
33
+ }
34
+ /** Whether a set accepts a code point as written. */
35
+ export function accepts(set, point) {
36
+ if (point === SLASH)
37
+ return set.separator;
38
+ return within(set.ranges, point) !== set.negated;
39
+ }
40
+ /**
41
+ * The code points a code point is the same letter as, ignoring case: itself,
42
+ * and its lower- and upper-case forms where each is a single code point.
43
+ *
44
+ * Simple case mapping, which is what `toLowerCase` and `toUpperCase` give one
45
+ * character at a time. It is locale-free, so two hosts agree; `ß` has no single
46
+ * upper-case code point and so matches only itself.
47
+ */
48
+ export function caseVariants(point) {
49
+ if (point < 0x80) {
50
+ if (point >= 0x41 && point <= 0x5a)
51
+ return [point, point + 32];
52
+ if (point >= 0x61 && point <= 0x7a)
53
+ return [point, point - 32];
54
+ return [point];
55
+ }
56
+ const char = String.fromCodePoint(point);
57
+ const out = [point];
58
+ for (const variant of [char.toLowerCase(), char.toUpperCase()]) {
59
+ const code = variant.codePointAt(0);
60
+ if (variant.length === String.fromCodePoint(code).length && !out.includes(code))
61
+ out.push(code);
62
+ }
63
+ return out;
64
+ }
65
+ /**
66
+ * Whether a set accepts a code point with case ignored: whether it accepts
67
+ * the point or one of its case variants. A negated set is negated over the
68
+ * same question, so `[!a]` refuses `A` as well as `a`.
69
+ */
70
+ export function acceptsIgnoringCase(set, point) {
71
+ if (point === SLASH)
72
+ return set.separator;
73
+ const variants = caseVariants(point);
74
+ let inside = false;
75
+ for (let i = 0; i < variants.length && !inside; i += 1)
76
+ inside = within(set.ranges, variants[i]);
77
+ return inside !== set.negated;
78
+ }
79
+ /**
80
+ * Characters a witness is spelled with when any of them will do, in order of
81
+ * preference. A witness is read by a person deciding whether two scopes really
82
+ * overlap, and `src/x.ts` reads better than `src/\u0000.ts`.
83
+ */
84
+ const READABLE = [0x78, 0x61, 0x62, 0x30, 0x5f, 0x2d, 0x7e, 0x21, DOT, SLASH];
85
+ /**
86
+ * Every code point at which the answer "which of these sets accept it" can
87
+ * change, readable ones first.
88
+ *
89
+ * Each set accepts a union of intervals, so the sets' memberships are constant
90
+ * between consecutive interval ends. The start of each interval and the point
91
+ * after its end therefore meet every distinct combination of answers, and
92
+ * trying them all decides every question a witness search can ask of one
93
+ * character. The separator and the dot are always included: path validity
94
+ * turns on them.
95
+ */
96
+ export function boundaryPoints(sets) {
97
+ // 1, not 0: no path holds a NUL, so the least character worth trying is the next.
98
+ const points = [...READABLE, 1];
99
+ for (const set of sets) {
100
+ for (const [low, high] of set.ranges) {
101
+ points.push(low);
102
+ if (high < MAX_CODE_POINT)
103
+ points.push(high + 1);
104
+ }
105
+ }
106
+ const seen = new Set();
107
+ const out = [];
108
+ for (const point of points) {
109
+ if (seen.has(point))
110
+ continue;
111
+ seen.add(point);
112
+ out.push(point);
113
+ }
114
+ return out;
115
+ }
116
+ //# sourceMappingURL=charset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"charset.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/pattern/charset.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Sets of characters a glob position accepts, over Unicode code points.\n *\n * A glob matches a path one character at a time, and a character is a code\n * point: `?` matches `é` whether it is stored as one UTF-16 unit or not, and an\n * emoji as one. That is what a person counting characters in a file name\n * expects, and it is the same on every host.\n *\n * No set but the separator's accepts `/`. A path is matched a segment at a\n * time, and a `*` or a `[!a]` that swallowed a slash would let one segment of\n * a pattern match two of a path.\n */\n\n/** An inclusive range of code points. */\nexport type CodeRange = readonly [number, number];\n\nexport interface CharSet {\n readonly negated: boolean;\n readonly ranges: readonly CodeRange[];\n /** True only for the path separator itself. */\n readonly separator: boolean;\n}\n\nexport const SLASH = 0x2f;\nexport const DOT = 0x2e;\nexport const MAX_CODE_POINT = 0x10ffff;\n\n/** The separator, and nothing else. */\nexport const SEPARATOR: CharSet = { negated: false, ranges: [[SLASH, SLASH]], separator: true };\n\n/** Any character but the separator: `?`, and the body of `*`. */\nexport const ANY: CharSet = { negated: true, ranges: [], separator: false };\n\nexport function literalSet(point: number): CharSet {\n return { negated: false, ranges: [[point, point]], separator: point === SLASH };\n}\n\nexport function classSet(ranges: readonly CodeRange[], negated: boolean): CharSet {\n return { negated, ranges, separator: false };\n}\n\nfunction within(ranges: readonly CodeRange[], point: number): boolean {\n for (let i = 0; i < ranges.length; i += 1) {\n const range = ranges[i] as CodeRange;\n if (point >= range[0] && point <= range[1]) return true;\n }\n return false;\n}\n\n/** Whether a set accepts a code point as written. */\nexport function accepts(set: CharSet, point: number): boolean {\n if (point === SLASH) return set.separator;\n return within(set.ranges, point) !== set.negated;\n}\n\n/**\n * The code points a code point is the same letter as, ignoring case: itself,\n * and its lower- and upper-case forms where each is a single code point.\n *\n * Simple case mapping, which is what `toLowerCase` and `toUpperCase` give one\n * character at a time. It is locale-free, so two hosts agree; `ß` has no single\n * upper-case code point and so matches only itself.\n */\nexport function caseVariants(point: number): readonly number[] {\n if (point < 0x80) {\n if (point >= 0x41 && point <= 0x5a) return [point, point + 32];\n if (point >= 0x61 && point <= 0x7a) return [point, point - 32];\n return [point];\n }\n const char = String.fromCodePoint(point);\n const out = [point];\n for (const variant of [char.toLowerCase(), char.toUpperCase()]) {\n const code = variant.codePointAt(0) as number;\n if (variant.length === String.fromCodePoint(code).length && !out.includes(code)) out.push(code);\n }\n return out;\n}\n\n/**\n * Whether a set accepts a code point with case ignored: whether it accepts\n * the point or one of its case variants. A negated set is negated over the\n * same question, so `[!a]` refuses `A` as well as `a`.\n */\nexport function acceptsIgnoringCase(set: CharSet, point: number): boolean {\n if (point === SLASH) return set.separator;\n const variants = caseVariants(point);\n let inside = false;\n for (let i = 0; i < variants.length && !inside; i += 1) inside = within(set.ranges, variants[i] as number);\n return inside !== set.negated;\n}\n\n/**\n * Characters a witness is spelled with when any of them will do, in order of\n * preference. A witness is read by a person deciding whether two scopes really\n * overlap, and `src/x.ts` reads better than `src/\\u0000.ts`.\n */\nconst READABLE = [0x78, 0x61, 0x62, 0x30, 0x5f, 0x2d, 0x7e, 0x21, DOT, SLASH] as const;\n\n/**\n * Every code point at which the answer \"which of these sets accept it\" can\n * change, readable ones first.\n *\n * Each set accepts a union of intervals, so the sets' memberships are constant\n * between consecutive interval ends. The start of each interval and the point\n * after its end therefore meet every distinct combination of answers, and\n * trying them all decides every question a witness search can ask of one\n * character. The separator and the dot are always included: path validity\n * turns on them.\n */\nexport function boundaryPoints(sets: readonly CharSet[]): number[] {\n // 1, not 0: no path holds a NUL, so the least character worth trying is the next.\n const points: number[] = [...READABLE, 1];\n for (const set of sets) {\n for (const [low, high] of set.ranges) {\n points.push(low);\n if (high < MAX_CODE_POINT) points.push(high + 1);\n }\n }\n const seen = new Set<number>();\n const out: number[] = [];\n for (const point of points) {\n if (seen.has(point)) continue;\n seen.add(point);\n out.push(point);\n }\n return out;\n}\n"]}