@miller-tech/uap 1.173.0 → 1.174.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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/delivery/agentic-executor.d.ts +2 -1
- package/dist/delivery/agentic-executor.d.ts.map +1 -1
- package/dist/delivery/agentic-executor.js +50 -4
- package/dist/delivery/agentic-executor.js.map +1 -1
- package/dist/delivery/bash-sweep.d.ts +188 -0
- package/dist/delivery/bash-sweep.d.ts.map +1 -0
- package/dist/delivery/bash-sweep.js +610 -0
- package/dist/delivery/bash-sweep.js.map +1 -0
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-end substance sweep for files written through `run_bash`.
|
|
3
|
+
*
|
|
4
|
+
* The stub guard covers `write_file` and `edit_file`. `run_bash` bypasses both:
|
|
5
|
+
* `cat > f <<'EOF' … EOF`, `sed -i` and `python -c "open(...).write(...)"` all
|
|
6
|
+
* land content without passing through a tool handler. That was recorded as a
|
|
7
|
+
* known limit when the guard shipped (PR #611) rather than papered over, and
|
|
8
|
+
* this closes it.
|
|
9
|
+
*
|
|
10
|
+
* WHY A SWEEP AND NOT A CHECK IN THE HANDLER
|
|
11
|
+
* The other run_bash protections work by SNAPSHOTTING a known set — protected
|
|
12
|
+
* tests, locked contracts, gate configs — and restoring whatever the command
|
|
13
|
+
* touched. That works because those sets are enumerable up front. The set of
|
|
14
|
+
* files a shell command might write is not, so there is nothing to snapshot by
|
|
15
|
+
* name. The sweep instead takes a baseline of the tree at the first command and
|
|
16
|
+
* compares at turn end, which is the only way to attribute an arbitrary write.
|
|
17
|
+
*
|
|
18
|
+
* THE COST MODEL IS INVERTED FROM THE WRITE PATH, AND THAT DRIVES EVERYTHING
|
|
19
|
+
* On the write path a false positive costs one retry: the write is refused and
|
|
20
|
+
* the model tries again. Here a false positive touches a file that already
|
|
21
|
+
* exists, so it costs WORK. Four consequences, each of which an earlier version
|
|
22
|
+
* of this file got wrong and each of which now has a test:
|
|
23
|
+
*
|
|
24
|
+
* 1. Absence of baseline CONTENT never implies absence of the FILE. Existence
|
|
25
|
+
* is recorded for every path with no read and no byte budget, so a file the
|
|
26
|
+
* content baseline skipped — capped, oversized, unreadable — is still known
|
|
27
|
+
* to have existed. Only a path absent from `known` may be treated as created
|
|
28
|
+
* this turn. Without that split, a file the baseline had skipped was DELETED
|
|
29
|
+
* when the shell shrank it, and on a tree past the cap files the shell never
|
|
30
|
+
* touched became deletion candidates.
|
|
31
|
+
* 2. Nothing the harness has SEEN is destroyed, and nothing leaves the project.
|
|
32
|
+
* Every removal and every revert preserves the current content under
|
|
33
|
+
* `.uap/bash-sweep-backup/` first, a failed preserve aborts the action, and
|
|
34
|
+
* every destination is proven to resolve inside that directory. The limit is
|
|
35
|
+
* worth stating precisely, because a broader claim would be false: a revert
|
|
36
|
+
* restores the last content the harness AUTHORISED, so if one shell command
|
|
37
|
+
* writes real code and a later command in the SAME turn hollows it, the
|
|
38
|
+
* intermediate version — which no tool handler ever saw — is not recovered.
|
|
39
|
+
* The rejected content is preserved; the unobserved good version is not. `relative()` used to be run through
|
|
40
|
+
* `.split('\\')`, which is correct on Windows and WRONG on POSIX where a
|
|
41
|
+
* backslash is a legal filename character: one directory entry named
|
|
42
|
+
* `..\..\..\..\x.js` produced a traversing key and the sweep wrote and
|
|
43
|
+
* RENAMED outside the project root. (Reproduced; test below. The harness
|
|
44
|
+
* already documents that the small model mangles paths, so this needed no
|
|
45
|
+
* adversary.)
|
|
46
|
+
* 3. An existing file is only reverted when the change made it STRICTLY WORSE —
|
|
47
|
+
* more empty bodies than the content we authorised. A formatter or codemod
|
|
48
|
+
* that rewrites an already-stubby file without emptying anything further is
|
|
49
|
+
* left alone, because reverting it would be both wrong and unexplainable
|
|
50
|
+
* ("your shell command wrote SKELETONS" about `prettier --write`).
|
|
51
|
+
* 4. Silence must mean "nothing changed", not "we could not look". Coverage
|
|
52
|
+
* gaps are reported — but ONLY for files that actually changed. Reporting
|
|
53
|
+
* every unreadable path made a single `logo.png` emit a coverage warning on
|
|
54
|
+
* every bash turn of every asset-bearing project, into a prompt slot that is
|
|
55
|
+
* head-truncated.
|
|
56
|
+
*
|
|
57
|
+
* WHAT COUNTS AS THE BASELINE
|
|
58
|
+
* Per file, the last content this harness knows it authorised: what a guarded
|
|
59
|
+
* tool wrote this turn if one did, otherwise the content at the first command.
|
|
60
|
+
* Using "was it written by a guarded tool" as a plain skip would leave a hole —
|
|
61
|
+
* write the real implementation with write_file, then hollow it out with sed,
|
|
62
|
+
* and the path is on the allow-list. Comparing against the authorised CONTENT
|
|
63
|
+
* closes it. A file CREATED this turn is judged on its own content regardless of
|
|
64
|
+
* authorisation, which closes the mirror hole: the shell writes a skeleton, then
|
|
65
|
+
* a single edit_file fills one body and the monotone-progress rule — measuring
|
|
66
|
+
* against the skeleton itself — stamps the rest as authorised.
|
|
67
|
+
*
|
|
68
|
+
* SCOPE, STATED PLAINLY
|
|
69
|
+
* This is a correctness guard against confused generation, not a security
|
|
70
|
+
* boundary. A model holding a shell can do anything a shell can do, including
|
|
71
|
+
* removing this check; run_bash is gated on kernel containment for that reason.
|
|
72
|
+
* The sweep judges SUBSTANCE only — a command that deletes a real file is a
|
|
73
|
+
* different failure and is not restored here. And a quarantine can leave the
|
|
74
|
+
* tree in a state neither the model nor the gates have seen: a `main.js` written
|
|
75
|
+
* by write_file may import a `player.js` the sweep removed. The gates see that
|
|
76
|
+
* and the note names the repair, which is the intended outcome, but it is a real
|
|
77
|
+
* intermediate state rather than a clean rollback.
|
|
78
|
+
*/
|
|
79
|
+
import { readdirSync, statSync, fstatSync, writeFileSync, mkdirSync, renameSync, realpathSync, lstatSync, existsSync, openSync, readSync, closeSync, constants as fsConstants, } from 'fs';
|
|
80
|
+
import { join, relative, resolve, dirname, sep } from 'path';
|
|
81
|
+
import { detectStub, stubGuardDisabled } from './stub-detector.js';
|
|
82
|
+
import { CONTEXT_BUDGET_MARKER } from './context-budget.js';
|
|
83
|
+
/**
|
|
84
|
+
* Never walked at any depth: version control, dependencies, harness state,
|
|
85
|
+
* language caches and vendored third-party trees. `.git` and `node_modules` also
|
|
86
|
+
* hold code that would be judged as if the model had authored it — and the
|
|
87
|
+
* harness actively steers models to vendor dependencies locally when a CDN fetch
|
|
88
|
+
* fails, so `vendor`/`third_party` are the same case by another name.
|
|
89
|
+
*/
|
|
90
|
+
const ALWAYS_SKIP = new Set([
|
|
91
|
+
'.git',
|
|
92
|
+
'node_modules',
|
|
93
|
+
'.uap',
|
|
94
|
+
'.uap-deliver',
|
|
95
|
+
'.uap-backups',
|
|
96
|
+
'__pycache__',
|
|
97
|
+
'.pytest_cache',
|
|
98
|
+
'.mypy_cache',
|
|
99
|
+
'.ruff_cache',
|
|
100
|
+
'.tox',
|
|
101
|
+
'.venv',
|
|
102
|
+
'venv',
|
|
103
|
+
'.cache',
|
|
104
|
+
'.next',
|
|
105
|
+
'.nuxt',
|
|
106
|
+
'.svelte-kit',
|
|
107
|
+
'.turbo',
|
|
108
|
+
'vendor',
|
|
109
|
+
'third_party',
|
|
110
|
+
// Every other tree-walk in this package excludes these; this one omitted them.
|
|
111
|
+
// A sweep rooted at a repo that follows the worktree workflow would otherwise
|
|
112
|
+
// walk N full checkouts, and `agents/` holds the memory/coordination SQLite
|
|
113
|
+
// stores and the vector index.
|
|
114
|
+
'.worktrees',
|
|
115
|
+
'agents',
|
|
116
|
+
]);
|
|
117
|
+
/**
|
|
118
|
+
* Build output — skipped only at the PROJECT ROOT. Matching these at any depth
|
|
119
|
+
* made `src/build/`, `app/out/` and `pkg/target/` permanent blind spots, and for
|
|
120
|
+
* a web mission the deliverable itself sometimes lives in `build/` or `out/`.
|
|
121
|
+
*/
|
|
122
|
+
const ROOT_ONLY_SKIP = new Set(['dist', 'build', 'out', 'coverage', 'target']);
|
|
123
|
+
/**
|
|
124
|
+
* A delivery target is an application, not a monorepo, so these sit far above
|
|
125
|
+
* any real project — they exist so a mission pointed at something huge degrades
|
|
126
|
+
* predictably instead of reading gigabytes inside a turn boundary. Injectable so
|
|
127
|
+
* tests exercise the capped paths for real rather than setting a flag by hand.
|
|
128
|
+
*/
|
|
129
|
+
export const DEFAULT_LIMITS = {
|
|
130
|
+
maxFiles: 3000,
|
|
131
|
+
maxTotalBytes: 16 * 1024 * 1024,
|
|
132
|
+
maxFileBytes: 200_000,
|
|
133
|
+
};
|
|
134
|
+
/** Where displaced content goes. Inside `.uap`, so the sweep never re-walks it. */
|
|
135
|
+
export const BACKUP_DIR = join('.uap', 'bash-sweep-backup');
|
|
136
|
+
/** Fresh on every call: a shared singleton lets one caller's mutation leak. */
|
|
137
|
+
function emptyOutcome() {
|
|
138
|
+
return { reverted: [], removed: [], uncovered: [], failed: [], note: '' };
|
|
139
|
+
}
|
|
140
|
+
/** A sweep that never fires — for callers with bash disabled. */
|
|
141
|
+
export function disabledSweep() {
|
|
142
|
+
return {
|
|
143
|
+
enabled: false,
|
|
144
|
+
projectRoot: '',
|
|
145
|
+
bashRan: false,
|
|
146
|
+
baselined: false,
|
|
147
|
+
swept: false,
|
|
148
|
+
authorised: new Map(),
|
|
149
|
+
baseline: new Map(),
|
|
150
|
+
known: new Set(),
|
|
151
|
+
statAt: new Map(),
|
|
152
|
+
truncated: false,
|
|
153
|
+
limits: DEFAULT_LIMITS,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Project-relative key for a walked path.
|
|
158
|
+
*
|
|
159
|
+
* Separator translation happens ONLY on Windows. Doing it unconditionally is the
|
|
160
|
+
* bug described in the header: on POSIX a backslash is a legal filename
|
|
161
|
+
* character, so translating it manufactures `..` segments out of a single
|
|
162
|
+
* directory entry.
|
|
163
|
+
*/
|
|
164
|
+
function relKey(projectRoot, abs) {
|
|
165
|
+
const rel = relative(projectRoot, abs);
|
|
166
|
+
return sep === '\\' ? rel.split('\\').join('/') : rel;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Read a file as text, or null when it is binary, unreadable, or not a regular
|
|
170
|
+
* file by the time it is opened.
|
|
171
|
+
*
|
|
172
|
+
* Opened non-blocking and re-checked through `fstat` on the open descriptor: a
|
|
173
|
+
* background process left running by the command can swap a file for a FIFO
|
|
174
|
+
* between the directory read and this open, and a blocking open on a FIFO with
|
|
175
|
+
* no writer hangs forever — inside the turn boundary, which stops the deliver
|
|
176
|
+
* heartbeat and invites the lock's wedge-reclaim to kill a run that is merely
|
|
177
|
+
* blocked.
|
|
178
|
+
*/
|
|
179
|
+
function readText(abs, maxBytes) {
|
|
180
|
+
let fd = -1;
|
|
181
|
+
try {
|
|
182
|
+
fd = openSync(abs, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK);
|
|
183
|
+
const st = fstatSync(fd);
|
|
184
|
+
if (!st.isFile() || st.size > maxBytes)
|
|
185
|
+
return null;
|
|
186
|
+
const buf = Buffer.alloc(st.size);
|
|
187
|
+
let off = 0;
|
|
188
|
+
while (off < st.size) {
|
|
189
|
+
const n = readSync(fd, buf, off, st.size - off, off);
|
|
190
|
+
if (n <= 0)
|
|
191
|
+
break;
|
|
192
|
+
off += n;
|
|
193
|
+
}
|
|
194
|
+
// Binary sniff. The detector exempts a fixed list of extensions and scans
|
|
195
|
+
// everything else — right for a write path (the model writes source) and wrong
|
|
196
|
+
// for a whole-tree walk, where a .png/.wasm/.db under the read cap would be
|
|
197
|
+
// decoded as UTF-8, held in the baseline, and fed to a brace scanner.
|
|
198
|
+
if (buf.subarray(0, Math.min(off, 8192)).includes(0))
|
|
199
|
+
return null;
|
|
200
|
+
const text = buf.subarray(0, off).toString('utf-8');
|
|
201
|
+
// The decoded string is what gets written BACK on a revert, so a lossy decode
|
|
202
|
+
// would silently corrupt the file it is meant to restore. Latin-1 source, or a
|
|
203
|
+
// NUL past the 8 KB sniff window, round-trips through U+FFFD; a byte-length
|
|
204
|
+
// mismatch is the cheap, exact test for that. Treat it as out of scope.
|
|
205
|
+
if (Buffer.byteLength(text, 'utf-8') !== off)
|
|
206
|
+
return null;
|
|
207
|
+
return text;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
finally {
|
|
213
|
+
if (fd >= 0) {
|
|
214
|
+
try {
|
|
215
|
+
closeSync(fd);
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
/* ignore */
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/** Walk project files, calling `onFile` for each. Continues past unreadable dirs. */
|
|
224
|
+
function walk(projectRoot, onFile) {
|
|
225
|
+
const stack = [projectRoot];
|
|
226
|
+
while (stack.length > 0) {
|
|
227
|
+
const dir = stack.pop();
|
|
228
|
+
let entries;
|
|
229
|
+
try {
|
|
230
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
continue; // unreadable directory — not a reason to fail the turn
|
|
234
|
+
}
|
|
235
|
+
const atRoot = dir === projectRoot;
|
|
236
|
+
for (const e of entries) {
|
|
237
|
+
if (e.isSymbolicLink())
|
|
238
|
+
continue; // never follow: a link can leave the root
|
|
239
|
+
const abs = join(dir, e.name);
|
|
240
|
+
if (e.isDirectory()) {
|
|
241
|
+
if (ALWAYS_SKIP.has(e.name))
|
|
242
|
+
continue;
|
|
243
|
+
if (atRoot && ROOT_ONLY_SKIP.has(e.name))
|
|
244
|
+
continue;
|
|
245
|
+
stack.push(abs);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (!e.isFile())
|
|
249
|
+
continue;
|
|
250
|
+
let st;
|
|
251
|
+
try {
|
|
252
|
+
st = statSync(abs);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
onFile(relKey(projectRoot, abs), abs, st.size, st.mtimeMs);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const ACTIVE_ROOTS = new Set();
|
|
262
|
+
/**
|
|
263
|
+
* Arm the sweep for a turn. Deliberately does NOT walk anything.
|
|
264
|
+
*
|
|
265
|
+
* The baseline is captured lazily, at the first command, so a bash-enabled
|
|
266
|
+
* session that does not actually shell out in a given turn pays nothing.
|
|
267
|
+
* Deferring is safe because of what `authorised` holds: anything that changed
|
|
268
|
+
* BEFORE the first command can only have come from a guarded tool, and those
|
|
269
|
+
* writes are recorded by content as they happen.
|
|
270
|
+
*/
|
|
271
|
+
export function beginBashSweep(projectRoot, enabled, limits = DEFAULT_LIMITS) {
|
|
272
|
+
if (!enabled || stubGuardDisabled())
|
|
273
|
+
return disabledSweep();
|
|
274
|
+
// Two live sweeps over ONE tree would cross-attribute: A's baseline predates
|
|
275
|
+
// B's guarded writes, so A can revert or quarantine a file B legitimately
|
|
276
|
+
// created, and both would write the same backup paths. Nothing in the current
|
|
277
|
+
// wiring runs concurrent agentic executors on a shared root, but that is a
|
|
278
|
+
// decision in another file and this module is exported. Degrade to no sweep
|
|
279
|
+
// rather than trust it: a missed check is recoverable, a wrong revert is not.
|
|
280
|
+
if (ACTIVE_ROOTS.has(projectRoot))
|
|
281
|
+
return disabledSweep();
|
|
282
|
+
ACTIVE_ROOTS.add(projectRoot);
|
|
283
|
+
return {
|
|
284
|
+
enabled: true,
|
|
285
|
+
projectRoot,
|
|
286
|
+
bashRan: false,
|
|
287
|
+
baselined: false,
|
|
288
|
+
swept: false,
|
|
289
|
+
authorised: new Map(),
|
|
290
|
+
baseline: new Map(),
|
|
291
|
+
known: new Set(),
|
|
292
|
+
statAt: new Map(),
|
|
293
|
+
truncated: false,
|
|
294
|
+
limits,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Arm for a command: mark that the shell ran, and capture the baseline once.
|
|
299
|
+
*
|
|
300
|
+
* Called from the run_bash handler BEFORE the spawn — a command that times out
|
|
301
|
+
* or is killed may still have written files, and a sweep with nothing to compare
|
|
302
|
+
* against would be worse than none, reporting "checked" over the messiest case.
|
|
303
|
+
*/
|
|
304
|
+
export function armSweepForCommand(sweep) {
|
|
305
|
+
if (!sweep.enabled)
|
|
306
|
+
return;
|
|
307
|
+
sweep.bashRan = true;
|
|
308
|
+
if (sweep.baselined)
|
|
309
|
+
return;
|
|
310
|
+
sweep.baselined = true;
|
|
311
|
+
let bytes = 0;
|
|
312
|
+
walk(sweep.projectRoot, (rel, abs, size, mtimeMs) => {
|
|
313
|
+
// EXISTENCE and STAT are recorded for every file, unconditionally. Existence
|
|
314
|
+
// stops a gap in the content baseline from being read as "this file is new";
|
|
315
|
+
// size is what lets a later change to an unbaselined file still be noticed,
|
|
316
|
+
// so coverage warnings name files that actually moved.
|
|
317
|
+
sweep.known.add(rel);
|
|
318
|
+
sweep.statAt.set(rel, { size, mtimeMs });
|
|
319
|
+
if (size > sweep.limits.maxFileBytes)
|
|
320
|
+
return; // handled via sizeAt, not a truncation
|
|
321
|
+
if (sweep.baseline.size >= sweep.limits.maxFiles || bytes + size > sweep.limits.maxTotalBytes) {
|
|
322
|
+
sweep.truncated = true;
|
|
323
|
+
return; // keep walking: existence still needs the rest of the tree
|
|
324
|
+
}
|
|
325
|
+
const text = readText(abs, sweep.limits.maxFileBytes);
|
|
326
|
+
if (text === null)
|
|
327
|
+
return; // binary — out of scope, and not a coverage gap
|
|
328
|
+
sweep.baseline.set(rel, text);
|
|
329
|
+
bytes += size;
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/** Record what a guarded tool wrote, so a later shell write is distinguishable. */
|
|
333
|
+
export function recordAuthorisedWrite(sweep, rel, content) {
|
|
334
|
+
if (sweep.enabled)
|
|
335
|
+
sweep.authorised.set(rel, content);
|
|
336
|
+
}
|
|
337
|
+
/** Empty bodies in a verdict — the quantity the "strictly worse" test compares. */
|
|
338
|
+
function emptyCount(v) {
|
|
339
|
+
return Math.round(v.emptyRatio * v.callables);
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Resolve the backup root and prove it is really inside the project.
|
|
343
|
+
*
|
|
344
|
+
* The walk never follows symlinks, so no path it yields can escape — but the
|
|
345
|
+
* backup root is a path this module CONSTRUCTS rather than discovers, and `.uap`
|
|
346
|
+
* is a directory a shell command can replace with a link. Measured before this
|
|
347
|
+
* check existed: `ln -s /elsewhere .uap` and the sweep's own backups landed
|
|
348
|
+
* outside the project root. Returns null when the location cannot be trusted,
|
|
349
|
+
* which disables every mutation rather than performing an unbacked-up one.
|
|
350
|
+
*/
|
|
351
|
+
function resolveBackupRoot(projectRoot) {
|
|
352
|
+
try {
|
|
353
|
+
const holder = join(projectRoot, '.uap');
|
|
354
|
+
// Check the component we create THROUGH before creating anything, so a
|
|
355
|
+
// redirected root does not even leave an empty directory behind.
|
|
356
|
+
try {
|
|
357
|
+
if (lstatSync(holder).isSymbolicLink())
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
/* absent — mkdir below creates it inside the project */
|
|
362
|
+
}
|
|
363
|
+
const dest = join(projectRoot, BACKUP_DIR);
|
|
364
|
+
mkdirSync(dest, { recursive: true });
|
|
365
|
+
const realDest = realpathSync(dest);
|
|
366
|
+
const realRoot = realpathSync(projectRoot);
|
|
367
|
+
return realDest === realRoot || realDest.startsWith(realRoot + sep) ? realDest : null;
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Destination inside the backup root for `rel`, or null if it would escape.
|
|
375
|
+
*
|
|
376
|
+
* Belt-and-braces now that `relKey` no longer manufactures `..` segments, but
|
|
377
|
+
* this is the check that actually contains the failure rather than the one that
|
|
378
|
+
* avoids provoking it — and it is two lines.
|
|
379
|
+
*/
|
|
380
|
+
function backupDest(backupRoot, rel) {
|
|
381
|
+
const dest = resolve(backupRoot, rel);
|
|
382
|
+
return dest.startsWith(backupRoot + sep) ? dest : null;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* A destination that will not clobber an earlier turn's backup.
|
|
386
|
+
*
|
|
387
|
+
* "Nothing is destroyed" has to hold ACROSS turns, and the retry loop is
|
|
388
|
+
* designed to re-attempt the same file — so the same `rel` being quarantined
|
|
389
|
+
* twice is the common case, not an edge one.
|
|
390
|
+
*/
|
|
391
|
+
function freeDest(dest) {
|
|
392
|
+
if (!existsSync(dest))
|
|
393
|
+
return dest;
|
|
394
|
+
for (let i = 2; i < 1000; i++) {
|
|
395
|
+
const candidate = `${dest}.${i}`;
|
|
396
|
+
if (!existsSync(candidate))
|
|
397
|
+
return candidate;
|
|
398
|
+
}
|
|
399
|
+
return `${dest}.overflow`;
|
|
400
|
+
}
|
|
401
|
+
/** Copy content into the backup root. False means the caller must NOT mutate. */
|
|
402
|
+
function backup(backupRoot, rel, content) {
|
|
403
|
+
const dest = backupDest(backupRoot, rel);
|
|
404
|
+
if (dest === null)
|
|
405
|
+
return null;
|
|
406
|
+
try {
|
|
407
|
+
const target = freeDest(dest);
|
|
408
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
409
|
+
writeFileSync(target, content, 'utf-8');
|
|
410
|
+
return target;
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Compare the tree against the baseline and undo unattributed stub writes.
|
|
418
|
+
* Returns an empty outcome when bash never ran, so the common path is a boolean.
|
|
419
|
+
*/
|
|
420
|
+
export function finishBashSweep(sweep) {
|
|
421
|
+
if (!sweep.enabled)
|
|
422
|
+
return emptyOutcome();
|
|
423
|
+
// Released here rather than by the caller: the executor's `finally` guarantees
|
|
424
|
+
// this runs, and a root left marked active would silently disable the guard for
|
|
425
|
+
// every later turn.
|
|
426
|
+
ACTIVE_ROOTS.delete(sweep.projectRoot);
|
|
427
|
+
if (!sweep.bashRan || sweep.swept || stubGuardDisabled())
|
|
428
|
+
return emptyOutcome();
|
|
429
|
+
sweep.swept = true;
|
|
430
|
+
const reverted = [];
|
|
431
|
+
const removed = [];
|
|
432
|
+
const uncovered = [];
|
|
433
|
+
const failed = [];
|
|
434
|
+
// Established once, before anything is touched. A backup location that cannot
|
|
435
|
+
// be proven inside the project means no mutation happens at all this turn.
|
|
436
|
+
const backupRoot = resolveBackupRoot(sweep.projectRoot);
|
|
437
|
+
walk(sweep.projectRoot, (rel, abs, size, mtimeMs) => {
|
|
438
|
+
const existedBefore = sweep.known.has(rel);
|
|
439
|
+
const before = sweep.statAt.get(rel);
|
|
440
|
+
const changedStat = before === undefined || before.size !== size || before.mtimeMs !== mtimeMs;
|
|
441
|
+
// Unmoved and not written by a guarded tool this turn: nothing to judge, and
|
|
442
|
+
// no reason to pay a full read. This is most of the tree on most turns.
|
|
443
|
+
if (!changedStat && !sweep.authorised.has(rel))
|
|
444
|
+
return;
|
|
445
|
+
// The last content this harness authorised: a guarded write this turn, else
|
|
446
|
+
// whatever was there when the first command ran.
|
|
447
|
+
const authorised = sweep.authorised.get(rel) ?? sweep.baseline.get(rel);
|
|
448
|
+
if (size > sweep.limits.maxFileBytes) {
|
|
449
|
+
// Too big to read now, so it can be neither judged nor reverted. Report it
|
|
450
|
+
// only if it demonstrably moved — otherwise every project with a large
|
|
451
|
+
// lockfile emits a coverage warning on every single bash turn.
|
|
452
|
+
if (existedBefore ? changedStat : true)
|
|
453
|
+
uncovered.push(rel);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const current = readText(abs, sweep.limits.maxFileBytes);
|
|
457
|
+
if (current === null)
|
|
458
|
+
return; // binary or unreadable — out of scope entirely
|
|
459
|
+
if (existedBefore && authorised === undefined) {
|
|
460
|
+
// Known to have existed, but no content is held for it — the content
|
|
461
|
+
// baseline was capped. Report only a real change; guessing here is what
|
|
462
|
+
// deleted pre-existing files in the first version of this module.
|
|
463
|
+
uncovered.push(rel);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (!existedBefore) {
|
|
467
|
+
// Created this turn. Judged on its own content REGARDLESS of authorisation,
|
|
468
|
+
// and BEFORE the unchanged-since-authorised skip below — that skip is what
|
|
469
|
+
// made the laundering hole real: the shell writes a skeleton, one edit_file
|
|
470
|
+
// fills a single body (legitimately allowed, since monotone progress is
|
|
471
|
+
// measured against the skeleton itself), the file is stamped as authorised,
|
|
472
|
+
// and a content comparison then matches and skips it forever.
|
|
473
|
+
if (!detectStub(rel, current).isStub)
|
|
474
|
+
return;
|
|
475
|
+
// Rename IS the backup here — the file's own bytes move to the preserved
|
|
476
|
+
// location. Writing a copy first and then renaming over it, as this did
|
|
477
|
+
// originally, paid a full write that the rename immediately discarded and
|
|
478
|
+
// left a stray duplicate whenever the rename failed.
|
|
479
|
+
const dest = backupRoot === null ? null : backupDest(backupRoot, rel);
|
|
480
|
+
if (dest === null) {
|
|
481
|
+
failed.push(rel);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
const target = freeDest(dest);
|
|
486
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
487
|
+
renameSync(abs, target);
|
|
488
|
+
removed.push(rel);
|
|
489
|
+
}
|
|
490
|
+
catch {
|
|
491
|
+
failed.push(rel);
|
|
492
|
+
}
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
if (authorised === current)
|
|
496
|
+
return; // untouched since we last saw it
|
|
497
|
+
// Pre-existing and changed. Act only when the change made it STRICTLY WORSE:
|
|
498
|
+
// a formatter or codemod that rewrites an already-stubby file without
|
|
499
|
+
// emptying anything further must survive.
|
|
500
|
+
const after = detectStub(rel, current);
|
|
501
|
+
if (!after.isStub)
|
|
502
|
+
return;
|
|
503
|
+
const beforeVerdict = detectStub(rel, authorised);
|
|
504
|
+
// A baseline the detector could not judge (over its scan cap, or an exempt
|
|
505
|
+
// extension) reports zero callables, which would make ANY later content with
|
|
506
|
+
// one empty body read as "strictly worse". No comparison, no action.
|
|
507
|
+
if (beforeVerdict.callables === 0)
|
|
508
|
+
return;
|
|
509
|
+
if (emptyCount(after) <= emptyCount(beforeVerdict))
|
|
510
|
+
return;
|
|
511
|
+
if (backupRoot === null || backup(backupRoot, rel, current) === null) {
|
|
512
|
+
failed.push(rel);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
try {
|
|
516
|
+
// Temp-then-rename, the pattern this subsystem already uses elsewhere: an
|
|
517
|
+
// in-place truncating write that dies mid-way leaves a mangled file whose
|
|
518
|
+
// good content existed only in a JS string the crash takes with it.
|
|
519
|
+
const tmp = `${abs}.uap-sweep-tmp`;
|
|
520
|
+
writeFileSync(tmp, authorised, 'utf-8');
|
|
521
|
+
renameSync(tmp, abs);
|
|
522
|
+
reverted.push(rel);
|
|
523
|
+
}
|
|
524
|
+
catch {
|
|
525
|
+
failed.push(rel);
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
return {
|
|
529
|
+
reverted,
|
|
530
|
+
removed,
|
|
531
|
+
uncovered,
|
|
532
|
+
failed,
|
|
533
|
+
note: buildNote({ reverted, removed, uncovered, failed }),
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Filenames reach the model verbatim, and POSIX allows newlines and brackets in
|
|
538
|
+
* them — which would let a crafted name inject harness-shaped lines into a note
|
|
539
|
+
* that flows into the retry prompt, the acceptance judge and the operator log.
|
|
540
|
+
*/
|
|
541
|
+
function safeName(rel) {
|
|
542
|
+
return rel.replace(/[\r\n\][]/g, '_').slice(0, 120);
|
|
543
|
+
}
|
|
544
|
+
function list(paths, max) {
|
|
545
|
+
const shown = paths.slice(0, max).map(safeName).join(', ');
|
|
546
|
+
return paths.length > max ? `${shown}, +${paths.length - max} more` : shown;
|
|
547
|
+
}
|
|
548
|
+
function buildNote(r) {
|
|
549
|
+
const parts = [];
|
|
550
|
+
const touched = [...r.removed, ...r.reverted];
|
|
551
|
+
if (touched.length > 0) {
|
|
552
|
+
const verb = r.removed.length > 0 && r.reverted.length > 0
|
|
553
|
+
? 'removed/reverted'
|
|
554
|
+
: r.removed.length > 0
|
|
555
|
+
? 'removed'
|
|
556
|
+
: 'reverted';
|
|
557
|
+
// The previous content IS preserved, but the location is deliberately not
|
|
558
|
+
// named: it lives under `.uap/`, the one directory read_file and list_dir
|
|
559
|
+
// refuse, and pointing an agent at a path the harness then hides is a
|
|
560
|
+
// harness bug this codebase has already had to fix once.
|
|
561
|
+
parts.push(`[blocked: ${touched.length} file(s) changed outside the write tools were SKELETONS — ` +
|
|
562
|
+
`an API surface with empty function bodies — and have been ${verb}: ${list(touched, 8)}. ` +
|
|
563
|
+
`Writing files through the shell does not bypass this check. Write the REAL ` +
|
|
564
|
+
`implementation with write_file — each function must contain the logic that makes ` +
|
|
565
|
+
`it work. If a file is deliberately a skeleton, give each body an explicit ` +
|
|
566
|
+
`throw new Error('TODO: <what>') instead of an empty block.]`);
|
|
567
|
+
}
|
|
568
|
+
if (r.failed.length > 0) {
|
|
569
|
+
// A guard that could not act must never look like a guard that found nothing.
|
|
570
|
+
parts.push(`[warning: the substance check could not act on ${r.failed.length} file(s) ` +
|
|
571
|
+
`(${list(r.failed, 4)}) — they were left as-is.]`);
|
|
572
|
+
}
|
|
573
|
+
if (r.uncovered.length > 0) {
|
|
574
|
+
// Gated on files that actually CHANGED, not on `truncated`. A capped baseline
|
|
575
|
+
// where nothing moved is complete coverage in every way the model cares
|
|
576
|
+
// about; emitting on the cap alone put a warning on every bash turn of every
|
|
577
|
+
// project with a big lockfile, in a prompt slot that is head-truncated.
|
|
578
|
+
// `truncated` remains on the sweep for callers and tests, as a fact about the
|
|
579
|
+
// baseline rather than a claim about coverage.
|
|
580
|
+
parts.push(`[note: ${r.uncovered.length} changed file(s) were too large to check this turn: ${list(r.uncovered, 4)}.]`);
|
|
581
|
+
}
|
|
582
|
+
return parts.join('\n');
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Put the note FIRST — but never ahead of a protocol marker.
|
|
586
|
+
*
|
|
587
|
+
* The retry prompt includes the previous output through `truncateHead`, which
|
|
588
|
+
* keeps the leading 3000 characters, so a note appended after a long turn summary
|
|
589
|
+
* is exactly the part that gets cut. That argues for prepending.
|
|
590
|
+
*
|
|
591
|
+
* Against it: `decodeBudgetStop` only recognises the context-budget marker within
|
|
592
|
+
* the first 512 characters, and this note routinely exceeds that on its own. A
|
|
593
|
+
* budget-stopped turn that was also swept would therefore stop being recognised
|
|
594
|
+
* as budget-stopped — which silently disables the epic controller's rail-sizing
|
|
595
|
+
* split, on exactly the long shell-using sessions that blow the rail. So when the
|
|
596
|
+
* output carries that marker, the note goes after the marker's own line: the
|
|
597
|
+
* marker keeps position 0, and the note is still near the front.
|
|
598
|
+
*/
|
|
599
|
+
export function prependSweepNote(output, outcome) {
|
|
600
|
+
if (!outcome.note)
|
|
601
|
+
return output;
|
|
602
|
+
if (output.startsWith(CONTEXT_BUDGET_MARKER)) {
|
|
603
|
+
const nl = output.indexOf('\n');
|
|
604
|
+
return nl === -1
|
|
605
|
+
? `${output}\n${outcome.note}`
|
|
606
|
+
: `${output.slice(0, nl)}\n${outcome.note}${output.slice(nl)}`;
|
|
607
|
+
}
|
|
608
|
+
return `${outcome.note}\n${output}`;
|
|
609
|
+
}
|
|
610
|
+
//# sourceMappingURL=bash-sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash-sweep.js","sourceRoot":"","sources":["../../src/delivery/bash-sweep.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AAEH,OAAO,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,aAAa,EACb,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,IAAI,WAAW,GACzB,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,MAAM;IACN,cAAc;IACd,MAAM;IACN,cAAc;IACd,cAAc;IACd,aAAa;IACb,eAAe;IACf,aAAa;IACb,aAAa;IACb,MAAM;IACN,OAAO;IACP,MAAM;IACN,QAAQ;IACR,OAAO;IACP,OAAO;IACP,aAAa;IACb,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,+EAA+E;IAC/E,8EAA8E;IAC9E,4EAA4E;IAC5E,+BAA+B;IAC/B,YAAY;IACZ,QAAQ;CACT,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAW/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IAC/B,YAAY,EAAE,OAAO;CACtB,CAAC;AAEF,mFAAmF;AACnF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAkD5D,+EAA+E;AAC/E,SAAS,YAAY;IACnB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AAC5E,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,SAAS,EAAE,KAAK;QAChB,MAAM,EAAE,cAAc;KACvB,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,MAAM,CAAC,WAAmB,EAAE,GAAW;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACxD,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,QAAQ,CAAC,GAAW,EAAE,QAAgB;IAC7C,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IACZ,IAAI,CAAC;QACH,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QACzB,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,GAAG,QAAQ;YAAE,OAAO,IAAI,CAAC;QACpD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC;YACrD,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM;YAClB,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QACD,0EAA0E;QAC1E,+EAA+E;QAC/E,4EAA4E;QAC5E,sEAAsE;QACtE,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAClE,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpD,8EAA8E;QAC9E,+EAA+E;QAC/E,4EAA4E;QAC5E,wEAAwE;QACxE,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,SAAS,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,qFAAqF;AACrF,SAAS,IAAI,CACX,WAAmB,EACnB,MAAyE;IAEzE,MAAM,KAAK,GAAa,CAAC,WAAW,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAY,CAAC;QAClC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS,CAAC,uDAAuD;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,KAAK,WAAW,CAAC;QACnC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,cAAc,EAAE;gBAAE,SAAS,CAAC,0CAA0C;YAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACpB,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACtC,IAAI,MAAM,IAAI,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,SAAS;gBACnD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;gBAAE,SAAS;YAC1B,IAAI,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;AAEvC;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,OAAgB,EAChB,SAAsB,cAAc;IAEpC,IAAI,CAAC,OAAO,IAAI,iBAAiB,EAAE;QAAE,OAAO,aAAa,EAAE,CAAC;IAC5D,6EAA6E;IAC7E,0EAA0E;IAC1E,8EAA8E;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,8EAA8E;IAC9E,IAAI,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,aAAa,EAAE,CAAC;IAC1D,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC9B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,WAAW;QACX,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,IAAI,GAAG,EAAE;QACrB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,MAAM,EAAE,IAAI,GAAG,EAAE;QACjB,SAAS,EAAE,KAAK;QAChB,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAgB;IACjD,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO;IAC3B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;IACrB,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO;IAC5B,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAClD,6EAA6E;QAC7E,6EAA6E;QAC7E,4EAA4E;QAC5E,uDAAuD;QACvD,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACzC,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY;YAAE,OAAO,CAAC,uCAAuC;QACrF,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YAC9F,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;YACvB,OAAO,CAAC,2DAA2D;QACrE,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACtD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,CAAC,gDAAgD;QAC3E,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,KAAK,IAAI,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,KAAgB,EAAE,GAAW,EAAE,OAAe;IAClF,IAAI,KAAK,CAAC,OAAO;QAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,mFAAmF;AACnF,SAAS,UAAU,CAAC,CAAc;IAChC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACzC,uEAAuE;QACvE,iEAAiE;QACjE,IAAI,CAAC;YACH,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,cAAc,EAAE;gBAAE,OAAO,IAAI,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,wDAAwD;QAC1D,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC3C,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,UAAU,CAAC,UAAkB,EAAE,GAAW;IACjD,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QACjC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAC/C,CAAC;IACD,OAAO,GAAG,IAAI,WAAW,CAAC;AAC5B,CAAC;AAED,iFAAiF;AACjF,SAAS,MAAM,CAAC,UAAkB,EAAE,GAAW,EAAE,OAAe;IAC9D,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC9B,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgB;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,YAAY,EAAE,CAAC;IAC1C,+EAA+E;IAC/E,gFAAgF;IAChF,oBAAoB;IACpB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,IAAI,iBAAiB,EAAE;QAAE,OAAO,YAAY,EAAE,CAAC;IAChF,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAEnB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,8EAA8E;IAC9E,2EAA2E;IAC3E,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAExD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAClD,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,CAAC;QAC/F,6EAA6E;QAC7E,wEAAwE;QACxE,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QACvD,4EAA4E;QAC5E,iDAAiD;QACjD,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAExE,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACrC,2EAA2E;YAC3E,uEAAuE;YACvE,+DAA+D;YAC/D,IAAI,aAAa,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;gBAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACzD,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,CAAC,+CAA+C;QAE7E,IAAI,aAAa,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC9C,qEAAqE;YACrE,wEAAwE;YACxE,kEAAkE;YAClE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,4EAA4E;YAC5E,2EAA2E;YAC3E,4EAA4E;YAC5E,wEAAwE;YACxE,4EAA4E;YAC5E,8DAA8D;YAC9D,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,MAAM;gBAAE,OAAO;YAC7C,yEAAyE;YACzE,wEAAwE;YACxE,0EAA0E;YAC1E,qDAAqD;YACrD,MAAM,IAAI,GAAG,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YACtE,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9B,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChD,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,UAAU,KAAK,OAAO;YAAE,OAAO,CAAC,iCAAiC;QAErE,6EAA6E;QAC7E,sEAAsE;QACtE,0CAA0C;QAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO;QAC1B,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,UAAoB,CAAC,CAAC;QAC5D,2EAA2E;QAC3E,6EAA6E;QAC7E,qEAAqE;QACrE,IAAI,aAAa,CAAC,SAAS,KAAK,CAAC;YAAE,OAAO;QAC1C,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,aAAa,CAAC;YAAE,OAAO;QAC3D,IAAI,UAAU,KAAK,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;YACrE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,0EAA0E;YAC1E,0EAA0E;YAC1E,oEAAoE;YACpE,MAAM,GAAG,GAAG,GAAG,GAAG,gBAAgB,CAAC;YACnC,aAAa,CAAC,GAAG,EAAE,UAAoB,EAAE,OAAO,CAAC,CAAC;YAClD,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ;QACR,OAAO;QACP,SAAS;QACT,MAAM;QACN,IAAI,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,IAAI,CAAC,KAAe,EAAE,GAAW;IACxC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,KAAK,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,CAKlB;IACC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GACR,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAC3C,CAAC,CAAC,kBAAkB;YACpB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBACpB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,UAAU,CAAC;QACnB,0EAA0E;QAC1E,0EAA0E;QAC1E,sEAAsE;QACtE,yDAAyD;QACzD,KAAK,CAAC,IAAI,CACR,aAAa,OAAO,CAAC,MAAM,4DAA4D;YACrF,6DAA6D,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI;YAC1F,6EAA6E;YAC7E,mFAAmF;YACnF,4EAA4E;YAC5E,6DAA6D,CAChE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,8EAA8E;QAC9E,KAAK,CAAC,IAAI,CACR,kDAAkD,CAAC,CAAC,MAAM,CAAC,MAAM,WAAW;YAC1E,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,4BAA4B,CACpD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,8EAA8E;QAC9E,wEAAwE;QACxE,6EAA6E;QAC7E,wEAAwE;QACxE,8EAA8E;QAC9E,+CAA+C;QAC/C,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,uDAAuD,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1H,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,OAAqB;IACpE,IAAI,CAAC,OAAO,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IACjC,IAAI,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,CAAC;QAC7C,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,EAAE,KAAK,CAAC,CAAC;YACd,CAAC,CAAC,GAAG,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE;YAC9B,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;AACtC,CAAC"}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|