opencode-swarm 7.195.0 → 7.197.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/.opencode/skills/brainstorm/SKILL.md +2 -1
- package/.opencode/skills/ci-failure-batching/SKILL.md +2 -1
- package/.opencode/skills/ci-fix-monitor/SKILL.md +2 -1
- package/.opencode/skills/clarify/SKILL.md +2 -1
- package/.opencode/skills/clarify-spec/SKILL.md +2 -1
- package/.opencode/skills/codebase-review-swarm/SKILL.md +1 -1
- package/.opencode/skills/commit-pr/SKILL.md +3 -2
- package/.opencode/skills/consult/SKILL.md +2 -1
- package/.opencode/skills/council/SKILL.md +2 -1
- package/.opencode/skills/critic-gate/SKILL.md +2 -1
- package/.opencode/skills/deep-dive/SKILL.md +2 -1
- package/.opencode/skills/deep-research/SKILL.md +2 -1
- package/.opencode/skills/design-docs/SKILL.md +2 -1
- package/.opencode/skills/discover/SKILL.md +2 -1
- package/.opencode/skills/durable-session-state/SKILL.md +2 -1
- package/.opencode/skills/engineering-conventions/SKILL.md +2 -1
- package/.opencode/skills/execute/SKILL.md +2 -1
- package/.opencode/skills/fork-pr-operations/SKILL.md +2 -1
- package/.opencode/skills/gate-attribution/SKILL.md +2 -1
- package/.opencode/skills/issue-ingest/SKILL.md +2 -1
- package/.opencode/skills/issue-tracer/SKILL.md +1 -1
- package/.opencode/skills/loop/SKILL.md +2 -1
- package/.opencode/skills/merge-queue-readiness/SKILL.md +2 -1
- package/.opencode/skills/orchestrating-subagents/SKILL.md +2 -1
- package/.opencode/skills/parallel-work-check/SKILL.md +17 -16
- package/.opencode/skills/phase-wrap/SKILL.md +2 -1
- package/.opencode/skills/pre-phase-briefing/SKILL.md +2 -1
- package/.opencode/skills/running-tests/SKILL.md +2 -1
- package/.opencode/skills/skill-edit-validation/SKILL.md +2 -1
- package/.opencode/skills/specify/SKILL.md +2 -1
- package/.opencode/skills/swarm/SKILL.md +2 -1
- package/.opencode/skills/swarm-ci-monitor/SKILL.md +3 -2
- package/.opencode/skills/swarm-implement/SKILL.md +2 -1
- package/.opencode/skills/swarm-plan/SKILL.md +2 -1
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +9 -162
- package/.opencode/skills/swarm-pr-feedback/references/gate-evidence-scope.md +20 -0
- package/.opencode/skills/swarm-pr-feedback/references/intake-surfaces.md +107 -0
- package/.opencode/skills/swarm-pr-feedback/references/preflight-checkout.md +67 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +12 -344
- package/.opencode/skills/swarm-pr-review/references/council-mode.md +38 -0
- package/.opencode/skills/swarm-pr-review/references/explorer-output-format.md +54 -0
- package/.opencode/skills/swarm-pr-review/references/findings-persistence-detail.md +15 -0
- package/.opencode/skills/swarm-pr-review/references/parser-candidate-extraction.md +75 -0
- package/.opencode/skills/swarm-pr-review/references/phase0a-intake.md +61 -0
- package/.opencode/skills/swarm-pr-review/references/scope-detection.md +103 -0
- package/.opencode/skills/swarm-pr-review/references/writeback-phases.md +68 -0
- package/.opencode/skills/swarm-pr-subscribe/SKILL.md +3 -2
- package/.opencode/skills/swarm-resume/SKILL.md +2 -1
- package/.opencode/skills/test-file-split/SKILL.md +2 -1
- package/.opencode/skills/worktree-retry-cleanup/SKILL.md +2 -1
- package/.opencode/skills/writing-tests/SKILL.md +7 -437
- package/.opencode/skills/writing-tests/references/cross-platform-patterns.md +237 -0
- package/.opencode/skills/writing-tests/references/mock-tiers.md +207 -0
- package/README.md +1 -1
- package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/cli/{auto-checkpoint-anf21wwa.js → auto-checkpoint-s05sxmg6.js} +4 -4
- package/dist/cli/{checkpoint-ngdw2qx2.js → checkpoint-kzyy9b7y.js} +8 -8
- package/dist/cli/{coder-settlement-bqb059y2.js → coder-settlement-d1qqfgdm.js} +3 -3
- package/dist/cli/{config-doctor-vetg215g.js → config-doctor-yrven0ya.js} +7 -7
- package/dist/cli/{core-8qgvsm6x.js → core-qpmksfae.js} +1 -1
- package/dist/cli/{curator-drift-3gjycbkv.js → curator-drift-2h6nf0mw.js} +5 -5
- package/dist/cli/{curator-llm-factory-d17ybmgm.js → curator-llm-factory-kt3jhgs9.js} +25 -25
- package/dist/cli/{curator-hh0n9wgz.js → curator-mqnqst1g.js} +25 -25
- package/dist/cli/{doctor-knowledge-receipt-phase-id-1d465vkg.js → doctor-knowledge-receipt-phase-id-d8arz38j.js} +4 -4
- package/dist/cli/{evidence-summary-service-rkd3yc5x.js → evidence-summary-service-gjs4zssz.js} +9 -9
- package/dist/cli/{gate-evidence-wtjrerkh.js → gate-evidence-9n5r17hq.js} +2 -2
- package/dist/cli/{guardrail-explain-8xh3r0dn.js → guardrail-explain-g4wcr664.js} +26 -26
- package/dist/cli/{guardrail-log-jrey2myg.js → guardrail-log-0hy23f7d.js} +3 -3
- package/dist/cli/{guardrail-reset-m5qbg30j.js → guardrail-reset-9z5rmp3f.js} +25 -25
- package/dist/cli/{hive-promoter-36yhdfre.js → hive-promoter-w8f840ah.js} +25 -25
- package/dist/cli/{index-gz16dke1.js → index-1cks27mv.js} +6 -6
- package/dist/cli/{index-epdzvp4w.js → index-1gnrtz76.js} +5 -5
- package/dist/cli/{index-jn4mmhqc.js → index-20m9q2z9.js} +1 -1
- package/dist/cli/{index-yryy781f.js → index-29xr45xr.js} +153 -52
- package/dist/cli/{index-bpq6z8qe.js → index-3qqnz0jg.js} +3 -3
- package/dist/cli/{index-kmvy5fr8.js → index-401a12w5.js} +1 -1
- package/dist/cli/{index-jatgbm7k.js → index-5p0jhn2s.js} +1 -1
- package/dist/cli/{index-gns3gc87.js → index-67w61x1b.js} +3 -3
- package/dist/cli/{index-ha8xc5d3.js → index-8ahnfc03.js} +2 -2
- package/dist/cli/{index-akb436kn.js → index-8zwmfh9d.js} +1 -1
- package/dist/cli/{index-3k65kdfp.js → index-9px1knpj.js} +1 -1
- package/dist/cli/{index-1hcjxz6w.js → index-9sqcmzc2.js} +2 -2
- package/dist/cli/{index-9teqkkp4.js → index-agvmmvdt.js} +25 -25
- package/dist/cli/{index-tc8x0zc5.js → index-avbvxmw2.js} +1 -1
- package/dist/cli/{index-c6hyd8hg.js → index-bpnpvhja.js} +1 -1
- package/dist/cli/{index-8448vj9w.js → index-dgvf1jey.js} +1 -1
- package/dist/cli/{index-bftpd2m5.js → index-eabxecjf.js} +2 -2
- package/dist/cli/{index-6vpqe4ws.js → index-fzx1wfxn.js} +1 -1
- package/dist/cli/{index-h7275akd.js → index-g1r94prs.js} +27 -27
- package/dist/cli/{index-82aj6gaj.js → index-g749xs7c.js} +2 -2
- package/dist/cli/{index-7kbpzg05.js → index-jvpvghyh.js} +328 -224
- package/dist/cli/{index-780g1hht.js → index-jvzfw0n5.js} +1 -1
- package/dist/cli/{index-479kf368.js → index-mbdkr2sh.js} +1 -1
- package/dist/cli/{index-c4hx57tz.js → index-ng6me2hh.js} +2 -2
- package/dist/cli/{index-fk4j26km.js → index-njfkqr77.js} +3 -3
- package/dist/cli/{index-peyz4k9k.js → index-t3tzk566.js} +1 -1
- package/dist/cli/{index-z59414gv.js → index-v8jhmn8x.js} +1 -1
- package/dist/cli/{index-5gf2wx2c.js → index-xb3h5tvj.js} +4 -4
- package/dist/cli/{index-xs9cn3c0.js → index-xf6tdsyr.js} +3 -3
- package/dist/cli/{index-863hst4e.js → index-ysbmrmzk.js} +1 -1
- package/dist/cli/index.js +26 -26
- package/dist/cli/{knowledge-escalator-6sgrjbcj.js → knowledge-escalator-42cvn0ec.js} +7 -7
- package/dist/cli/{knowledge-events-hztjt63y.js → knowledge-events-v0xavjkd.js} +5 -5
- package/dist/cli/{knowledge-store-3sd2034v.js → knowledge-store-s01cread.js} +1 -1
- package/dist/cli/{knowledge-validator-3fe82zy4.js → knowledge-validator-kvtcqpke.js} +2 -2
- package/dist/cli/{mcp-spbx3efe.js → mcp-ff73w9z7.js} +1 -1
- package/dist/cli/{model-preflight-k2bw7rt1.js → model-preflight-0k8bd388.js} +25 -25
- package/dist/cli/{pending-delegations-kcvd9t41.js → pending-delegations-bmj7djk1.js} +2 -2
- package/dist/cli/{pr-subscriptions-nqby87en.js → pr-subscriptions-9dbrw7ky.js} +1 -1
- package/dist/cli/{pr-workflow-gate-cgbc0x1z.js → pr-workflow-gate-wg003fkd.js} +25 -25
- package/dist/cli/{scan-cursor-sphr9phs.js → scan-cursor-d93q0q3s.js} +2 -2
- package/dist/cli/{schema-x892aatt.js → schema-0ny9ef6s.js} +1 -1
- package/dist/cli/{scope-persistence-n9xksct2.js → scope-persistence-ekcfq34x.js} +5 -5
- package/dist/cli/{server-am2y11yn.js → server-rpx7pkg1.js} +25 -25
- package/dist/cli/{skill-generator-p71b6h5k.js → skill-generator-h1w7s5dh.js} +8 -8
- package/dist/cli/{snapshot-coordination-init-x9b4t9sk.js → snapshot-coordination-init-f6ecsn9c.js} +25 -25
- package/dist/cli/{speckit-checkoff-xp9vsp9k.js → speckit-checkoff-kf0zkpdw.js} +3 -3
- package/dist/cli/{worktree-collision-ownership-2pmyww6g.js → worktree-collision-ownership-p7zmj4ag.js} +2 -2
- package/dist/cli/{worktree-isolation-379tmkta.js → worktree-isolation-nz90xvw5.js} +25 -25
- package/dist/commands/registry.d.ts +1 -1
- package/dist/config/skill-contract-digest.d.ts +6 -0
- package/dist/epic/start.d.ts +5 -4
- package/dist/hooks/skill-scoring.d.ts +1 -1
- package/dist/hooks/skill-usage-log.d.ts +2 -0
- package/dist/host/v2/agents-commands.d.ts +13 -3
- package/dist/index.js +103 -98
- package/dist/sbom/detectors/index.d.ts +15 -0
- package/dist/services/skill-evaluator.d.ts +2 -0
- package/dist/services/skill-generator.d.ts +13 -0
- package/dist/tools/sbom-generate.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Cross-Platform Test Patterns and Requirements
|
|
2
|
+
|
|
3
|
+
## Cross-Platform Requirements
|
|
4
|
+
|
|
5
|
+
> **See also**: [Cross-Platform Test Patterns](#cross-platform-test-patterns) above for detailed
|
|
6
|
+
> guidance on mock keys, symlink behavior, temp directories, and line endings.
|
|
7
|
+
|
|
8
|
+
All tests must pass on Linux, macOS, and Windows unless explicitly gated with:
|
|
9
|
+
```typescript
|
|
10
|
+
const isWindows = process.platform === 'win32';
|
|
11
|
+
if (isWindows) test.skip('reason', () => {});
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Path handling
|
|
15
|
+
- Use `path.join()` or `path.resolve()`, never string concatenation with `/`.
|
|
16
|
+
- Temp directories: use `os.tmpdir()`, not hardcoded `/tmp`.
|
|
17
|
+
- File comparisons: normalize paths before comparing (`path.resolve(a) === path.resolve(b)`).
|
|
18
|
+
|
|
19
|
+
### Process spawning
|
|
20
|
+
- Use `.cmd` extension on Windows for npm/bun binaries: `process.platform === 'win32' ? 'bun.cmd' : 'bun'`.
|
|
21
|
+
- Use array-form `spawn`/`spawnSync`, never shell string commands.
|
|
22
|
+
|
|
23
|
+
### macOS rename-visibility race (write-then-read atomic files)
|
|
24
|
+
|
|
25
|
+
On macOS/APFS, `fs.renameSync` can complete before the data is visible to
|
|
26
|
+
subsequent reads. Tests that write-then-read atomic files may fail on
|
|
27
|
+
`macos-latest` but pass on `ubuntu-latest` and `windows-latest`.
|
|
28
|
+
|
|
29
|
+
**Symptom:** Test fails only on macOS with `result === null` or
|
|
30
|
+
`result === undefined` immediately after a write that should have made the
|
|
31
|
+
file visible.
|
|
32
|
+
|
|
33
|
+
**Root cause:** macOS filesystem updates the directory entry asynchronously
|
|
34
|
+
after `fs.renameSync`. Immediately-following reads may see ENOENT or stale
|
|
35
|
+
data.
|
|
36
|
+
|
|
37
|
+
**Fix — three layers (use all three for production code):**
|
|
38
|
+
|
|
39
|
+
**Layer 1: Use `bunWrite` for atomic writes.** The `bunWrite` function in
|
|
40
|
+
`src/utils/bun-compat.ts` already handles temp file creation, fsync,
|
|
41
|
+
atomic rename, and parent directory fsync correctly across platforms.
|
|
42
|
+
Do NOT reimplement this pattern.
|
|
43
|
+
|
|
44
|
+
**Layer 2: Add ENOENT retry in the read path.** Wrap `validateSwarmPath` and
|
|
45
|
+
the file read in a try/catch with a bounded retry loop for ENOENT:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// CORRECT — retry on ENOENT only (not other errors), bounded
|
|
49
|
+
const maxAttempts = 5;
|
|
50
|
+
const retryDelayMs = 10;
|
|
51
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
52
|
+
try {
|
|
53
|
+
const resolvedPath = _internals.validateSwarmPath(directory, filename);
|
|
54
|
+
const file = bunFile(resolvedPath);
|
|
55
|
+
const content = await file.text();
|
|
56
|
+
return content;
|
|
57
|
+
} catch (err) {
|
|
58
|
+
const isNotFound = (err as NodeJS.ErrnoException)?.code === 'ENOENT';
|
|
59
|
+
if (!isNotFound || attempt === maxAttempts - 1) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
CRITICAL: `validateSwarmPath` must be INSIDE the try block so that throws
|
|
69
|
+
(for path traversal attempts) are caught and return null. Security tests
|
|
70
|
+
expect `readSwarmFileAsync` to return null for traversal attempts.
|
|
71
|
+
|
|
72
|
+
**Layer 3: Don't add arbitrary delays.** `setTimeout` should be bounded
|
|
73
|
+
(5-10ms, max 5 attempts). Do not add `await new Promise(r => setTimeout(r, 100))`
|
|
74
|
+
"just in case" — that's a code smell. The retry loop handles it.
|
|
75
|
+
|
|
76
|
+
See [`.opencode/skills/engineering-conventions/SKILL.md`](../engineering-conventions/SKILL.md)
|
|
77
|
+
for the evidence file flow that triggers this retry pattern in QA gates.
|
|
78
|
+
|
|
79
|
+
### Node FileHandle API
|
|
80
|
+
|
|
81
|
+
Node's `FileHandle` uses `.sync()`, NOT `.fsync()`:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// CORRECT
|
|
85
|
+
const fd = await fsPromises.open(dir, 'r');
|
|
86
|
+
try {
|
|
87
|
+
await fd.sync();
|
|
88
|
+
} finally {
|
|
89
|
+
await fd.close();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// WRONG — TypeScript error: Property 'fsync' does not exist on type 'FileHandle'
|
|
93
|
+
const fd = await fsPromises.open(dir, 'r');
|
|
94
|
+
try {
|
|
95
|
+
await fd.fsync();
|
|
96
|
+
} finally {
|
|
97
|
+
await fd.close();
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Cross-Platform Test Patterns
|
|
102
|
+
|
|
103
|
+
Tests run on all three CI platforms (ubuntu, macos, windows). Path and filesystem behavior
|
|
104
|
+
differs between them. Follow these patterns to prevent platform-specific failures:
|
|
105
|
+
|
|
106
|
+
### Mock keys with filesystem paths
|
|
107
|
+
|
|
108
|
+
**Never hardcode Unix-format paths as mock keys.** On Windows, `path.resolve('/dir', 'file')`
|
|
109
|
+
produces drive-letter-prefixed paths like `D:\dir\file`, not `/dir/file`. A mock that checks
|
|
110
|
+
for `/dir/file` will silently never match, causing the test to behave differently on Windows.
|
|
111
|
+
|
|
112
|
+
**Use `path.resolve()` to construct mock keys the same way the source code does:**
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
// ❌ WRONG — fails on Windows (mock expects '/safe/dir/linked.ts',
|
|
116
|
+
// but path.resolve('/safe/dir', 'linked.ts') = 'D:\safe\dir\linked.ts')
|
|
117
|
+
mockRealpathSync.mockImplementation((inputPath: string) => {
|
|
118
|
+
if (inputPath === '/safe/dir') return '/safe/dir';
|
|
119
|
+
if (inputPath === '/safe/dir/linked.ts') return '/outside/linked.ts';
|
|
120
|
+
return inputPath;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// ✅ CORRECT — path.resolve produces matching keys on all platforms
|
|
124
|
+
const mockDir = path.resolve('/safe/dir');
|
|
125
|
+
const linkedResolved = path.resolve(mockDir, 'linked.ts');
|
|
126
|
+
const outsideResolved = path.resolve('/outside/linked.ts');
|
|
127
|
+
|
|
128
|
+
// mockRealpathSync is a mock() function (bun:test) — see mocking patterns above
|
|
129
|
+
mockRealpathSync.mockImplementation((inputPath: string) => {
|
|
130
|
+
if (inputPath === mockDir) return mockDir;
|
|
131
|
+
if (inputPath === linkedResolved) return outsideResolved;
|
|
132
|
+
return inputPath;
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Symlink behavior differences
|
|
137
|
+
|
|
138
|
+
- On Windows, `fs.symlinkSync` for directories creates **junctions** by default, which
|
|
139
|
+
resolve differently than POSIX symlinks. Junction creation may require administrator
|
|
140
|
+
elevation on older Node.js versions.
|
|
141
|
+
- `fs.realpathSync` on a broken symlink throws `ENOENT` on POSIX but may throw
|
|
142
|
+
`EINVAL` on Windows, depending on symlink type.
|
|
143
|
+
- Use `test.skipIf(process.platform === 'win32')` for tests that directly manipulate
|
|
144
|
+
filesystem symlinks, unless the test's purpose is explicitly to verify cross-platform
|
|
145
|
+
symlink behavior.
|
|
146
|
+
|
|
147
|
+
### Temporary directory patterns
|
|
148
|
+
|
|
149
|
+
- Use `os.tmpdir()` + `path.join()` for temp paths. **Never** hardcode `/tmp` or `C:\`.
|
|
150
|
+
- Wrap `mkdtempSync` in `realpathSync` if the result is `chdir`'d on macOS (temp
|
|
151
|
+
dirs are often symlinked to `/private/var/...`).
|
|
152
|
+
- Clean up temp dirs in `afterEach` or `afterAll` with a bounded helper that
|
|
153
|
+
verifies the resolved cleanup target is a child of `os.tmpdir()` before
|
|
154
|
+
calling recursive `rm`. Reuse `tests/helpers/safe-test-dir.ts` when possible.
|
|
155
|
+
Do not call recursive `rm` on a computed path unless the helper has rejected
|
|
156
|
+
empty strings, `os.tmpdir()` itself, and paths outside the temp root.
|
|
157
|
+
|
|
158
|
+
### Platform-specific environment variable redirection
|
|
159
|
+
|
|
160
|
+
When tests redirect `process.env.HOME` to isolate path-resolver-dependent code
|
|
161
|
+
(functions like `resolveHiveKnowledgePath`, `resolveSwarmKnowledgePath`, or any
|
|
162
|
+
function that reads `os.homedir()` / platform env vars), they MUST redirect ALL
|
|
163
|
+
platform-specific env vars, not just `HOME`. A partial redirect silently falls
|
|
164
|
+
back to the real user profile on some platforms, causing tests to read/write
|
|
165
|
+
actual user data instead of the isolated temp directory.
|
|
166
|
+
|
|
167
|
+
Per-platform requirements:
|
|
168
|
+
|
|
169
|
+
- **Linux**: redirect `HOME`, `XDG_CONFIG_HOME`, and `XDG_DATA_HOME`.
|
|
170
|
+
- **macOS**: redirect `HOME` (macOS resolves `~/Library/Application Support` from
|
|
171
|
+
the home directory).
|
|
172
|
+
- **Windows**: redirect `HOME`, `LOCALAPPDATA`, AND `APPDATA`. Windows path
|
|
173
|
+
resolvers read `LOCALAPPDATA` and `APPDATA`, neither of which is derived from
|
|
174
|
+
`HOME`. Redirecting only `HOME` silently fails on Windows, causing tests to
|
|
175
|
+
touch the real `%LOCALAPPDATA%` and `%APPDATA%` trees.
|
|
176
|
+
|
|
177
|
+
> **⚠️ Bun caches `os.homedir()` on first call.** If a module calls `os.homedir()`
|
|
178
|
+
> before the test sets `process.env.HOME`, the cached value persists for the
|
|
179
|
+
> lifetime of the process and later env changes are silently ignored. Set
|
|
180
|
+
> `process.env.HOME` (and other redirected vars) **before** importing any module
|
|
181
|
+
> that calls `os.homedir()`. The source code documents this at
|
|
182
|
+
> `src/hooks/knowledge-store.ts`: "Bun caches os.homedir(), so changing $HOME
|
|
183
|
+
> after first call is ignored."
|
|
184
|
+
|
|
185
|
+
Use per-variable save/restore rather than saving and replacing the entire
|
|
186
|
+
`process.env` object — the latter discards process-level env state and can
|
|
187
|
+
interfere with other test infrastructure:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { beforeEach, afterEach } from 'bun:test';
|
|
191
|
+
import os from 'node:os';
|
|
192
|
+
import path from 'node:path';
|
|
193
|
+
|
|
194
|
+
const saved = {
|
|
195
|
+
HOME: process.env.HOME,
|
|
196
|
+
LOCALAPPDATA: process.env.LOCALAPPDATA,
|
|
197
|
+
APPDATA: process.env.APPDATA,
|
|
198
|
+
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
|
|
199
|
+
XDG_DATA_HOME: process.env.XDG_DATA_HOME,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
const isolatedDir = path.join(os.tmpdir(), 'test-home');
|
|
204
|
+
process.env.HOME = isolatedDir;
|
|
205
|
+
process.env.LOCALAPPDATA = isolatedDir;
|
|
206
|
+
process.env.APPDATA = isolatedDir;
|
|
207
|
+
process.env.XDG_CONFIG_HOME = isolatedDir;
|
|
208
|
+
process.env.XDG_DATA_HOME = isolatedDir;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
afterEach(() => {
|
|
212
|
+
for (const [key, value] of Object.entries(saved)) {
|
|
213
|
+
if (value === undefined) delete process.env[key];
|
|
214
|
+
else process.env[key] = value;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
For cross-file isolation (tests that must survive across multiple files in the
|
|
220
|
+
same process, e.g. batch steps), use `beforeAll` / `afterAll` with the same
|
|
221
|
+
per-var save/restore pattern. Never mutate `process.env` without restoring it in
|
|
222
|
+
a matching teardown hook.
|
|
223
|
+
|
|
224
|
+
**Preferred approach:** Use `createIsolatedTestEnv()` from
|
|
225
|
+
`tests/helpers/isolated-test-env.ts`. It handles `XDG_CONFIG_HOME`, `APPDATA`,
|
|
226
|
+
`LOCALAPPDATA`, and `HOME` with correct per-variable save/restore and returns a
|
|
227
|
+
cleanup function that removes the temp directory. Use this helper unless your
|
|
228
|
+
test has specific requirements it doesn't cover.
|
|
229
|
+
|
|
230
|
+
### Line ending normalization
|
|
231
|
+
|
|
232
|
+
Git on Windows converts LF to CRLF by default. Tests that compare file contents
|
|
233
|
+
byte-by-byte against expected strings must normalize line endings:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
const actual = readFileSync(path, 'utf-8').replace(/\r\n/g, '\n');
|
|
237
|
+
```
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Two-Tier Mock Convention and mock.module() Export Completeness
|
|
2
|
+
|
|
3
|
+
## mock.module() Export Completeness
|
|
4
|
+
|
|
5
|
+
When using `mock.module()` (or `vi.mock()`) with Bun's test runner, the mock factory **MUST provide stubs for ALL named exports** of the target module — not just the ones your test calls. Bun validates the export set at dynamic-import time and throws `SyntaxError: Export named 'X' not found` if any export is missing.
|
|
6
|
+
|
|
7
|
+
### Why this matters
|
|
8
|
+
|
|
9
|
+
Transitive imports may reference exports your test never calls directly. For example, if your test mocks `config/schema.js` and only uses `stripKnownSwarmPrefix`, but a transitive dependency imports `PluginConfigSchema` from the same module, the mock MUST include `PluginConfigSchema` as a stub — even though your test never calls it.
|
|
10
|
+
|
|
11
|
+
When the source module gains new exports (e.g., a PR adds 50 new Zod schemas to `config/schema.ts`), ALL existing `mock.module()` calls targeting that module must be updated — even if the new exports are irrelevant to your test.
|
|
12
|
+
|
|
13
|
+
### How to verify completeness
|
|
14
|
+
|
|
15
|
+
Before finalizing a test that uses `mock.module()`:
|
|
16
|
+
|
|
17
|
+
1. List all runtime exports of the target module (type-only exports are erased at compile time and need no stub):
|
|
18
|
+
```bash
|
|
19
|
+
grep -E "^export (const|function|async function|class) " src/path/to/module.ts
|
|
20
|
+
```
|
|
21
|
+
**Note:** Do NOT include `type` or `interface` exports — Bun erases these at compile time and they need no runtime stub.
|
|
22
|
+
2. Ensure every export name has an entry in your `mock.module()` factory.
|
|
23
|
+
3. Stubs can be minimal:
|
|
24
|
+
- Functions: `() => null` or `async () => {}`
|
|
25
|
+
- Zod schemas: use a comprehensive stub that supports common methods:
|
|
26
|
+
```typescript
|
|
27
|
+
const zodStub = {
|
|
28
|
+
parse: (v: unknown) => v,
|
|
29
|
+
safeParse: (v: unknown) => ({ success: true as const, data: v }),
|
|
30
|
+
parseAsync: async (v: unknown) => v,
|
|
31
|
+
};
|
|
32
|
+
```
|
|
33
|
+
- Constants: appropriate zero values (`''`, `0`, `null`, `[]`, `{}`)
|
|
34
|
+
|
|
35
|
+
### Verification pattern
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// ✅ CORRECT — all exports provided, test uses only the first one
|
|
39
|
+
mock.module('../../../src/config/schema.js', () => ({
|
|
40
|
+
// The one export your test actually uses
|
|
41
|
+
stripKnownSwarmPrefix: mockStripFn,
|
|
42
|
+
// Stubs for transitive import resolution (never called in test)
|
|
43
|
+
PluginConfigSchema: zodStub,
|
|
44
|
+
ScoringConfigSchema: zodStub,
|
|
45
|
+
isKnownCanonicalRole: () => false,
|
|
46
|
+
// ... all other runtime exports as stubs
|
|
47
|
+
}));
|
|
48
|
+
|
|
49
|
+
// ❌ WRONG — missing exports cause SyntaxError at module-load time
|
|
50
|
+
mock.module('../../../src/config/schema.js', () => ({
|
|
51
|
+
stripKnownSwarmPrefix: mockStripFn,
|
|
52
|
+
// Missing: PluginConfigSchema, ScoringConfigSchema, etc.
|
|
53
|
+
// → "SyntaxError: Export named 'PluginConfigSchema' not found"
|
|
54
|
+
}));
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### What IS and IS NOT test theater
|
|
58
|
+
|
|
59
|
+
Adding stubs for ESM resolution is NOT test theater — it's a Bun runtime requirement. The distinction:
|
|
60
|
+
|
|
61
|
+
| Pattern | Test theater? | Why |
|
|
62
|
+
|---------|--------------|-----|
|
|
63
|
+
| Adding `PluginConfigSchema: zodStub` so the module loads | **No** | Required for ESM resolution; stub is never called |
|
|
64
|
+
| Stubbing `validateDirectory` to return `true` then asserting "validation works" | **Yes** | The stub bypasses the logic you should be testing |
|
|
65
|
+
| Using `zodStub` in assertions: `expect(zodStub.parse(input)).toBe(input)` | **Yes** | Testing the stub, not the real code |
|
|
66
|
+
| Adding stubs for ALL 50 Zod schemas in config/schema.ts | **No** | All are required for transitive import resolution |
|
|
67
|
+
|
|
68
|
+
The stubs exist solely to satisfy the module loader. Test assertions must verify behavior through the real-mocked functions (the ones your test actually calls), not through the stubs.
|
|
69
|
+
|
|
70
|
+
### Files Intentionally Using File-Scoped Mocks
|
|
71
|
+
|
|
72
|
+
Some test files use top-level `mock.module` that must persist across all tests in the file. These files use `mockReset()`/`mockClear()` in `beforeEach` instead of `mock.restore()` in `afterEach`:
|
|
73
|
+
|
|
74
|
+
- `src/__tests__/preflight-phase.test.ts` — mocks `plan/manager` and `preflight-service`
|
|
75
|
+
|
|
76
|
+
## Two-Tier Mock Convention
|
|
77
|
+
|
|
78
|
+
The codebase uses a two-tier strategy for mock isolation, plus a zero-mock testing pattern:
|
|
79
|
+
|
|
80
|
+
### Tier 0: _test_exports Pure Function Testing (Zero Mocks)
|
|
81
|
+
|
|
82
|
+
When a module contains internal utility functions (formatters, normalizers, transformers) that don't need external dependencies, export them via a `_test_exports` object for direct unit testing. This avoids `mock.module` entirely and produces tests that are deterministic, fast, and immune to Bun's cross-file mock leakage:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// In source file (src/tools/formatter.ts)
|
|
86
|
+
function formatEntry(entry: SomeType): string {
|
|
87
|
+
// internal implementation — may use optional chaining, defaults, etc.
|
|
88
|
+
return entry.score?.toFixed(2) ?? 'N/A';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Public API (tool handler, command handler, etc.)
|
|
92
|
+
export function handleQuery(ctx: Context) {
|
|
93
|
+
const entries = readData(ctx);
|
|
94
|
+
return entries.map(formatEntry);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Export seam for testing — only used by test files
|
|
98
|
+
export const _test_exports = { formatEntry };
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// In test file (tests/unit/tools/formatter.test.ts)
|
|
103
|
+
import { _test_exports } from '../../../src/tools/formatter';
|
|
104
|
+
|
|
105
|
+
const { formatEntry } = _test_exports;
|
|
106
|
+
|
|
107
|
+
describe('formatEntry', () => {
|
|
108
|
+
test('handles missing score', () => {
|
|
109
|
+
expect(formatEntry({ score: undefined })).toBe('N/A');
|
|
110
|
+
});
|
|
111
|
+
test('formats numeric score', () => {
|
|
112
|
+
expect(formatEntry({ score: 0.85 })).toBe('0.85');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**When to use Tier 0 vs Tier 1:**
|
|
118
|
+
- **Tier 0 (`_test_exports`)**: The function is a pure utility (formatter, normalizer, transformer) that doesn't call external modules. No mocking needed — test it directly.
|
|
119
|
+
- **Tier 1 (`_internals`)**: You need to mock a function within the same module to test the caller in isolation. The function has side effects or calls external APIs.
|
|
120
|
+
- **Tier 2 (`mock.module`)**: You need to mock a dependency from another module (Node built-ins, other application modules).
|
|
121
|
+
|
|
122
|
+
**Benefits of Tier 0:**
|
|
123
|
+
- Zero mock pollution — no `mock.module` calls, no `mock.restore()` needed
|
|
124
|
+
- Works in batch test runs without per-file isolation
|
|
125
|
+
- Type-safe (the exported object carries the real TypeScript types)
|
|
126
|
+
- No filesystem dependencies (no tmpDir, no chdir, no existsSync)
|
|
127
|
+
- Deterministic on all platforms and CI environments
|
|
128
|
+
|
|
129
|
+
### Tier 1: _internals DI Seams (Within-Module)
|
|
130
|
+
|
|
131
|
+
For mocking functions within the same module, source files export an `_internals` object that wraps key functions. Tests can replace individual functions without using `mock.module`:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// In source file (src/services/my-service.ts)
|
|
135
|
+
export const _internals = {
|
|
136
|
+
helperFn: () => { /* real implementation */ }
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export function mainFn() {
|
|
140
|
+
return _internals.helperFn();
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// In test file
|
|
146
|
+
import { _internals, mainFn } from '../../../src/services/my-service';
|
|
147
|
+
|
|
148
|
+
test('mainFn uses mocked helper', () => {
|
|
149
|
+
const original = _internals.helperFn;
|
|
150
|
+
_internals.helperFn = mock(() => 'mocked');
|
|
151
|
+
// ... test ...
|
|
152
|
+
_internals.helperFn = original; // restore
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Benefits:**
|
|
157
|
+
- No process-global mock pollution
|
|
158
|
+
- Type-safe
|
|
159
|
+
- Fast (no module re-parsing)
|
|
160
|
+
- Works in batch test runs without isolation
|
|
161
|
+
|
|
162
|
+
**Critical limitation — reference-captured functions:** `_internals` interception requires the source code to read `_internals.fn` at the call site. When a function is instead passed as a direct argument or captured in a closure at module definition time, replacing `_internals.fn` has no effect — the mock is silently ignored and the real function runs.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// Source: readKnowledge is captured at definition time, NOT via _internals
|
|
166
|
+
export async function transactKnowledge(filePath: string, mutate: Fn) {
|
|
167
|
+
return transactFile(filePath, readKnowledge, ...); // direct ref, captured at definition time
|
|
168
|
+
}
|
|
169
|
+
export const _internals = { readKnowledge }; // mutating this does NOT affect the closure above
|
|
170
|
+
|
|
171
|
+
// Test — mock is silently ignored; real readKnowledge still runs
|
|
172
|
+
const orig = _internals.readKnowledge;
|
|
173
|
+
_internals.readKnowledge = mock(() => []); // only mutates the object property
|
|
174
|
+
await transactKnowledge(path, mutate); // still calls the real readKnowledge
|
|
175
|
+
_internals.readKnowledge = orig;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
When `_internals` interception cannot work, verify **observable outcomes** instead: run concurrent callers and assert on final persisted state. See `tests/unit/hooks/knowledge-application.test.ts` ("two concurrent bumpCountersBatch calls") for the pattern.
|
|
179
|
+
|
|
180
|
+
### Tier 2: mock.module (Cross-Module)
|
|
181
|
+
|
|
182
|
+
When mocking dependencies from other modules (especially Node built-ins), use `mock.module` with proper cleanup:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import * as realFs from 'node:fs/promises';
|
|
186
|
+
|
|
187
|
+
mock.module('node:fs/promises', () => ({
|
|
188
|
+
...realFs, // MUST spread real exports
|
|
189
|
+
readFile: mock(() => Promise.resolve('mocked')),
|
|
190
|
+
}));
|
|
191
|
+
|
|
192
|
+
afterEach(() => mock.restore());
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Critical rules for cross-module mocks:**
|
|
196
|
+
1. **Always spread real exports** for Node built-ins — other code depends on exports you don't mock
|
|
197
|
+
2. **Always add `afterEach(mock.restore())`** — provides best-effort cleanup
|
|
198
|
+
3. **Run in per-file isolation** — CI runs each file in its own process (`for f in *.test.ts; do bun --smol test "$f"; done`)
|
|
199
|
+
|
|
200
|
+
### Choosing Between Tiers
|
|
201
|
+
|
|
202
|
+
| Scenario | Pattern | Example |
|
|
203
|
+
|----------|---------|--------|
|
|
204
|
+
| Mocking a function in the same module you're testing | `_internals` seam | `src/state.ts` `_internals.loadSnapshot` |
|
|
205
|
+
| Mocking a Node built-in (fs, child_process, etc.) | `mock.module` + spread real | `mock.module('node:fs/promises', () => ({ ...realFs, readFile: mockFn }))` |
|
|
206
|
+
| Mocking another application module | `mock.module` + cleanup | `mock.module('../../../src/utils/logger', ...)` + `afterEach(mock.restore())` |
|
|
207
|
+
| File-scoped mock (applies to all tests in file) | `mock.module` at top level + `mockReset()` in `beforeEach` | Preflight tests with `mockLoadPlan.mockReset()` |
|
package/README.md
CHANGED
|
@@ -151,7 +151,7 @@ Swarm has two independent mode systems:
|
|
|
151
151
|
|
|
152
152
|
Full-Auto reduces approval friction by deterministically allowing safe operations (read-only tools, in-scope writes, safe shell) and routing every ambiguous or high-risk action (writes to plugin/build/guardrail paths, network, dependency changes, plan/phase mutations, subagent delegation) through the read-only `critic_oversight` agent before it executes. Denials are returned to the agent as structured signals so it can choose a safer path; repeated denials pause the run; phase completion requires an APPROVED oversight record. See [docs/modes.md](docs/modes.md#full-auto) for `mode`, `permission_policy`, `denials`, and `oversight` config keys, fail-closed semantics, and recovery from a paused run.
|
|
153
153
|
|
|
154
|
-
Epic binds to the current plan and runs fully on
|
|
154
|
+
Epic binds to the current plan and runs fully on OpenCode 1.x and OpenCode 2 (7.x plugin). On OpenCode 2 the v2 adapter ships a session-capable client, places coder worktree sessions with an eager parentless create (#3169 Phase 3), and — since #3169 Phase 4 — dispatches human-typed `/swarm` commands natively, so the full flow (`/swarm epic start` → waves → phase review → close) is available there; the remaining live-host verification legs and the dual-host CI lane are tracked on #3169 and #2910. The epic itself is always opened by the user (`human-only` policy — the agent cannot start one on any host). `/swarm epic start` also refuses plans too small to benefit and suggests Balanced. The `epic_next_wave` tool then dispatches each phase as waves of tasks whose declared scopes don't conflict; in a git project each coder works in an isolated worktree on an epic branch, and `/swarm epic close` squash-lands the work as staged changes for you to review. Every task in a wave still runs the full per-task QA pipeline (Stage A and Stage B). Epic learns which files tasks tend to write together and uses it to plan later waves and epics. See [docs/modes.md](docs/modes.md#epic-mode-preview); maintainers start with [src/epic/README.md](src/epic/README.md).
|
|
155
155
|
|
|
156
156
|
**Project mode** — persistent via `execution_mode` config key:
|
|
157
157
|
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import"./index-
|
|
2
|
+
import"./index-g749xs7c.js";
|
|
3
3
|
import"./index-g22dps7x.js";
|
|
4
4
|
import"./index-0725jpp7.js";
|
|
5
5
|
import {
|
|
@@ -15,12 +15,12 @@ import"./index-yf2z4j7s.js";
|
|
|
15
15
|
import"./index-gx2vp8gx.js";
|
|
16
16
|
import {
|
|
17
17
|
loadPluginConfigWithMeta
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-bpnpvhja.js";
|
|
19
19
|
import {
|
|
20
20
|
init_git_executable,
|
|
21
21
|
resolveGitExecutable
|
|
22
22
|
} from "./index-zxdawwc7.js";
|
|
23
|
-
import"./index-
|
|
23
|
+
import"./index-20m9q2z9.js";
|
|
24
24
|
import"./index-hqrkr9ag.js";
|
|
25
25
|
import"./index-bk5tah7q.js";
|
|
26
26
|
import"./index-gknz3bv1.js";
|
|
@@ -152,7 +152,7 @@ async function maybeSaveAutoCheckpoint(directory, plan) {
|
|
|
152
152
|
generation += 1;
|
|
153
153
|
label = buildAutoCheckpointLabel(plan, completedCount, generation);
|
|
154
154
|
}
|
|
155
|
-
const { saveCheckpointRecord } = await import("./checkpoint-
|
|
155
|
+
const { saveCheckpointRecord } = await import("./checkpoint-kzyy9b7y.js");
|
|
156
156
|
const result = await saveCheckpointRecord(label, directory);
|
|
157
157
|
if (result.success) {
|
|
158
158
|
emitAutoSavedEvent(directory, {
|
|
@@ -3,21 +3,21 @@ import {
|
|
|
3
3
|
_internals,
|
|
4
4
|
checkpoint,
|
|
5
5
|
saveCheckpointRecord
|
|
6
|
-
} from "./index-
|
|
7
|
-
import"./index-
|
|
6
|
+
} from "./index-xf6tdsyr.js";
|
|
7
|
+
import"./index-1gnrtz76.js";
|
|
8
8
|
import"./index-6b295cas.js";
|
|
9
9
|
import"./index-9nyqt3kb.js";
|
|
10
|
-
import"./index-
|
|
10
|
+
import"./index-t3tzk566.js";
|
|
11
11
|
import"./index-v3bmwmqw.js";
|
|
12
|
-
import"./index-
|
|
12
|
+
import"./index-v8jhmn8x.js";
|
|
13
13
|
import"./index-g4fs6z4e.js";
|
|
14
14
|
import"./index-m9zzj4ee.js";
|
|
15
15
|
import"./index-kphy4we7.js";
|
|
16
16
|
import"./index-2s7dvzff.js";
|
|
17
|
-
import"./index-
|
|
17
|
+
import"./index-g749xs7c.js";
|
|
18
18
|
import"./index-g22dps7x.js";
|
|
19
19
|
import"./index-0725jpp7.js";
|
|
20
|
-
import"./index-
|
|
20
|
+
import"./index-9sqcmzc2.js";
|
|
21
21
|
import"./index-6183at3v.js";
|
|
22
22
|
import"./index-crz772sx.js";
|
|
23
23
|
import"./index-app2rmxv.js";
|
|
@@ -33,9 +33,9 @@ import"./index-ejhxgyvm.js";
|
|
|
33
33
|
import"./index-7g4c7s5r.js";
|
|
34
34
|
import"./index-yf2z4j7s.js";
|
|
35
35
|
import"./index-gx2vp8gx.js";
|
|
36
|
-
import"./index-
|
|
36
|
+
import"./index-bpnpvhja.js";
|
|
37
37
|
import"./index-zxdawwc7.js";
|
|
38
|
-
import"./index-
|
|
38
|
+
import"./index-20m9q2z9.js";
|
|
39
39
|
import"./index-hqrkr9ag.js";
|
|
40
40
|
import"./index-bk5tah7q.js";
|
|
41
41
|
import"./index-gknz3bv1.js";
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
releaseCoderDispatchOwnership,
|
|
15
15
|
settleCoderDispatch,
|
|
16
16
|
transferCoderSettlementToBackground
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-njfkqr77.js";
|
|
18
18
|
import"./index-ghckhk16.js";
|
|
19
19
|
import"./index-dfrcc46h.js";
|
|
20
|
-
import"./index-
|
|
21
|
-
import"./index-
|
|
20
|
+
import"./index-401a12w5.js";
|
|
21
|
+
import"./index-mbdkr2sh.js";
|
|
22
22
|
import"./index-g4fs6z4e.js";
|
|
23
23
|
import"./index-kphy4we7.js";
|
|
24
24
|
import"./index-2s7dvzff.js";
|
|
@@ -21,17 +21,17 @@ import {
|
|
|
21
21
|
shouldRunOnStartup,
|
|
22
22
|
writeBackupArtifact,
|
|
23
23
|
writeDoctorArtifact
|
|
24
|
-
} from "./index-
|
|
25
|
-
import"./index-
|
|
24
|
+
} from "./index-67w61x1b.js";
|
|
25
|
+
import"./index-1gnrtz76.js";
|
|
26
26
|
import"./index-6b295cas.js";
|
|
27
|
-
import"./index-
|
|
27
|
+
import"./index-t3tzk566.js";
|
|
28
28
|
import"./index-v3bmwmqw.js";
|
|
29
|
-
import"./index-
|
|
29
|
+
import"./index-v8jhmn8x.js";
|
|
30
30
|
import"./index-m9zzj4ee.js";
|
|
31
31
|
import"./index-kphy4we7.js";
|
|
32
32
|
import"./index-2s7dvzff.js";
|
|
33
33
|
import"./index-0725jpp7.js";
|
|
34
|
-
import"./index-
|
|
34
|
+
import"./index-9sqcmzc2.js";
|
|
35
35
|
import"./index-6183at3v.js";
|
|
36
36
|
import"./index-crz772sx.js";
|
|
37
37
|
import"./index-app2rmxv.js";
|
|
@@ -47,9 +47,9 @@ import"./index-ejhxgyvm.js";
|
|
|
47
47
|
import"./index-7g4c7s5r.js";
|
|
48
48
|
import"./index-yf2z4j7s.js";
|
|
49
49
|
import"./index-gx2vp8gx.js";
|
|
50
|
-
import"./index-
|
|
50
|
+
import"./index-bpnpvhja.js";
|
|
51
51
|
import"./index-zxdawwc7.js";
|
|
52
|
-
import"./index-
|
|
52
|
+
import"./index-20m9q2z9.js";
|
|
53
53
|
import"./index-hqrkr9ag.js";
|
|
54
54
|
import"./index-bk5tah7q.js";
|
|
55
55
|
import"./index-gknz3bv1.js";
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
readPriorDriftReports,
|
|
6
6
|
runDeterministicDriftCheck,
|
|
7
7
|
writeDriftReport
|
|
8
|
-
} from "./index-
|
|
9
|
-
import"./index-
|
|
10
|
-
import"./index-
|
|
8
|
+
} from "./index-ysbmrmzk.js";
|
|
9
|
+
import"./index-t3tzk566.js";
|
|
10
|
+
import"./index-v8jhmn8x.js";
|
|
11
11
|
import"./index-kphy4we7.js";
|
|
12
12
|
import"./index-2s7dvzff.js";
|
|
13
13
|
import"./index-0725jpp7.js";
|
|
@@ -18,9 +18,9 @@ import"./index-fzpt2djt.js";
|
|
|
18
18
|
import"./index-ejhxgyvm.js";
|
|
19
19
|
import"./index-7g4c7s5r.js";
|
|
20
20
|
import"./index-yf2z4j7s.js";
|
|
21
|
-
import"./index-
|
|
21
|
+
import"./index-bpnpvhja.js";
|
|
22
22
|
import"./index-zxdawwc7.js";
|
|
23
|
-
import"./index-
|
|
23
|
+
import"./index-20m9q2z9.js";
|
|
24
24
|
import"./index-hqrkr9ag.js";
|
|
25
25
|
import"./index-bk5tah7q.js";
|
|
26
26
|
import"./index-gknz3bv1.js";
|