opencode-swarm 7.144.4 → 7.144.5
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/swarm-pr-review/references/prompt-templates.md +2 -2
- package/dist/background/workspace-snapshot.d.ts +7 -0
- package/dist/cli/{capability-probe-f1paszww.js → capability-probe-976tt4ba.js} +6 -2
- package/dist/cli/{config-doctor-rw9zrjk6.js → config-doctor-m005xfdt.js} +2 -2
- package/dist/cli/{core-zjx9aqaf.js → core-6vdtfb8s.js} +4 -3
- package/dist/cli/{curation-policy-0wbrh11c.js → curation-policy-a511r0qz.js} +4 -4
- package/dist/cli/{curator-g54a7wv0.js → curator-0t87anp5.js} +33 -32
- package/dist/cli/{curator-drift-2jbjv03a.js → curator-drift-ckjm272w.js} +2 -2
- package/dist/cli/curator-llm-factory-j8tk9rxm.js +63 -0
- package/dist/cli/{dispatch-1y1rnv1h.js → dispatch-ndxbsk98.js} +2 -2
- package/dist/cli/{evidence-summary-service-fnr5y54e.js → evidence-summary-service-c22gahjc.js} +13 -12
- package/dist/cli/{gate-evidence-2xt1x07r.js → gate-evidence-hh8kc9wt.js} +7 -6
- package/dist/cli/guardrail-explain-9gjw2dsd.js +64 -0
- package/dist/cli/{guardrail-log-5w4b9zrw.js → guardrail-log-ejf5zjac.js} +4 -4
- package/dist/cli/{hive-promoter-x63ehffd.js → hive-promoter-gkbfpdtv.js} +33 -32
- package/dist/cli/{index-psvxq93b.js → index-1pxqkvvq.js} +2 -2
- package/dist/cli/{index-q67jb94n.js → index-3qdzpv91.js} +1 -1
- package/dist/cli/{index-9qq7c18c.js → index-58cvm3dw.js} +36 -1
- package/dist/cli/{index-p7cm3gtj.js → index-5wenr2vs.js} +35 -34
- package/dist/cli/{index-nckg4gxb.js → index-63tgh0cn.js} +15 -4
- package/dist/cli/{index-03pv47h2.js → index-641yjpk8.js} +6 -6
- package/dist/cli/{index-1csyxv0f.js → index-6z5jtf7d.js} +2 -2
- package/dist/cli/{index-z6v7kwpa.js → index-7e4q41nb.js} +1 -1
- package/dist/cli/{index-8j0va7jp.js → index-855hseq4.js} +43 -22
- package/dist/cli/index-9e6fdz2h.js +282 -0
- package/dist/cli/{index-mazgg5s2.js → index-9s8drsf9.js} +1 -1
- package/dist/cli/{index-cz25e8xp.js → index-a1hxejxc.js} +166 -34
- package/dist/cli/{index-b6e016tv.js → index-abtrcs16.js} +1 -1
- package/dist/cli/{index-8fwhhayc.js → index-b44qqqt2.js} +27 -18
- package/dist/cli/{index-k3cxyk66.js → index-cwtpqm5f.js} +1 -1
- package/dist/cli/{index-h98t1m88.js → index-dc04v786.js} +29 -1
- package/dist/cli/{index-d12jd5mn.js → index-dtbzyr3s.js} +1 -1
- package/dist/cli/{index-x6tp0hfr.js → index-ea09xax6.js} +5 -5
- package/dist/cli/{index-74hpm6sh.js → index-f36ybbsv.js} +12 -6
- package/dist/cli/{index-rn0eq85g.js → index-fv0s19g9.js} +1 -1
- package/dist/cli/{index-btmsqv7p.js → index-fv2pzwnp.js} +5 -4
- package/dist/cli/{index-ywn7vtxp.js → index-h1p08s3n.js} +1 -1
- package/dist/cli/{index-bt9aa01f.js → index-hkdgkkhb.js} +1 -1
- package/dist/cli/{index-y8j8ehc8.js → index-kdak6s63.js} +11 -5
- package/dist/cli/{index-az8etqpp.js → index-kh0jt9pg.js} +298 -1179
- package/dist/cli/{index-pw83zgny.js → index-mkmcz6x8.js} +3 -3
- package/dist/cli/{index-jabkn643.js → index-n4hwcsbd.js} +2 -2
- package/dist/cli/{index-2m7mavaz.js → index-rdgtfj74.js} +2 -2
- package/dist/cli/{index-yts89pqg.js → index-rnyt30tm.js} +4 -4
- package/dist/cli/{index-dty5qgk2.js → index-vdha477y.js} +1 -1
- package/dist/cli/{index-4w5qdbk7.js → index-wbrqvm2g.js} +6 -6
- package/dist/cli/{index-fqcjragy.js → index-wknz5c8q.js} +1 -1
- package/dist/cli/{index-zb0xcz9t.js → index-wm6f7t7w.js} +3 -3
- package/dist/cli/{index-q4ed1jk7.js → index-wmsehjq6.js} +1994 -1333
- package/dist/cli/{index-4nt52yr9.js → index-zj6t9zgx.js} +173 -25
- package/dist/cli/index-zy7f84cs.js +1210 -0
- package/dist/cli/index.d.ts +11 -1
- package/dist/cli/index.js +61 -39
- package/dist/cli/{knowledge-escalator-ypg14d5r.js → knowledge-escalator-1d79m1tr.js} +12 -11
- package/dist/cli/{knowledge-events-nkrym4wb.js → knowledge-events-ces29ncg.js} +10 -9
- package/dist/cli/{knowledge-link-e4qgqmpx.js → knowledge-link-4cg4776a.js} +3 -3
- package/dist/cli/{knowledge-store-vh3nhtg2.js → knowledge-store-pe8webc2.js} +4 -4
- package/dist/cli/{knowledge-validator-jrxvexv6.js → knowledge-validator-4yjf1f7k.js} +6 -6
- package/dist/cli/{pending-delegations-pw79c8ds.js → pending-delegations-9h1jmtw1.js} +3 -3
- package/dist/cli/{pr-subscriptions-fk628bhc.js → pr-subscriptions-8pg34pev.js} +3 -3
- package/dist/cli/{runner-b02sz2vx.js → runner-cqecp1na.js} +4 -4
- package/dist/cli/{scan-cursor-fp7w5jmc.js → scan-cursor-d6exjmqj.js} +7 -5
- package/dist/cli/{schema-rptwqbm4.js → schema-2esybebd.js} +3 -1
- package/dist/cli/{scope-persistence-0bkaxawa.js → scope-persistence-ej59x0yc.js} +7 -6
- package/dist/cli/{skill-generator-nh8b4gjv.js → skill-generator-yqta3yrg.js} +14 -13
- package/dist/cli/{workspace-snapshot-w3tg4ne5.js → workspace-snapshot-d89zm6wm.js} +5 -2
- package/dist/cli/{worktree-collision-ownership-hqd9ypsz.js → worktree-collision-ownership-vy0kxa98.js} +26 -19
- package/dist/cli/{worktree-isolation-canf3rj8.js → worktree-isolation-rwq0kke7.js} +33 -32
- package/dist/cli/{worktree-provisioning-owner-g24xd417.js → worktree-provisioning-owner-zzkjycp1.js} +3 -3
- package/dist/commands/ci-simulate.d.ts +2 -0
- package/dist/config/cache-paths.d.ts +57 -0
- package/dist/config/evidence-schema.d.ts +3 -3
- package/dist/config/schema.d.ts +9 -0
- package/dist/git/branch.d.ts +2 -0
- package/dist/git/pr.d.ts +2 -0
- package/dist/hooks/delegation-gate/worktree-isolation.d.ts +7 -0
- package/dist/hooks/diff-scope.d.ts +7 -0
- package/dist/hooks/review-receipt-scope.d.ts +7 -0
- package/dist/hooks/reviewer-scope-lifecycle.d.ts +9 -0
- package/dist/hooks/semantic-diff-injection.d.ts +8 -0
- package/dist/index.js +599 -589
- package/dist/mutation/engine.d.ts +11 -0
- package/dist/review/diff-source.d.ts +2 -0
- package/dist/sandbox/capability-probe.d.ts +22 -0
- package/dist/sandbox/executor.d.ts +15 -0
- package/dist/sandbox/linux/bubblewrap-executor.d.ts +6 -0
- package/dist/sandbox/macos/sandbox-exec-executor.d.ts +41 -0
- package/dist/tools/checkpoint.d.ts +11 -0
- package/dist/tools/complexity-hotspots.d.ts +15 -0
- package/dist/tools/diff-summary.d.ts +12 -0
- package/dist/tools/dispatch-lanes.d.ts +8 -0
- package/dist/tools/gh-evidence.d.ts +17 -1
- package/dist/tools/knowledge-receipt.d.ts +1 -1
- package/dist/tools/pkg-audit.d.ts +13 -0
- package/dist/tools/prepare-pr-workflow-checkout.d.ts +1 -0
- package/dist/utils/bun-compat.d.ts +80 -3
- package/dist/utils/git-binary-missing-error.d.ts +80 -2
- package/dist/utils/git-executable.d.ts +179 -0
- package/dist/utils/gitignore-warning.d.ts +10 -0
- package/dist/workflow/coder-settlement.d.ts +18 -0
- package/dist/worktree/core.d.ts +8 -0
- package/dist/worktree/merge.d.ts +33 -0
- package/package.json +3 -2
- package/dist/cli/curator-llm-factory-xgb4pxmm.js +0 -62
- package/dist/cli/guardrail-explain-6wcgr9tz.js +0 -63
- package/dist/cli/index-q1exe2b3.js +0 -256
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import { resolveExecutableFromPath, runExternalTool } from '../utils/external-tool-runner.js';
|
|
3
|
+
import { resolveGitExecutable } from '../utils/git-executable.js';
|
|
3
4
|
export type MutationOutcome = 'killed' | 'survived' | 'timeout' | 'cancelled' | 'error' | 'equivalent' | 'skipped';
|
|
4
5
|
/**
|
|
5
6
|
* Known test runner executables permitted as the first element of testCommand.
|
|
@@ -84,6 +85,16 @@ export declare const _internals: {
|
|
|
84
85
|
runCommand: MutationCommandRunner;
|
|
85
86
|
runExternalTool: typeof runExternalTool;
|
|
86
87
|
resolveExecutableFromPath: typeof resolveExecutableFromPath;
|
|
88
|
+
/**
|
|
89
|
+
* Test seam for git binary resolution (issue #2236 hardening, lane C1b) —
|
|
90
|
+
* used ONLY by the two `executable: 'git'` sites in `executeMutation`
|
|
91
|
+
* (apply / revert). Deliberately NOT used by `runMutationCommand`'s
|
|
92
|
+
* caller-supplied `args.executable` path (see the doc comment above
|
|
93
|
+
* `runMutationCommand`) — that path stays on `resolveExecutableFromPath`
|
|
94
|
+
* so the friendly "git is not installed" message (keyed on
|
|
95
|
+
* `args.executable === 'git'`) keeps working for `git`-flavored callers.
|
|
96
|
+
*/
|
|
97
|
+
resolveGitExecutable: typeof resolveGitExecutable;
|
|
87
98
|
};
|
|
88
99
|
export declare function executeMutation(patch: MutationPatch, testCommand: string[], testFiles: string[], workingDir: string, options?: MutationExecutionOptions): Promise<MutationResult>;
|
|
89
100
|
export declare function computeReport(results: MutationResult[], durationMs: number, budgetMs?: number): MutationReport;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import * as fs from 'node:fs';
|
|
10
10
|
import { bunSpawn } from '../utils/bun-compat.js';
|
|
11
|
+
import { resolveGitExecutableAsync } from '../utils/git-executable.js';
|
|
11
12
|
export interface InclusiveLineRange {
|
|
12
13
|
start: number;
|
|
13
14
|
end: number;
|
|
@@ -130,5 +131,6 @@ export declare const _internals: {
|
|
|
130
131
|
fstatBigIntSync: (fd: number) => fs.BigIntStats;
|
|
131
132
|
readSync: typeof fs.readSync;
|
|
132
133
|
closeSync: typeof fs.closeSync;
|
|
134
|
+
resolveGitExecutable: typeof resolveGitExecutableAsync;
|
|
133
135
|
};
|
|
134
136
|
export {};
|
|
@@ -36,6 +36,27 @@ export interface SandboxCapability {
|
|
|
36
36
|
/** Error message from the probe, if any. */
|
|
37
37
|
error?: string;
|
|
38
38
|
}
|
|
39
|
+
/** Reset the session-lifetime capability cache. Test-only. */
|
|
40
|
+
export declare function _resetCapabilityCache(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Wraps a probe command in an AbortController timeout.
|
|
43
|
+
*
|
|
44
|
+
* @param cmd Command binary to run.
|
|
45
|
+
* @param args Arguments to pass.
|
|
46
|
+
* @param ms Timeout in milliseconds.
|
|
47
|
+
* @returns A promise that resolves to the captured stdout string, or rejects on timeout / error.
|
|
48
|
+
*/
|
|
49
|
+
declare function withProbeTimeout(cmd: string, args: string[], ms: number): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* DI seam for testability. Exposes withProbeTimeout so tests can simulate
|
|
52
|
+
* exit-0/exit-nonzero/ENOENT probe outcomes for every platform's probe
|
|
53
|
+
* (including darwin) without requiring the real binary on the host running
|
|
54
|
+
* the tests. See src/sandbox/macos/sandbox-exec-executor.ts's _internals for
|
|
55
|
+
* the sibling sync-probe seam.
|
|
56
|
+
*/
|
|
57
|
+
export declare const _internals: {
|
|
58
|
+
withProbeTimeout: typeof withProbeTimeout;
|
|
59
|
+
};
|
|
39
60
|
/**
|
|
40
61
|
* Detects the availability of OS-native sandbox mechanisms.
|
|
41
62
|
*
|
|
@@ -67,3 +88,4 @@ export declare class SandboxCapabilityProbe {
|
|
|
67
88
|
*/
|
|
68
89
|
detect(): Promise<SandboxCapability>;
|
|
69
90
|
}
|
|
91
|
+
export {};
|
|
@@ -54,6 +54,21 @@ export interface SandboxExecutor {
|
|
|
54
54
|
* failures on platforms where they don't exist.
|
|
55
55
|
*/
|
|
56
56
|
export declare function getExecutor(): Promise<SandboxExecutor | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Set whether the macOS sandbox-exec mechanism may be activated. Called
|
|
59
|
+
* once from `createToolBeforeHandler` (src/hooks/guardrails/tool-before.ts)
|
|
60
|
+
* using the already-resolved `GuardrailsConfig`, at guardrails hook
|
|
61
|
+
* registration — which runs at plugin init, before the first bash tool call
|
|
62
|
+
* can trigger `getExecutor()`. When false (the default), `getExecutor()`
|
|
63
|
+
* behaves exactly as it did before F6: it resolves to `null` and every
|
|
64
|
+
* consumer (tool-before's `applySandboxExecution`, `diagnose-service`,
|
|
65
|
+
* guardrails/index) observes the identical fail-open "executor not
|
|
66
|
+
* available" state, so activation stays byte-identical to today until this
|
|
67
|
+
* is explicitly turned on.
|
|
68
|
+
*/
|
|
69
|
+
export declare function setMacOSSandboxPolicy(enabled: boolean): void;
|
|
70
|
+
/** @internal test seam — read the current policy without going through config. */
|
|
71
|
+
export declare function _getMacOSSandboxPolicyForTest(): boolean;
|
|
57
72
|
/**
|
|
58
73
|
* Reset the cached executor — useful for testing.
|
|
59
74
|
* @internal
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* for defense-in-depth within the user namespace.
|
|
8
8
|
*/
|
|
9
9
|
import { type SandboxExecutor } from '../executor';
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the bwrap binary: absolute base-OS path when present, bare-name
|
|
12
|
+
* (PATH resolution) fallback otherwise. Never throws.
|
|
13
|
+
*/
|
|
14
|
+
declare function resolveBwrapBinary(): string;
|
|
10
15
|
/**
|
|
11
16
|
* Check whether the bwrap binary is present on PATH.
|
|
12
17
|
* Uses spawnSync to probe synchronously without throwing.
|
|
@@ -20,6 +25,7 @@ declare function probeBwrap(): boolean;
|
|
|
20
25
|
*/
|
|
21
26
|
export declare const _internals: {
|
|
22
27
|
probeBwrap: typeof probeBwrap;
|
|
28
|
+
resolveBwrapBinary: typeof resolveBwrapBinary;
|
|
23
29
|
};
|
|
24
30
|
/**
|
|
25
31
|
* Linux Bubblewrap sandbox executor.
|
|
@@ -11,19 +11,60 @@
|
|
|
11
11
|
* - Read-write access to each scope path and the temp directory
|
|
12
12
|
* - All other file writes are denied
|
|
13
13
|
*/
|
|
14
|
+
import { spawnSync } from 'node:child_process';
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
14
16
|
import { type SandboxExecutor } from '../executor';
|
|
17
|
+
/** Resolve the sandbox-exec binary: absolute base-OS path, bare-name fallback. */
|
|
18
|
+
declare function resolveSandboxExecBinary(): string;
|
|
19
|
+
/** Resolve the probe's target command: absolute base-OS path, bare-name fallback. */
|
|
20
|
+
declare function resolveProbeTargetBinary(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Build the SBPL profile used ONLY for availability probing.
|
|
23
|
+
*
|
|
24
|
+
* F6a item 2 (issue #2236): this deliberately shares the same primitives and
|
|
25
|
+
* ordering as buildSandboxProfile's production profile — a blanket
|
|
26
|
+
* `(deny file-write*)` followed by a scoped `(allow file-write* (subpath …))`,
|
|
27
|
+
* plus a `(setenv …)`/`(unsetenv …)` pair (F6b) — so that probe success
|
|
28
|
+
* implies the production profile's primitives actually parse under this
|
|
29
|
+
* host's sandbox-exec. A trivial `(allow default)`-only probe would pass
|
|
30
|
+
* even when the production profile is unparseable, which is the exact
|
|
31
|
+
* probe-passes/production-fails failure mode this guards against.
|
|
32
|
+
*/
|
|
33
|
+
declare function buildProbeProfile(tempDir: string): string;
|
|
15
34
|
/**
|
|
16
35
|
* Check whether the sandbox-exec binary is present and functional.
|
|
17
36
|
* Uses spawnSync to probe synchronously without throwing.
|
|
37
|
+
*
|
|
38
|
+
* F6 (issue #2236 RC2): sandbox-exec(8) has NO `--version` flag — its
|
|
39
|
+
* synopsis is `sandbox-exec [-f file | -n name | -p string] [-D k=v]
|
|
40
|
+
* command [args...]` (BSD getopt, short options only). The previous probe
|
|
41
|
+
* invoked `sandbox-exec --version`, which is consumed as an invalid option
|
|
42
|
+
* and fails on EVERY macOS host regardless of whether Seatbelt actually
|
|
43
|
+
* works. The corrected probe runs a real invocation
|
|
44
|
+
* (`sandbox-exec -p <profile> <target>`) and gates on **exit code 0 ONLY**.
|
|
45
|
+
* stderr is deliberately never consulted — modern macOS prints a
|
|
46
|
+
* deprecation notice to stderr on every sandbox-exec call, and that is not
|
|
47
|
+
* a failure. Empty stdout with exit 0 IS success (sandbox-exec prints
|
|
48
|
+
* nothing on a clean run of `true`).
|
|
18
49
|
*/
|
|
19
50
|
declare function probeSandboxExec(): boolean;
|
|
51
|
+
declare function probeSandboxExecMemoized(): boolean;
|
|
52
|
+
/** Clear the probe memo. Test-only — production never needs to reset it mid-process. */
|
|
53
|
+
declare function resetProbeMemo(): void;
|
|
20
54
|
/**
|
|
21
55
|
* DI seam for testability. Exposes probeSandboxExec so tests can simulate
|
|
22
56
|
* ENOENT / EACCES / ENOSPC error conditions without requiring a real sandbox-exec binary.
|
|
23
57
|
*/
|
|
24
58
|
export declare const _internals: {
|
|
25
59
|
probeSandboxExec: typeof probeSandboxExec;
|
|
60
|
+
probeSandboxExecMemoized: typeof probeSandboxExecMemoized;
|
|
61
|
+
resetProbeMemo: typeof resetProbeMemo;
|
|
26
62
|
buildSandboxProfile: typeof buildSandboxProfile;
|
|
63
|
+
buildProbeProfile: typeof buildProbeProfile;
|
|
64
|
+
resolveSandboxExecBinary: typeof resolveSandboxExecBinary;
|
|
65
|
+
resolveProbeTargetBinary: typeof resolveProbeTargetBinary;
|
|
66
|
+
exists: typeof existsSync;
|
|
67
|
+
spawnSync: typeof spawnSync;
|
|
27
68
|
};
|
|
28
69
|
/**
|
|
29
70
|
* Build a sandbox-exec profile string for the given scope paths, temp dir, and optional env overrides.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
2
2
|
import { tryAcquireLock } from '../parallel/file-locks.js';
|
|
3
3
|
import { loadPlan } from '../plan/manager.js';
|
|
4
|
+
import { resolveGitExecutable } from '../utils/git-executable.js';
|
|
4
5
|
export declare const _internals: {
|
|
5
6
|
tryAcquireLock: typeof tryAcquireLock;
|
|
6
7
|
loadPlan: typeof loadPlan;
|
|
@@ -9,6 +10,16 @@ export declare const _internals: {
|
|
|
9
10
|
findCommitByExactSubject: typeof findCommitByExactSubject;
|
|
10
11
|
stageAllExcludingSwarm: typeof stageAllExcludingSwarm;
|
|
11
12
|
afterTaskEligibilityRead?: (directory: string, taskId: string) => Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Issue #2236 hardening (F1/F4/F5) — resolves the absolute git executable
|
|
15
|
+
* path instead of spawning the bare `'git'` name. Exposed for test
|
|
16
|
+
* injection (mirrors `src/git/branch.ts`'s `_internals.resolveGitExecutable`
|
|
17
|
+
* convention) so a test that mocks `node:child_process` wholesale to drive
|
|
18
|
+
* `gitExec`'s retry/classification logic can stub a fixed value instead of
|
|
19
|
+
* having the real candidate-probing loop consume the same mocked
|
|
20
|
+
* `spawnSync` call slots the test is asserting on.
|
|
21
|
+
*/
|
|
22
|
+
resolveGitExecutable: typeof resolveGitExecutable;
|
|
12
23
|
};
|
|
13
24
|
declare function stageAllExcludingSwarm(directory: string): void;
|
|
14
25
|
declare function gitExec(args: string[], cwd: string): string;
|
|
@@ -1,2 +1,17 @@
|
|
|
1
1
|
import type { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { bunSpawn } from '../utils/bun-compat';
|
|
3
|
+
import { resolveGitExecutable } from '../utils/git-executable.js';
|
|
4
|
+
/**
|
|
5
|
+
* Test-only seam for the `bunSpawn` call this file makes. Lets tests inject a
|
|
6
|
+
* synthetic subprocess (e.g. one with `spawnError` set) without monkey-patching
|
|
7
|
+
* the `Bun.spawn` global — see #2236 Sweep A, FIX 1.
|
|
8
|
+
*
|
|
9
|
+
* `resolveGitExecutable` (issue #2236 hardening, F1/F4/F5) resolves the
|
|
10
|
+
* absolute git executable path instead of spawning the bare `'git'` name;
|
|
11
|
+
* exposed here so tests can inject a deterministic value.
|
|
12
|
+
*/
|
|
13
|
+
export declare const _internals: {
|
|
14
|
+
bunSpawn: typeof bunSpawn;
|
|
15
|
+
resolveGitExecutable: typeof resolveGitExecutable;
|
|
16
|
+
};
|
|
2
17
|
export declare const complexity_hotspots: ReturnType<typeof tool>;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import * as child_process from 'node:child_process';
|
|
1
2
|
import { type ChangeCategory, type RiskLevel } from '../diff/semantic-classifier.js';
|
|
3
|
+
import { resolveGitExecutableAsync } from '../utils/git-executable.js';
|
|
2
4
|
import { createSwarmTool } from './create-tool';
|
|
5
|
+
export declare const _internals: {
|
|
6
|
+
execFile: typeof child_process.execFile;
|
|
7
|
+
resolveGitExecutableAsync: typeof resolveGitExecutableAsync;
|
|
8
|
+
execGit: typeof execGit;
|
|
9
|
+
};
|
|
10
|
+
declare function execGit(workingDir: string, args: string[], options?: {
|
|
11
|
+
timeout?: number;
|
|
12
|
+
maxBuffer?: number;
|
|
13
|
+
}): Promise<string>;
|
|
3
14
|
export interface DiffSummaryArgs {
|
|
4
15
|
files: string[];
|
|
5
16
|
classification?: ChangeCategory;
|
|
@@ -10,3 +21,4 @@ export interface DiffSummaryArgs {
|
|
|
10
21
|
* to produce a filtered SemanticDiffSummary.
|
|
11
22
|
*/
|
|
12
23
|
export declare const diff_summary: ReturnType<typeof createSwarmTool>;
|
|
24
|
+
export {};
|
|
@@ -399,6 +399,7 @@ export declare const _test_exports: {
|
|
|
399
399
|
*/
|
|
400
400
|
resetDeliveredLaneOutputs: () => void;
|
|
401
401
|
recordToLaneResult: typeof recordToLaneResult;
|
|
402
|
+
prReviewLaneResponseBudgetChars: typeof prReviewLaneResponseBudgetChars;
|
|
402
403
|
};
|
|
403
404
|
type ReadOnlyToolPermissions = Record<string, false> & {
|
|
404
405
|
write: false;
|
|
@@ -497,6 +498,13 @@ declare function applyExplorerFormatSuffix(lanes: DispatchLaneSpec[], options?:
|
|
|
497
498
|
failClosed?: boolean;
|
|
498
499
|
mode?: string;
|
|
499
500
|
}): ApplyCommonPromptResult;
|
|
501
|
+
/**
|
|
502
|
+
* #2276: derive the final-response character budget for a PR-review lane from
|
|
503
|
+
* the lane's owned workload. Returns `undefined` for modes without a derived
|
|
504
|
+
* budget (the swarm-pr-feedback modes keep their flat
|
|
505
|
+
* {@link PR_WORKFLOW_PROTOCOL_OUTPUT_MAX_CHARS} guidance).
|
|
506
|
+
*/
|
|
507
|
+
declare function prReviewLaneResponseBudgetChars(mode: string, lane: DispatchLaneSpec): number | undefined;
|
|
500
508
|
declare function applyPrWorkflowPromptContract(lanes: DispatchLaneSpec[], options: {
|
|
501
509
|
mode?: string;
|
|
502
510
|
prHeadSha?: string;
|
|
@@ -5,7 +5,23 @@ interface GhBinaryCandidateOptions {
|
|
|
5
5
|
platform?: NodeJS.Platform;
|
|
6
6
|
}
|
|
7
7
|
export declare function resolveGhBinaryCandidates(options?: GhBinaryCandidateOptions): string[];
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the `gh` binary to invoke. Exported (issue #2236 hardening, lane
|
|
10
|
+
* C1b) so other call sites that need a `gh` executable — e.g. `src/git/pr.ts`,
|
|
11
|
+
* `src/commands/pr-monitor-status.ts` — reuse this resolver instead of
|
|
12
|
+
* spawning a bare `'gh'` literal or inventing a second gh resolver. Returns
|
|
13
|
+
* `null` when no candidate is found; callers should fall back to the bare
|
|
14
|
+
* `'gh'` literal (mirrors `resolveGitExecutable()`'s "never regress a working
|
|
15
|
+
* host" fallback in `src/utils/git-executable.ts`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveGhBinary(): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* TEST-ONLY seam (issue #2236 FR-006 ratchet fix) — NOT a production API, do
|
|
20
|
+
* not call from `src/`. Sets the pin `resolveGhBinary()` checks first; pass
|
|
21
|
+
* `null` to simulate "no `gh` candidate found". Mirrors
|
|
22
|
+
* `__seedGitExecutableForTests` in `src/utils/git-executable.ts`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function __seedGhBinaryForTests(value: string | null): void;
|
|
9
25
|
export declare const gh_evidence: ToolDefinition;
|
|
10
26
|
export declare const _internals: {
|
|
11
27
|
resolveGhBinaryCandidates: typeof resolveGhBinaryCandidates;
|
|
@@ -17,8 +17,8 @@ import { createSwarmTool } from './create-tool.js';
|
|
|
17
17
|
declare const ignoredItem: z.ZodObject<{
|
|
18
18
|
id: z.ZodString;
|
|
19
19
|
reason: z.ZodEnum<{
|
|
20
|
-
stale: "stale";
|
|
21
20
|
other: "other";
|
|
21
|
+
stale: "stale";
|
|
22
22
|
superseded: "superseded";
|
|
23
23
|
unsafe: "unsafe";
|
|
24
24
|
too_generic: "too_generic";
|
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
import type { tool } from '@opencode-ai/plugin';
|
|
2
|
+
import { bunSpawn } from '../utils/bun-compat';
|
|
3
|
+
/**
|
|
4
|
+
* Test-only seam for the `bunSpawn` calls `runNpmAudit` and `runCargoAudit`
|
|
5
|
+
* make. Lets tests inject a synthetic subprocess (e.g. one with `spawnError`
|
|
6
|
+
* set) without monkey-patching the `Bun.spawn` global — see #2236 Sweep A,
|
|
7
|
+
* FIX 2. These two route through the seam because both had a path where a
|
|
8
|
+
* failed spawn could be reported as a completed scan; the remaining audit
|
|
9
|
+
* functions gate strictly on a non-zero exit and were dispositioned
|
|
10
|
+
* SAFE-EXIT-CHECK by that sweep.
|
|
11
|
+
*/
|
|
12
|
+
export declare const _internals: {
|
|
13
|
+
bunSpawn: typeof bunSpawn;
|
|
14
|
+
};
|
|
2
15
|
export declare const pkg_audit: ReturnType<typeof tool>;
|
|
@@ -22,6 +22,7 @@ declare function runGit(directory: string, args: string[], options?: {
|
|
|
22
22
|
}): Promise<{
|
|
23
23
|
exitCode: number;
|
|
24
24
|
stdout: string;
|
|
25
|
+
spawnError?: Error | null;
|
|
25
26
|
}>;
|
|
26
27
|
declare function readBoundedGitStdout(stream: {
|
|
27
28
|
getReader(): ReadableStreamDefaultReader<Uint8Array>;
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* present and falls back to a stable djb2-derived 32-bit hash on Node.
|
|
26
26
|
*/
|
|
27
27
|
import { spawn as nodeSpawn } from 'node:child_process';
|
|
28
|
+
import * as fsSync from 'node:fs';
|
|
28
29
|
/**
|
|
29
30
|
* Whether the current runtime is Bun. Cached at first call — every subsequent
|
|
30
31
|
* call is a single property access.
|
|
@@ -118,9 +119,16 @@ export interface BunCompatSubprocess {
|
|
|
118
119
|
exitCode: number | null;
|
|
119
120
|
readonly signalCode?: NodeJS.Signals | null;
|
|
120
121
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
122
|
+
* Process-creation failure (for example ENOENT), reported as a **value**
|
|
123
|
+
* on every runtime.
|
|
124
|
+
*
|
|
125
|
+
* The Node fallback populates it from ChildProcess's `error` event. Bun
|
|
126
|
+
* reports the same failures by throwing synchronously from `Bun.spawn`;
|
|
127
|
+
* issue #2236 showed that throw escaping uncaught to a tool boundary and
|
|
128
|
+
* surfacing a raw `ENOENT ... posix_spawn 'git'` to the user. The Bun path
|
|
129
|
+
* is now normalised *down* to this contract — the throw is caught and
|
|
130
|
+
* exposed here — so process-creation failures have no exit code, are
|
|
131
|
+
* described by `spawnError`, and `bunSpawn` never throws.
|
|
124
132
|
*/
|
|
125
133
|
readonly spawnError?: Error | null;
|
|
126
134
|
kill(signal?: NodeJS.Signals | number): void;
|
|
@@ -133,7 +141,76 @@ export declare const _internals: {
|
|
|
133
141
|
cwd: () => string;
|
|
134
142
|
spawnTaskkill: (args: string[], options: Parameters<typeof nodeSpawn>[2]) => import("node:child_process").ChildProcess;
|
|
135
143
|
createProcessTreeKiller: typeof createProcessTreeKiller;
|
|
144
|
+
/**
|
|
145
|
+
* Test seam for the spawn-`cwd` probe. Lets a test drive the `EACCES`
|
|
146
|
+
* branch on hosts (Windows) where an unreadable directory cannot be created
|
|
147
|
+
* without elevation, instead of skipping the case.
|
|
148
|
+
*/
|
|
149
|
+
statSync: (target: string) => fsSync.Stats;
|
|
136
150
|
};
|
|
151
|
+
/** Why a spawn `cwd` was rejected before the child was ever created. */
|
|
152
|
+
export type SpawnCwdFailureReason = 'missing' | 'not-directory';
|
|
153
|
+
/**
|
|
154
|
+
* Raised as a **value**, never thrown: `bunSpawn`/`bunSpawnSync` surface it
|
|
155
|
+
* through the runtime's existing failure contract (`spawnError` plus a
|
|
156
|
+
* non-zero `exited`), and `runGit` converts it into its typed failure result.
|
|
157
|
+
* Throwing it would escalate previously-safe call sites into unhandled
|
|
158
|
+
* synchronous throws — the exact leak class this change removes.
|
|
159
|
+
*/
|
|
160
|
+
export declare class SpawnCwdMissingError extends Error {
|
|
161
|
+
readonly name = "SpawnCwdMissingError";
|
|
162
|
+
/** Kept ENOENT so existing `code`-sniffing call sites keep working. */
|
|
163
|
+
readonly code = "ENOENT";
|
|
164
|
+
readonly cwd: string;
|
|
165
|
+
readonly reason: SpawnCwdFailureReason;
|
|
166
|
+
readonly executable: string;
|
|
167
|
+
constructor(cwd: string, reason: SpawnCwdFailureReason, executable: string, options?: {
|
|
168
|
+
cause?: unknown;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/** Observable state of a spawn `cwd`. */
|
|
172
|
+
export type SpawnCwdState =
|
|
173
|
+
/** Present and a directory — a spawn ENOENT here really is the binary. */
|
|
174
|
+
'directory'
|
|
175
|
+
/** Definitely absent. */
|
|
176
|
+
| 'missing'
|
|
177
|
+
/** Present but not a directory (a file, for example). */
|
|
178
|
+
| 'not-directory'
|
|
179
|
+
/** `stat` refused (`EACCES`/`EPERM`) — we cannot tell. */
|
|
180
|
+
| 'unreadable'
|
|
181
|
+
/** `stat` failed for some other reason — we cannot tell. */
|
|
182
|
+
| 'unknown';
|
|
183
|
+
/**
|
|
184
|
+
* Inspects a spawn `cwd` with `statSync(...).isDirectory()`.
|
|
185
|
+
*
|
|
186
|
+
* `existsSync` is deliberately NOT used: it returns `true` for a `cwd` that is
|
|
187
|
+
* a regular *file* (the spawn then fails `ENOTDIR` on POSIX / `ENOENT` on
|
|
188
|
+
* Windows) and `false` when `stat` fails with `EACCES` (the directory is in
|
|
189
|
+
* fact present). Both would be misclassified.
|
|
190
|
+
*
|
|
191
|
+
* Verified rather than assumed: a **relative** `cwd` is safe (the stat and the
|
|
192
|
+
* child resolve against the same parent cwd), and a **symlinked** `cwd` is
|
|
193
|
+
* safe (`statSync` follows the link, as does the child).
|
|
194
|
+
*/
|
|
195
|
+
export declare function inspectSpawnCwd(cwd: string): SpawnCwdState;
|
|
196
|
+
/**
|
|
197
|
+
* Returns a typed error when `cwd` is *definitely* unusable as a spawn working
|
|
198
|
+
* directory, `null` otherwise.
|
|
199
|
+
*
|
|
200
|
+
* An `unreadable`/`unknown` `cwd` deliberately returns `null`: refusing to
|
|
201
|
+
* spawn on "I cannot tell" would convert a stat permission quirk into a hard
|
|
202
|
+
* failure. The spawn proceeds and the OS decides; the classifiers in
|
|
203
|
+
* `git-binary-missing-error.ts` then report the honest third state.
|
|
204
|
+
*/
|
|
205
|
+
export declare function describeSpawnCwdFailure(cwd: string, executable: string, cause?: unknown): SpawnCwdMissingError | null;
|
|
206
|
+
/** Mutually exclusive classification of a spawn failure. */
|
|
207
|
+
export type SpawnFailureClass = 'binary-missing' | 'cwd-missing' | 'cwd-unreadable' | 'other';
|
|
208
|
+
/**
|
|
209
|
+
* Single source of truth for the three-way split (issue #2236).
|
|
210
|
+
* `git-binary-missing-error.ts` re-exports this and its predicates delegate
|
|
211
|
+
* here, so the wrap below and every caller-side check can never disagree.
|
|
212
|
+
*/
|
|
213
|
+
export declare function classifySpawnFailure(err: unknown, cwd?: string): SpawnFailureClass;
|
|
137
214
|
/**
|
|
138
215
|
* Merges `envOverrides` into the base env (or `process.env` if no base env
|
|
139
216
|
* is given) and returns the resulting record.
|
|
@@ -1,9 +1,87 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Spawn-failure classification for git (and any other external binary).
|
|
3
|
+
*
|
|
4
|
+
* Issue #2236: a spawn that fails with `ENOENT` was previously read as
|
|
5
|
+
* "the git binary is not on PATH". That is only one of the reasons a spawn
|
|
6
|
+
* can produce `ENOENT`. When the `cwd` handed to the spawn no longer exists,
|
|
7
|
+
* libuv reports the *same* code — `ENOENT: no such file or directory,
|
|
8
|
+
* posix_spawn 'git'` (`uv_spawn` on Windows) — and the misclassification sent
|
|
9
|
+
* the reported bug down a four-day PATH investigation while git was present
|
|
10
|
+
* the whole time.
|
|
11
|
+
*
|
|
12
|
+
* The discriminator is the `cwd` the caller already holds. Classification is
|
|
13
|
+
* three-way, never two-way: "I cannot tell" gets its own state and is never
|
|
14
|
+
* folded into either definite bucket.
|
|
15
|
+
*
|
|
16
|
+
* The `cwd` probe itself (`inspectSpawnCwd`, `SpawnCwdMissingError`) lives in
|
|
17
|
+
* `bun-compat.ts` — that file must stay loadable by bare Node, so it cannot
|
|
18
|
+
* import from here. It is re-exported below so callers still have one
|
|
19
|
+
* classification surface.
|
|
20
|
+
*/
|
|
21
|
+
export { classifySpawnFailure, describeSpawnCwdFailure, inspectSpawnCwd, type SpawnCwdFailureReason, SpawnCwdMissingError, type SpawnCwdState, type SpawnFailureClass, } from './bun-compat.js';
|
|
22
|
+
/**
|
|
23
|
+
* Base type for "git never ran".
|
|
24
|
+
*
|
|
25
|
+
* Both subclasses mean the child process was never created, so **nothing may
|
|
26
|
+
* be inferred from its absence of output**. That distinction is the whole
|
|
27
|
+
* point: a caller that reads "git produced no result" as a fact about the
|
|
28
|
+
* repository (for example "this path is not in HEAD") is only entitled to do
|
|
29
|
+
* so when git actually executed and reported. Callers therefore discriminate
|
|
30
|
+
* on this base, not on either subclass — a two-way `instanceof` check against
|
|
31
|
+
* a three-way classification is what re-introduces the #2236 misdiagnosis one
|
|
32
|
+
* state at a time.
|
|
33
|
+
*/
|
|
34
|
+
export declare class GitUnavailableError extends Error {
|
|
35
|
+
}
|
|
36
|
+
export declare class GitBinaryMissingError extends GitUnavailableError {
|
|
2
37
|
readonly name = "GitBinaryMissingError";
|
|
3
38
|
constructor(message?: string, options?: {
|
|
4
39
|
cause?: unknown;
|
|
5
40
|
});
|
|
6
41
|
}
|
|
7
|
-
|
|
42
|
+
/** Which of the two `cwd` fault states produced a {@link GitSpawnCwdError}. */
|
|
43
|
+
export type GitSpawnCwdFault = 'missing' | 'unreadable';
|
|
44
|
+
/**
|
|
45
|
+
* git could not start because its `cwd` was unusable — the #2236 shape.
|
|
46
|
+
*
|
|
47
|
+
* Deliberately a *sibling* of {@link GitBinaryMissingError}, never a subclass:
|
|
48
|
+
* "the working directory is gone" and "git is not installed" are different
|
|
49
|
+
* facts with different remediations, and the #2236 regression suites assert
|
|
50
|
+
* that a cwd fault is `not.toBeInstanceOf(GitBinaryMissingError)`.
|
|
51
|
+
*
|
|
52
|
+
* The message text is rendered here rather than at each throw site so all four
|
|
53
|
+
* `execGit`-style call sites (`git/branch.ts`, `tools/checkpoint.ts`,
|
|
54
|
+
* `hooks/semantic-diff-injection.ts`, `tools/diff-summary.ts`) cannot drift.
|
|
55
|
+
*/
|
|
56
|
+
export declare class GitSpawnCwdError extends GitUnavailableError {
|
|
57
|
+
readonly name = "GitSpawnCwdError";
|
|
58
|
+
readonly cwd: string;
|
|
59
|
+
readonly fault: GitSpawnCwdFault;
|
|
60
|
+
constructor(cwd: string, fault: GitSpawnCwdFault, options?: {
|
|
61
|
+
cause?: unknown;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* True when the spawn failed because the executable itself could not be
|
|
66
|
+
* resolved. Passing the `cwd` the caller already holds is what makes this
|
|
67
|
+
* answer trustworthy; omitting it preserves the pre-#2236 ENOENT-only
|
|
68
|
+
* behaviour for call sites that have no cwd to offer.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isGitBinaryMissing(err: unknown, cwd?: string): err is {
|
|
71
|
+
code?: string;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* True when the spawn failed because `cwd` is gone, or exists but is not a
|
|
75
|
+
* directory. This is the #2236 failure shape.
|
|
76
|
+
*/
|
|
77
|
+
export declare function isSpawnCwdMissing(err: unknown, cwd: string): err is {
|
|
78
|
+
code?: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* True when `cwd` could not be inspected (`EACCES`/`EPERM`, or an unexpected
|
|
82
|
+
* stat failure). Never folded into either definite bucket — callers must fail
|
|
83
|
+
* closed on it rather than assume the directory is gone.
|
|
84
|
+
*/
|
|
85
|
+
export declare function isSpawnCwdUnreadable(err: unknown, cwd: string): err is {
|
|
8
86
|
code?: string;
|
|
9
87
|
};
|