opencode-swarm 7.139.2 → 7.139.4
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/phase-wrap/SKILL.md +2 -2
- package/README.md +2 -2
- package/dist/background/stage-b-gates.d.ts +5 -1
- package/dist/background/task-envelope.d.ts +4 -4
- package/dist/cli/{config-doctor-hrb61yqe.js → config-doctor-whxr386t.js} +6 -6
- package/dist/cli/{core-g2dfh9fq.js → core-aj5g7an6.js} +5 -5
- package/dist/cli/{curation-policy-4tp0mbcb.js → curation-policy-anym2y3v.js} +8 -8
- package/dist/cli/{curator-drift-vfh07mqy.js → curator-drift-49p3jnte.js} +7 -7
- package/dist/cli/{curator-vpcs1p1v.js → curator-e8cvb55d.js} +41 -41
- package/dist/cli/curator-llm-factory-h9xbpgmw.js +61 -0
- package/dist/cli/{dispatch-b1fge4xk.js → dispatch-2s23fbcs.js} +4 -4
- package/dist/cli/{evidence-summary-service-kzxr71yd.js → evidence-summary-service-g82bsjqa.js} +16 -16
- package/dist/cli/{gate-evidence-z2b1ymnw.js → gate-evidence-72cgrvs2.js} +6 -5
- package/dist/cli/guardrail-explain-0be7msvq.js +62 -0
- package/dist/cli/{guardrail-log-2ftew0p3.js → guardrail-log-9mm5443g.js} +9 -9
- package/dist/cli/{hive-promoter-mpf0cfkk.js → hive-promoter-nnzs5x1r.js} +41 -41
- package/dist/cli/{index-w71cq27a.js → index-0e95eck5.js} +5 -5
- package/dist/cli/{index-5zyk8qgv.js → index-0xkjhgrf.js} +5 -5
- package/dist/cli/{index-q7ezzgwq.js → index-1kyex7z2.js} +1 -1
- package/dist/cli/{index-668dpw5e.js → index-33skgk1a.js} +1 -1
- package/dist/cli/{index-vm4xw9z3.js → index-41hkt36g.js} +2 -2
- package/dist/cli/{index-y111zefa.js → index-4nt52yr9.js} +80 -31
- package/dist/cli/{index-3jcyn8g6.js → index-4wjk296r.js} +1 -1
- package/dist/cli/{index-3radty3f.js → index-5azdnaty.js} +2 -2
- package/dist/cli/{index-8p9pasnp.js → index-5s23pfsy.js} +8 -8
- package/dist/cli/{index-5w7ekpy3.js → index-5z2xps64.js} +2 -2
- package/dist/cli/{index-0wp67gqj.js → index-6nzmp937.js} +61 -111
- package/dist/cli/{index-gvhvz176.js → index-6r522srn.js} +2 -2
- package/dist/cli/{index-4xbyy6aw.js → index-6rxgb5r9.js} +10 -6
- package/dist/cli/{index-cyw81ngh.js → index-6vh6vrnk.js} +10 -10
- package/dist/cli/{index-a12906mj.js → index-6z0a940s.js} +8 -8
- package/dist/cli/{index-wsdnttf4.js → index-74hpm6sh.js} +1 -1
- package/dist/cli/{index-6w1re1qn.js → index-9cdj4020.js} +6 -6
- package/dist/cli/{index-y47dwge1.js → index-e1k9vpqn.js} +5 -5
- package/dist/cli/{index-y64jv2pe.js → index-ejbcpbzp.js} +7 -7
- package/dist/cli/{index-6c5f309q.js → index-gfmrw2f5.js} +2 -2
- package/dist/cli/{index-prmb5qfp.js → index-j77frjq8.js} +7 -7
- package/dist/cli/{index-ffpmqx30.js → index-jnfyxeap.js} +4 -4
- package/dist/cli/{index-e9tx99ds.js → index-k41dn8me.js} +3 -3
- package/dist/cli/{index-x9q4bbhd.js → index-k46me75h.js} +4 -4
- package/dist/cli/{index-s608d3hw.js → index-nrx08gcr.js} +6 -2
- package/dist/cli/{index-ktagrqxw.js → index-pg84msyc.js} +7 -7
- package/dist/cli/{index-a5eba0t8.js → index-rsrx77fg.js} +6 -6
- package/dist/cli/index-s0qc4gj6.js +298 -0
- package/dist/cli/{index-q11t5erh.js → index-s58vghgj.js} +7 -7
- package/dist/cli/{index-se8xc78k.js → index-sa15nfgg.js} +45 -45
- package/dist/cli/{index-wrt6m5ze.js → index-sd657fkp.js} +291 -75
- package/dist/cli/{index-yr6x707c.js → index-vfsqpcz6.js} +16 -16
- package/dist/cli/{index-a7nh382r.js → index-vyqd1hzm.js} +20593 -19882
- package/dist/cli/{index-8gftfvpp.js → index-xb1zq933.js} +1 -1
- package/dist/cli/{index-3eddtgxt.js → index-xmhhhjjw.js} +39 -4
- package/dist/cli/index.js +43 -43
- package/dist/cli/{knowledge-escalator-n9pmx4qr.js → knowledge-escalator-a6z30y9p.js} +10 -10
- package/dist/cli/{knowledge-events-raevm18w.js → knowledge-events-deq0ds8e.js} +7 -7
- package/dist/cli/{knowledge-link-3tq8w6gs.js → knowledge-link-bmbatt8s.js} +6 -6
- package/dist/cli/{knowledge-store-bcfqz8fr.js → knowledge-store-vdr19mnq.js} +8 -8
- package/dist/cli/{knowledge-validator-jxqj96cx.js → knowledge-validator-5hgacnrf.js} +11 -11
- package/dist/cli/{pending-delegations-tmyf18p4.js → pending-delegations-7ayryxbg.js} +8 -8
- package/dist/cli/{pr-subscriptions-hhx6yk24.js → pr-subscriptions-w5y08ebc.js} +8 -8
- package/dist/cli/{runner-w30gazew.js → runner-h7vmgkth.js} +7 -6
- package/dist/cli/{scan-cursor-ah5swtyh.js → scan-cursor-d6qcg9hr.js} +9 -9
- package/dist/cli/{schema-f7jgrtxj.js → schema-y1zekrag.js} +3 -3
- package/dist/cli/{scope-persistence-3f0d4fwv.js → scope-persistence-tj6qway9.js} +7 -7
- package/dist/cli/{skill-generator-hp7as46c.js → skill-generator-bw8xhzzn.js} +13 -13
- package/dist/cli/{task-envelope-qn0qtnh0.js → task-envelope-jp2fdsvn.js} +11 -8
- package/dist/cli/{telemetry-4tgrfhaz.js → telemetry-62cn5t24.js} +1 -1
- package/dist/cli/{workspace-snapshot-h5rzw37b.js → workspace-snapshot-w3tg4ne5.js} +2 -2
- package/dist/cli/{worktree-collision-ownership-vexb0b6r.js → worktree-collision-ownership-hs5c2qzp.js} +9 -9
- package/dist/commands/approve-plan-critic.d.ts +2 -2
- package/dist/commands/registry.d.ts +1 -1
- package/dist/config/agent-model.d.ts +35 -0
- package/dist/db/qa-gate-profile.d.ts +11 -3
- package/dist/evidence/manager.d.ts +5 -2
- package/dist/evidence/phase-participation.d.ts +44 -0
- package/dist/hooks/compaction-customizer.d.ts +30 -2
- package/dist/hooks/context-budget.d.ts +1 -1
- package/dist/hooks/delegation-gate.d.ts +3 -3
- package/dist/hooks/guardrails/index.d.ts +5 -1
- package/dist/hooks/guardrails/messages-transform.d.ts +2 -0
- package/dist/hooks/guardrails/pre-check-result.d.ts +20 -0
- package/dist/index.js +616 -609
- package/dist/prm/escalation.d.ts +34 -0
- package/dist/prm/index.d.ts +6 -2
- package/dist/prm/pattern-detector.d.ts +22 -1
- package/dist/prm/types.d.ts +12 -2
- package/dist/sast/semgrep.d.ts +15 -32
- package/dist/services/compaction-service.d.ts +3 -1
- package/dist/session/snapshot-writer.d.ts +1 -0
- package/dist/state.d.ts +119 -19
- package/dist/summaries/schema.d.ts +2 -2
- package/dist/tools/context-status.d.ts +4 -1
- package/dist/tools/convene-council.d.ts +1 -1
- package/dist/tools/lint.d.ts +48 -22
- package/dist/tools/pre-check-batch.d.ts +41 -13
- package/dist/tools/quality-budget.d.ts +3 -2
- package/dist/tools/resolve-working-directory.d.ts +4 -4
- package/dist/tools/sast-baseline.d.ts +1 -0
- package/dist/tools/sast-scan.d.ts +4 -1
- package/dist/tools/secretscan.d.ts +2 -2
- package/dist/tools/set-qa-gates.d.ts +5 -4
- package/dist/tools/submit-phase-council-verdicts.d.ts +1 -1
- package/dist/tools/write-final-council-evidence.d.ts +1 -1
- package/dist/utils/bun-compat.d.ts +20 -0
- package/dist/utils/external-tool-runner.d.ts +10 -0
- package/dist/utils/project-boundary.d.ts +34 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-hvw13hmr.js +0 -61
- package/dist/cli/guardrail-explain-k62h3c92.js +0 -62
- package/dist/cli/index-5j6chvj8.js +0 -159
- package/dist/cli/{index-z6xqpmqg.js → index-ee3x66a5.js} +3 -3
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
import type { tool } from '@opencode-ai/plugin';
|
|
7
7
|
import type { PluginConfig } from '../config';
|
|
8
8
|
import { saveEvidence } from '../evidence/manager.js';
|
|
9
|
-
import
|
|
9
|
+
import { runExternalTool } from '../utils/external-tool-runner';
|
|
10
|
+
import type { LintResult, ResolvedLinterCommand } from './lint';
|
|
11
|
+
import { detectResolvedLinter } from './lint';
|
|
10
12
|
import type { QualityBudgetResult } from './quality-budget';
|
|
11
13
|
import { qualityBudget } from './quality-budget';
|
|
12
14
|
import type { SastScanFinding, SastScanResult } from './sast-scan';
|
|
@@ -17,8 +19,15 @@ export declare const _internals: {
|
|
|
17
19
|
runSecretscanWrapped: typeof runSecretscanWrapped;
|
|
18
20
|
runSastScanWrapped: typeof runSastScanWrapped;
|
|
19
21
|
runQualityBudgetWrapped: typeof runQualityBudgetWrapped;
|
|
22
|
+
runWithTimeout: typeof runWithTimeout;
|
|
20
23
|
getChangedLineRanges: typeof getChangedLineRanges;
|
|
21
24
|
saveEvidence: typeof saveEvidence;
|
|
25
|
+
runExternalTool: typeof runExternalTool;
|
|
26
|
+
detectResolvedLinter: typeof detectResolvedLinter;
|
|
27
|
+
runLintOnFiles: typeof runLintOnFiles;
|
|
28
|
+
platform: () => NodeJS.Platform;
|
|
29
|
+
serializePreCheckResult: typeof serializePreCheckResult;
|
|
30
|
+
MAX_COMBINED_BYTES: number;
|
|
22
31
|
};
|
|
23
32
|
export interface PreCheckBatchInput {
|
|
24
33
|
/** List of specific files to check (optional) */
|
|
@@ -45,10 +54,14 @@ export interface ToolResult<T> {
|
|
|
45
54
|
result?: T;
|
|
46
55
|
/** Error message if failed */
|
|
47
56
|
error?: string;
|
|
57
|
+
/** Successful result payload was omitted from a compact serialized response. */
|
|
58
|
+
result_omitted?: boolean;
|
|
48
59
|
/** Duration in milliseconds */
|
|
49
60
|
duration_ms: number;
|
|
50
61
|
}
|
|
51
62
|
export interface PreCheckBatchResult {
|
|
63
|
+
/** Structured producer status. Optional only for legacy serialized results. */
|
|
64
|
+
batch_status?: 'completed' | 'skipped' | 'invalid';
|
|
52
65
|
/** Overall gate status: true if all security gates pass */
|
|
53
66
|
gates_passed: boolean;
|
|
54
67
|
/** Lint tool result */
|
|
@@ -64,36 +77,51 @@ export interface PreCheckBatchResult {
|
|
|
64
77
|
/** Pre-existing SAST findings on unchanged lines, requiring reviewer triage */
|
|
65
78
|
sast_preexisting_findings?: SastScanFinding[];
|
|
66
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Serialize the public result below the decoder's stricter byte ceiling. When
|
|
82
|
+
* detailed diagnostics exceed the aggregate budget, preserve every control
|
|
83
|
+
* field and replace optional payloads with bounded, UTF-8-safe summaries.
|
|
84
|
+
*/
|
|
85
|
+
declare function serializePreCheckResult(result: PreCheckBatchResult): string;
|
|
86
|
+
declare function isAcceptedProjectRootForPlatform(dir: string, workspaceDir: string, platform: NodeJS.Platform, hasExplicitBoundary: boolean): boolean;
|
|
87
|
+
export declare const _test_exports: {
|
|
88
|
+
isAcceptedProjectRootForPlatform: typeof isAcceptedProjectRootForPlatform;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Run a function with timeout
|
|
92
|
+
*/
|
|
93
|
+
declare function runWithTimeout<T>(operation: (abortSignal: AbortSignal) => Promise<T>, timeoutMs: number, parentSignal?: AbortSignal, waitForCancellationSettlement?: boolean): Promise<T>;
|
|
67
94
|
/**
|
|
68
95
|
* Run lint with detection and timeout
|
|
69
96
|
*/
|
|
70
|
-
declare function runLintWrapped(files: string[] | undefined, directory: string, _config?: PluginConfig): Promise<ToolResult<LintResult>>;
|
|
97
|
+
declare function runLintWrapped(files: string[] | undefined, directory: string, _config?: PluginConfig, abortSignal?: AbortSignal): Promise<ToolResult<LintResult>>;
|
|
98
|
+
/**
|
|
99
|
+
* Run lint on specific files only
|
|
100
|
+
*/
|
|
101
|
+
declare function runLintOnFiles(resolvedLinter: ResolvedLinterCommand, files: string[], workspaceDir: string, abortSignal?: AbortSignal): Promise<LintResult>;
|
|
71
102
|
/**
|
|
72
103
|
* Run secretscan with timeout
|
|
73
104
|
*/
|
|
74
|
-
declare function runSecretscanWrapped(files: string[] | undefined, directory: string, _config?: PluginConfig): Promise<ToolResult<SecretscanResult | SecretscanErrorResult>>;
|
|
105
|
+
declare function runSecretscanWrapped(files: string[] | undefined, directory: string, _config?: PluginConfig, abortSignal?: AbortSignal): Promise<ToolResult<SecretscanResult | SecretscanErrorResult>>;
|
|
75
106
|
/**
|
|
76
107
|
* Run SAST scan with timeout
|
|
77
108
|
*/
|
|
78
|
-
declare function runSastScanWrapped(changedFiles: string[], directory: string, severityThreshold: 'low' | 'medium' | 'high' | 'critical', config?: PluginConfig, phase?: number): Promise<ToolResult<SastScanResult>>;
|
|
109
|
+
declare function runSastScanWrapped(changedFiles: string[], directory: string, severityThreshold: 'low' | 'medium' | 'high' | 'critical', config?: PluginConfig, phase?: number, abortSignal?: AbortSignal): Promise<ToolResult<SastScanResult>>;
|
|
79
110
|
/**
|
|
80
111
|
* Run quality budget with timeout
|
|
81
112
|
*/
|
|
82
|
-
declare function runQualityBudgetWrapped(changedFiles: string[], directory: string, config?: PluginConfig): Promise<ToolResult<QualityBudgetResult>>;
|
|
113
|
+
declare function runQualityBudgetWrapped(changedFiles: string[], directory: string, config?: PluginConfig, abortSignal?: AbortSignal): Promise<ToolResult<QualityBudgetResult>>;
|
|
83
114
|
/**
|
|
84
115
|
* Parse unified diff output (with -U0) to extract added/modified line numbers per file.
|
|
85
116
|
* Returns a Map from normalised file path → Set of changed line numbers.
|
|
86
117
|
*/
|
|
87
118
|
export declare function parseDiffLineRanges(diffOutput: string): Map<string, Set<number>>;
|
|
88
119
|
/**
|
|
89
|
-
* Get
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* 2. HEAD~1 (single-commit diff, works after commit)
|
|
93
|
-
* 3. HEAD (unstaged/staged changes, works before commit)
|
|
94
|
-
* Returns null if git is unavailable or no changes found.
|
|
120
|
+
* Get the union of committed, staged, unstaged, and untracked changed lines.
|
|
121
|
+
* A known empty union is authoritative; null means a required Git source was
|
|
122
|
+
* unavailable or malformed and callers must classify findings fail-closed.
|
|
95
123
|
*/
|
|
96
|
-
export declare function getChangedLineRanges(directory: string): Promise<Map<string, Set<number>> | null>;
|
|
124
|
+
export declare function getChangedLineRanges(directory: string, abortSignal?: AbortSignal, requestedFiles?: string[]): Promise<Map<string, Set<number>> | null>;
|
|
97
125
|
/**
|
|
98
126
|
* Classify SAST findings as "new" (on changed lines) or "pre-existing" (unchanged lines).
|
|
99
127
|
* A finding is "new" if its file+line intersects the changed line ranges from git diff.
|
|
@@ -108,7 +136,7 @@ export declare function classifySastFindings(findings: SastScanFinding[], change
|
|
|
108
136
|
* @param input - The pre-check batch input
|
|
109
137
|
* @param workspaceDir - Optional workspace directory for traversal validation (injected project root from createSwarmTool, or input.directory)
|
|
110
138
|
*/
|
|
111
|
-
export declare function runPreCheckBatch(input: PreCheckBatchInput, workspaceDir?: string, contextDir?: string): Promise<PreCheckBatchResult>;
|
|
139
|
+
export declare function runPreCheckBatch(input: PreCheckBatchInput, workspaceDir?: string, contextDir?: string, abortSignal?: AbortSignal): Promise<PreCheckBatchResult>;
|
|
112
140
|
/**
|
|
113
141
|
* Pre-check batch tool - runs 4 verification tools in parallel
|
|
114
142
|
* Returns unified result with gates_passed status
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { tool } from '@opencode-ai/plugin';
|
|
2
2
|
import type { QualityBudgetConfig } from '../config/schema';
|
|
3
|
-
import { type QualityMetrics, type QualityViolation } from '../quality/metrics';
|
|
3
|
+
import { computeQualityMetrics, type QualityMetrics, type QualityViolation } from '../quality/metrics';
|
|
4
4
|
export interface QualityBudgetInput {
|
|
5
5
|
changed_files: string[];
|
|
6
6
|
config?: Partial<QualityBudgetConfig>;
|
|
@@ -22,7 +22,7 @@ export interface QualityBudgetResult {
|
|
|
22
22
|
* Computes quality metrics (complexity, API, duplication, test ratio)
|
|
23
23
|
* and compares against configured thresholds to ensure code quality.
|
|
24
24
|
*/
|
|
25
|
-
export declare function qualityBudget(input: QualityBudgetInput, directory: string): Promise<QualityBudgetResult>;
|
|
25
|
+
export declare function qualityBudget(input: QualityBudgetInput, directory: string, abortSignal?: AbortSignal): Promise<QualityBudgetResult>;
|
|
26
26
|
export declare const quality_budget: ReturnType<typeof tool>;
|
|
27
27
|
/**
|
|
28
28
|
* DI seam for testability. Contains all test-mocked exports.
|
|
@@ -30,4 +30,5 @@ export declare const quality_budget: ReturnType<typeof tool>;
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const _internals: {
|
|
32
32
|
qualityBudget: typeof qualityBudget;
|
|
33
|
+
computeQualityMetrics: typeof computeQualityMetrics;
|
|
33
34
|
};
|
|
@@ -23,10 +23,10 @@ export interface ResolveError {
|
|
|
23
23
|
*
|
|
24
24
|
* NOTE: This function intentionally does NOT use realpathSync for the resolved path
|
|
25
25
|
* to avoid Windows 8.3 short filename issues. Symlink-based subdirectory bypasses
|
|
26
|
-
* through this coarse filter are caught by the
|
|
27
|
-
*
|
|
28
|
-
* defense-in-depth pair: resolveWorkingDirectory is the fast entry filter
|
|
29
|
-
*
|
|
26
|
+
* through this coarse filter are caught by the shared canonical project-root
|
|
27
|
+
* assertion at evidence, plan, and scope persistence sinks. These checks form a
|
|
28
|
+
* defense-in-depth pair: resolveWorkingDirectory is the fast entry filter and the
|
|
29
|
+
* persistence assertion is authoritative at write time.
|
|
30
30
|
*
|
|
31
31
|
* Priority: explicit working_directory param > injected directory (from createSwarmTool).
|
|
32
32
|
*
|
|
@@ -116,6 +116,7 @@ export declare function assignOccurrenceIndices(findings: SastScanFinding[], dir
|
|
|
116
116
|
*/
|
|
117
117
|
export declare function captureOrMergeBaseline(directory: string, phase: number, findings: SastScanFinding[], engine: 'tier_a' | 'tier_a+tier_b', scannedFiles: string[], opts?: {
|
|
118
118
|
force?: boolean;
|
|
119
|
+
abortSignal?: AbortSignal;
|
|
119
120
|
}): Promise<CaptureResult>;
|
|
120
121
|
/**
|
|
121
122
|
* Load the SAST baseline for a given phase.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import type { ToolDefinition } from '@opencode-ai/plugin/tool';
|
|
6
6
|
import type { PluginConfig } from '../config';
|
|
7
7
|
import type { EvidenceVerdict } from '../config/evidence-schema';
|
|
8
|
-
import { isSemgrepAvailable, runSemgrep } from '../sast/semgrep';
|
|
8
|
+
import { checkSemgrepAvailable, isSemgrepAvailable, runSemgrep } from '../sast/semgrep';
|
|
9
9
|
export interface SastScanInput {
|
|
10
10
|
/** List of files to scan */
|
|
11
11
|
changed_files: string[];
|
|
@@ -32,6 +32,8 @@ export interface SastScanInput {
|
|
|
32
32
|
* baseline diff mode: only findings absent from the phase baseline fail.
|
|
33
33
|
*/
|
|
34
34
|
phase?: number;
|
|
35
|
+
/** Host/tool cancellation propagated to optional external scanners. */
|
|
36
|
+
abort_signal?: AbortSignal;
|
|
35
37
|
}
|
|
36
38
|
export interface SastScanResult {
|
|
37
39
|
/** Overall verdict: pass if no findings above threshold, fail otherwise */
|
|
@@ -101,6 +103,7 @@ export declare const sast_scan: ToolDefinition;
|
|
|
101
103
|
export declare const _internals: {
|
|
102
104
|
sastScan: typeof sastScan;
|
|
103
105
|
sast_scan: typeof sast_scan;
|
|
106
|
+
checkSemgrepAvailable: typeof checkSemgrepAvailable;
|
|
104
107
|
isSemgrepAvailable: typeof isSemgrepAvailable;
|
|
105
108
|
runSemgrep: typeof runSemgrep;
|
|
106
109
|
};
|
|
@@ -67,10 +67,10 @@ export declare const _internals: {
|
|
|
67
67
|
now: () => number;
|
|
68
68
|
yieldToEventLoop: typeof yieldToEventLoop;
|
|
69
69
|
openFile: typeof fs.openSync;
|
|
70
|
-
fstatFile:
|
|
70
|
+
fstatFile: (fd: number) => fs.BigIntStats;
|
|
71
71
|
readFileChunk: typeof fs.readSync;
|
|
72
72
|
closeFile: typeof fs.closeSync;
|
|
73
|
-
lstatFile:
|
|
73
|
+
lstatFile: (path: fs.PathLike) => fs.BigIntStats;
|
|
74
74
|
closeDirectory: (directory: fs.Dir) => void;
|
|
75
75
|
};
|
|
76
76
|
export {};
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* Tool to configure the QA gate profile for the current plan.
|
|
3
3
|
*
|
|
4
4
|
* Architect-only: invoked during the QA GATE SELECTION phase of brainstorm
|
|
5
|
-
* mode (or equivalent).
|
|
6
|
-
*
|
|
5
|
+
* mode (or equivalent). The initial selection may override defaults; after a
|
|
6
|
+
* profile exists, updates are ratchet-tighter and cannot disable enabled gates.
|
|
7
|
+
* Rejects all writes once the profile is locked.
|
|
7
8
|
*
|
|
8
|
-
* Creates the profile with defaults
|
|
9
|
-
* partial update.
|
|
9
|
+
* Creates the profile with defaults plus the initial selection if missing,
|
|
10
|
+
* then always applies the requested partial update through the normal ratchet.
|
|
10
11
|
*/
|
|
11
12
|
import type { tool } from '@opencode-ai/plugin';
|
|
12
13
|
export interface SetQaGatesArgs {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* - `bunHash` uses Node's `xxhash` via `Bun.hash`'s default algorithm when
|
|
25
25
|
* present and falls back to a stable djb2-derived 32-bit hash on Node.
|
|
26
26
|
*/
|
|
27
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
27
28
|
/**
|
|
28
29
|
* Whether the current runtime is Bun. Cached at first call — every subsequent
|
|
29
30
|
* call is a single property access.
|
|
@@ -86,6 +87,8 @@ export interface BunCompatSpawnOptions {
|
|
|
86
87
|
stdout?: 'inherit' | 'ignore' | 'pipe';
|
|
87
88
|
stderr?: 'inherit' | 'ignore' | 'pipe';
|
|
88
89
|
timeout?: number;
|
|
90
|
+
/** Preserve the caller's exact Windows argv quoting (required for cmd.exe /c). */
|
|
91
|
+
windowsVerbatimArguments?: boolean;
|
|
89
92
|
/**
|
|
90
93
|
* When true, spawn the child as its own process-group leader (Node path:
|
|
91
94
|
* `detached`) and kill the entire descendant tree on `kill()`/timeout
|
|
@@ -113,8 +116,24 @@ export interface BunCompatSubprocess {
|
|
|
113
116
|
readonly stderr: BunCompatStream;
|
|
114
117
|
readonly exited: Promise<number>;
|
|
115
118
|
exitCode: number | null;
|
|
119
|
+
readonly signalCode?: NodeJS.Signals | null;
|
|
120
|
+
/**
|
|
121
|
+
* Asynchronous process-creation failure reported by Node's ChildProcess
|
|
122
|
+
* `error` event (for example ENOENT). Bun reports equivalent failures by
|
|
123
|
+
* throwing from `Bun.spawn`, so this is populated only by the Node fallback.
|
|
124
|
+
*/
|
|
125
|
+
readonly spawnError?: Error | null;
|
|
116
126
|
kill(signal?: NodeJS.Signals | number): void;
|
|
127
|
+
/** Awaitable best-effort descendant-tree termination for bounded runners. */
|
|
128
|
+
killTree?(signal?: NodeJS.Signals | number): Promise<void>;
|
|
117
129
|
}
|
|
130
|
+
declare function createProcessTreeKiller(pid: number | undefined, directKill: (signal?: NodeJS.Signals | number) => void, wasDetached: boolean): (signal?: NodeJS.Signals | number) => Promise<void>;
|
|
131
|
+
export declare const _internals: {
|
|
132
|
+
platform: () => NodeJS.Platform;
|
|
133
|
+
cwd: () => string;
|
|
134
|
+
spawnTaskkill: (args: string[], options: Parameters<typeof nodeSpawn>[2]) => import("node:child_process").ChildProcess;
|
|
135
|
+
createProcessTreeKiller: typeof createProcessTreeKiller;
|
|
136
|
+
};
|
|
118
137
|
/**
|
|
119
138
|
* Merges `envOverrides` into the base env (or `process.env` if no base env
|
|
120
139
|
* is given) and returns the resulting record.
|
|
@@ -150,3 +169,4 @@ export declare function bunSpawnSync(cmd: string[] | {
|
|
|
150
169
|
stdin?: string | Uint8Array;
|
|
151
170
|
timeout?: number;
|
|
152
171
|
}, options?: BunCompatSpawnOptions): BunCompatSyncResult;
|
|
172
|
+
export {};
|
|
@@ -8,6 +8,8 @@ export interface ExternalToolRunOptions {
|
|
|
8
8
|
maxStderrBytes: number;
|
|
9
9
|
env?: Record<string, string | undefined>;
|
|
10
10
|
abortSignal?: AbortSignal;
|
|
11
|
+
/** Preserve an already-quoted Windows command line, such as constrained cmd.exe /c. */
|
|
12
|
+
windowsVerbatimArguments?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export interface ExternalToolRunResult {
|
|
13
15
|
status: 'completed' | 'timeout' | 'cancelled' | 'spawn-error';
|
|
@@ -19,8 +21,16 @@ export interface ExternalToolRunResult {
|
|
|
19
21
|
message?: string;
|
|
20
22
|
}
|
|
21
23
|
export declare function resolveExecutableFromPath(names: string[], envPath?: string, platform?: NodeJS.Platform): string | null;
|
|
24
|
+
declare function clampTimeoutMs(timeoutMs: number): number;
|
|
25
|
+
declare function computeSpawnTimeoutMs(timeoutMs: number): number;
|
|
22
26
|
export declare function runExternalTool(options: ExternalToolRunOptions): Promise<ExternalToolRunResult>;
|
|
23
27
|
export declare const _internals: {
|
|
24
28
|
bunSpawn: typeof bunSpawn;
|
|
25
29
|
platform: () => NodeJS.Platform;
|
|
30
|
+
now: () => number;
|
|
31
|
+
setTimeout: typeof setTimeout;
|
|
32
|
+
clearTimeout: typeof clearTimeout;
|
|
33
|
+
clampTimeoutMs: typeof clampTimeoutMs;
|
|
34
|
+
computeSpawnTimeoutMs: typeof computeSpawnTimeoutMs;
|
|
26
35
|
};
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
/** Maximum depth to walk up the directory tree before failing closed. */
|
|
3
|
+
export declare const MAX_PROJECT_ROOT_DEPTH = 20;
|
|
4
|
+
/** File/directory names that indicate a real ancestor project root. */
|
|
5
|
+
export declare const PROJECT_ROOT_INDICATORS: readonly ["package.json", ".git", ".opencode", "Cargo.toml", "go.mod", "pyproject.toml", "Gemfile", "composer.json", "pom.xml", "build.gradle", "CMakeLists.txt"];
|
|
6
|
+
/**
|
|
7
|
+
* Return whether `directory` directly declares its own project boundary.
|
|
8
|
+
*
|
|
9
|
+
* Markers are local declarations, not verified Git metadata. A direct `.git`
|
|
10
|
+
* file/directory covers repositories, linked worktrees, and submodules; a
|
|
11
|
+
* direct `.opencode` directory is the manual opt-in. `lstatSync` is deliberate:
|
|
12
|
+
* marker symlinks/junctions do not grant an exemption. Missing, inaccessible,
|
|
13
|
+
* or ambiguous markers fail closed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function hasExplicitProjectBoundary(directory: unknown): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Test whether `candidate` is a strict lexical descendant of `root` using the
|
|
18
|
+
* host platform's path semantics (including case-insensitive Windows paths).
|
|
19
|
+
*/
|
|
20
|
+
export declare function isStrictPathDescendant(candidate: unknown, root: unknown): boolean;
|
|
21
|
+
type ProjectRootProbeDependencies = Pick<typeof fs, 'realpathSync' | 'statSync'>;
|
|
22
|
+
/**
|
|
23
|
+
* Authoritative write-time project-root assertion shared by persistence sinks.
|
|
24
|
+
*
|
|
25
|
+
* Direct boundary markers exempt a nested project from ancestor checks. Ordinary
|
|
26
|
+
* descendants are rejected when an ancestor contains both `.swarm/` and a
|
|
27
|
+
* project indicator. Ambiguous ancestor state fails closed.
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertProjectRoot(directory: string, dependencies?: ProjectRootProbeDependencies, artifactLabel?: string): void;
|
|
30
|
+
/** Narrow filesystem seam for deterministic marker error tests. */
|
|
31
|
+
export declare const _internals: {
|
|
32
|
+
lstatSync: typeof fs.lstatSync;
|
|
33
|
+
};
|
|
34
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.139.
|
|
3
|
+
"version": "7.139.4",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
createCuratorLLMDelegate
|
|
4
|
-
} from "./index-a7nh382r.js";
|
|
5
|
-
import"./index-vm4xw9z3.js";
|
|
6
|
-
import"./index-wrt6m5ze.js";
|
|
7
|
-
import"./index-y64jv2pe.js";
|
|
8
|
-
import"./index-y47dwge1.js";
|
|
9
|
-
import"./index-0wp67gqj.js";
|
|
10
|
-
import"./index-s608d3hw.js";
|
|
11
|
-
import"./index-y8552snf.js";
|
|
12
|
-
import"./index-4905hd2m.js";
|
|
13
|
-
import"./index-134d35c1.js";
|
|
14
|
-
import"./index-ktagrqxw.js";
|
|
15
|
-
import"./index-w71cq27a.js";
|
|
16
|
-
import"./index-6w1re1qn.js";
|
|
17
|
-
import"./index-6mjf4vr1.js";
|
|
18
|
-
import"./index-c8s9a3zh.js";
|
|
19
|
-
import"./index-9ss2m4rs.js";
|
|
20
|
-
import"./index-wsdnttf4.js";
|
|
21
|
-
import"./index-5w7ekpy3.js";
|
|
22
|
-
import"./index-ffpmqx30.js";
|
|
23
|
-
import"./index-3radty3f.js";
|
|
24
|
-
import"./index-rtry5xyf.js";
|
|
25
|
-
import"./index-cyw81ngh.js";
|
|
26
|
-
import"./index-e9tx99ds.js";
|
|
27
|
-
import"./index-ae75rja9.js";
|
|
28
|
-
import"./index-668dpw5e.js";
|
|
29
|
-
import"./index-gvhvz176.js";
|
|
30
|
-
import"./index-q11t5erh.js";
|
|
31
|
-
import"./index-gprxjmm7.js";
|
|
32
|
-
import"./index-n832052r.js";
|
|
33
|
-
import"./index-8p9pasnp.js";
|
|
34
|
-
import"./index-bk5tah7q.js";
|
|
35
|
-
import"./index-8fwhhayc.js";
|
|
36
|
-
import"./index-q1exe2b3.js";
|
|
37
|
-
import"./index-5zyk8qgv.js";
|
|
38
|
-
import"./index-3eddtgxt.js";
|
|
39
|
-
import"./index-556ja8an.js";
|
|
40
|
-
import"./index-4xbyy6aw.js";
|
|
41
|
-
import"./index-1kz6da87.js";
|
|
42
|
-
import"./index-q7ezzgwq.js";
|
|
43
|
-
import"./index-b8zgtz81.js";
|
|
44
|
-
import"./index-a12906mj.js";
|
|
45
|
-
import"./index-4rhhvd1a.js";
|
|
46
|
-
import"./index-3jcyn8g6.js";
|
|
47
|
-
import"./index-prmb5qfp.js";
|
|
48
|
-
import"./index-x9q4bbhd.js";
|
|
49
|
-
import"./index-ed5ykebp.js";
|
|
50
|
-
import"./index-5j6chvj8.js";
|
|
51
|
-
import"./index-7g4c7s5r.js";
|
|
52
|
-
import"./index-a5eba0t8.js";
|
|
53
|
-
import"./index-bpmtbmy9.js";
|
|
54
|
-
import"./index-z6xqpmqg.js";
|
|
55
|
-
import"./index-zjygnfay.js";
|
|
56
|
-
import"./index-y111zefa.js";
|
|
57
|
-
import"./index-zgwm4ryv.js";
|
|
58
|
-
import"./index-a76rekgs.js";
|
|
59
|
-
export {
|
|
60
|
-
createCuratorLLMDelegate
|
|
61
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
handleGuardrailExplain
|
|
4
|
-
} from "./index-6c5f309q.js";
|
|
5
|
-
import"./index-a7nh382r.js";
|
|
6
|
-
import"./index-vm4xw9z3.js";
|
|
7
|
-
import"./index-wrt6m5ze.js";
|
|
8
|
-
import"./index-y64jv2pe.js";
|
|
9
|
-
import"./index-y47dwge1.js";
|
|
10
|
-
import"./index-0wp67gqj.js";
|
|
11
|
-
import"./index-s608d3hw.js";
|
|
12
|
-
import"./index-y8552snf.js";
|
|
13
|
-
import"./index-4905hd2m.js";
|
|
14
|
-
import"./index-134d35c1.js";
|
|
15
|
-
import"./index-ktagrqxw.js";
|
|
16
|
-
import"./index-w71cq27a.js";
|
|
17
|
-
import"./index-6w1re1qn.js";
|
|
18
|
-
import"./index-6mjf4vr1.js";
|
|
19
|
-
import"./index-c8s9a3zh.js";
|
|
20
|
-
import"./index-9ss2m4rs.js";
|
|
21
|
-
import"./index-wsdnttf4.js";
|
|
22
|
-
import"./index-5w7ekpy3.js";
|
|
23
|
-
import"./index-ffpmqx30.js";
|
|
24
|
-
import"./index-3radty3f.js";
|
|
25
|
-
import"./index-rtry5xyf.js";
|
|
26
|
-
import"./index-cyw81ngh.js";
|
|
27
|
-
import"./index-e9tx99ds.js";
|
|
28
|
-
import"./index-ae75rja9.js";
|
|
29
|
-
import"./index-668dpw5e.js";
|
|
30
|
-
import"./index-gvhvz176.js";
|
|
31
|
-
import"./index-q11t5erh.js";
|
|
32
|
-
import"./index-gprxjmm7.js";
|
|
33
|
-
import"./index-n832052r.js";
|
|
34
|
-
import"./index-8p9pasnp.js";
|
|
35
|
-
import"./index-bk5tah7q.js";
|
|
36
|
-
import"./index-8fwhhayc.js";
|
|
37
|
-
import"./index-q1exe2b3.js";
|
|
38
|
-
import"./index-5zyk8qgv.js";
|
|
39
|
-
import"./index-3eddtgxt.js";
|
|
40
|
-
import"./index-556ja8an.js";
|
|
41
|
-
import"./index-4xbyy6aw.js";
|
|
42
|
-
import"./index-1kz6da87.js";
|
|
43
|
-
import"./index-q7ezzgwq.js";
|
|
44
|
-
import"./index-b8zgtz81.js";
|
|
45
|
-
import"./index-a12906mj.js";
|
|
46
|
-
import"./index-4rhhvd1a.js";
|
|
47
|
-
import"./index-3jcyn8g6.js";
|
|
48
|
-
import"./index-prmb5qfp.js";
|
|
49
|
-
import"./index-x9q4bbhd.js";
|
|
50
|
-
import"./index-ed5ykebp.js";
|
|
51
|
-
import"./index-5j6chvj8.js";
|
|
52
|
-
import"./index-7g4c7s5r.js";
|
|
53
|
-
import"./index-a5eba0t8.js";
|
|
54
|
-
import"./index-bpmtbmy9.js";
|
|
55
|
-
import"./index-z6xqpmqg.js";
|
|
56
|
-
import"./index-zjygnfay.js";
|
|
57
|
-
import"./index-y111zefa.js";
|
|
58
|
-
import"./index-zgwm4ryv.js";
|
|
59
|
-
import"./index-a76rekgs.js";
|
|
60
|
-
export {
|
|
61
|
-
handleGuardrailExplain
|
|
62
|
-
};
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import {
|
|
3
|
-
require_proper_lockfile
|
|
4
|
-
} from "./index-7g4c7s5r.js";
|
|
5
|
-
import {
|
|
6
|
-
emit
|
|
7
|
-
} from "./index-a5eba0t8.js";
|
|
8
|
-
import {
|
|
9
|
-
__toESM
|
|
10
|
-
} from "./index-a76rekgs.js";
|
|
11
|
-
|
|
12
|
-
// src/parallel/file-locks.ts
|
|
13
|
-
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
14
|
-
import * as crypto from "crypto";
|
|
15
|
-
import * as fs from "fs";
|
|
16
|
-
import * as path from "path";
|
|
17
|
-
var LOCKS_DIR = ".swarm/locks";
|
|
18
|
-
var LOCK_TIMEOUT_MS = 5 * 60 * 1000;
|
|
19
|
-
var _internals = {
|
|
20
|
-
tryAcquireLock,
|
|
21
|
-
writeFile: fs.promises.writeFile
|
|
22
|
-
};
|
|
23
|
-
function getLockFilePath(directory, filePath) {
|
|
24
|
-
const normalized = path.resolve(directory, filePath);
|
|
25
|
-
const baseDir = path.resolve(directory) + path.sep;
|
|
26
|
-
const pathOk = process.platform === "win32" ? normalized.toLowerCase().startsWith(baseDir.toLowerCase()) : normalized.startsWith(baseDir);
|
|
27
|
-
if (!pathOk) {
|
|
28
|
-
throw new Error("Invalid file path: path traversal not allowed");
|
|
29
|
-
}
|
|
30
|
-
const pathForHash = process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
31
|
-
const hash = crypto.createHash("sha256").update(pathForHash).digest("hex");
|
|
32
|
-
const lockPath = path.join(directory, LOCKS_DIR, `${hash}.lock`);
|
|
33
|
-
const legacyPaths = [pathForHash];
|
|
34
|
-
if (process.platform === "win32" && normalized !== pathForHash) {
|
|
35
|
-
legacyPaths.push(normalized);
|
|
36
|
-
}
|
|
37
|
-
for (const legacyPath of legacyPaths) {
|
|
38
|
-
const oldHash = Buffer.from(legacyPath).toString("base64").replace(/[/+=]/g, "_");
|
|
39
|
-
const oldLockPath = path.join(directory, LOCKS_DIR, `${oldHash}.lock`);
|
|
40
|
-
if (fs.existsSync(oldLockPath)) {
|
|
41
|
-
return oldLockPath;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return lockPath;
|
|
45
|
-
}
|
|
46
|
-
async function tryAcquireLock(directory, filePath, agent, taskId) {
|
|
47
|
-
const lockPath = getLockFilePath(directory, filePath);
|
|
48
|
-
const locksDir = path.dirname(lockPath);
|
|
49
|
-
if (!fs.existsSync(locksDir)) {
|
|
50
|
-
fs.mkdirSync(locksDir, { recursive: true });
|
|
51
|
-
}
|
|
52
|
-
if (!fs.existsSync(lockPath)) {
|
|
53
|
-
fs.writeFileSync(lockPath, "", "utf-8");
|
|
54
|
-
}
|
|
55
|
-
let release;
|
|
56
|
-
try {
|
|
57
|
-
release = await import_proper_lockfile.default.lock(lockPath, {
|
|
58
|
-
stale: LOCK_TIMEOUT_MS,
|
|
59
|
-
retries: {
|
|
60
|
-
retries: 5,
|
|
61
|
-
minTimeout: 10,
|
|
62
|
-
maxTimeout: 500,
|
|
63
|
-
factor: 2
|
|
64
|
-
},
|
|
65
|
-
realpath: false
|
|
66
|
-
});
|
|
67
|
-
} catch (err) {
|
|
68
|
-
const code = err.code;
|
|
69
|
-
if (code === "ELOCKED" || code === "EEXIST") {
|
|
70
|
-
return { acquired: false };
|
|
71
|
-
}
|
|
72
|
-
throw err;
|
|
73
|
-
}
|
|
74
|
-
const lock = {
|
|
75
|
-
filePath,
|
|
76
|
-
agent,
|
|
77
|
-
taskId,
|
|
78
|
-
timestamp: new Date().toISOString(),
|
|
79
|
-
expiresAt: Date.now() + LOCK_TIMEOUT_MS,
|
|
80
|
-
_release: release
|
|
81
|
-
};
|
|
82
|
-
return { acquired: true, lock };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// src/evidence/lock.ts
|
|
86
|
-
class EvidenceLockTimeoutError extends Error {
|
|
87
|
-
directory;
|
|
88
|
-
evidencePath;
|
|
89
|
-
agent;
|
|
90
|
-
taskId;
|
|
91
|
-
constructor(directory, evidencePath, agent, taskId, timeoutMs) {
|
|
92
|
-
super(`Evidence lock timeout after ${timeoutMs}ms for ${evidencePath} (agent=${agent}, task=${taskId})`);
|
|
93
|
-
this.name = "EvidenceLockTimeoutError";
|
|
94
|
-
this.directory = directory;
|
|
95
|
-
this.evidencePath = evidencePath;
|
|
96
|
-
this.agent = agent;
|
|
97
|
-
this.taskId = taskId;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
var BACKOFF_START_MS = 50;
|
|
101
|
-
var BACKOFF_MAX_MS = 2000;
|
|
102
|
-
var BACKOFF_JITTER_RATIO = 0.25;
|
|
103
|
-
function backoffMs(attempt) {
|
|
104
|
-
const base = Math.min(BACKOFF_START_MS * 2 ** attempt, BACKOFF_MAX_MS);
|
|
105
|
-
const jitter = base * BACKOFF_JITTER_RATIO * (Math.random() * 2 - 1);
|
|
106
|
-
return Math.max(1, Math.round(base + jitter));
|
|
107
|
-
}
|
|
108
|
-
async function withEvidenceLock(directory, evidencePath, agent, taskId, fn, timeoutMs = 60000) {
|
|
109
|
-
const deadline = Date.now() + timeoutMs;
|
|
110
|
-
let attempt = 0;
|
|
111
|
-
while (true) {
|
|
112
|
-
const result = await tryAcquireLock(directory, evidencePath, agent, taskId);
|
|
113
|
-
if (result.acquired) {
|
|
114
|
-
const lock = result.lock;
|
|
115
|
-
if (attempt > 0) {
|
|
116
|
-
emit("evidence_lock_stale_recovered", {
|
|
117
|
-
directory,
|
|
118
|
-
evidencePath,
|
|
119
|
-
agent,
|
|
120
|
-
taskId,
|
|
121
|
-
attempt
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
emit("evidence_lock_acquired", {
|
|
125
|
-
directory,
|
|
126
|
-
evidencePath,
|
|
127
|
-
agent,
|
|
128
|
-
taskId,
|
|
129
|
-
attempt
|
|
130
|
-
});
|
|
131
|
-
try {
|
|
132
|
-
return await fn();
|
|
133
|
-
} finally {
|
|
134
|
-
if (lock._release) {
|
|
135
|
-
try {
|
|
136
|
-
await lock._release();
|
|
137
|
-
} catch {}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if (Date.now() >= deadline) {
|
|
142
|
-
throw new EvidenceLockTimeoutError(directory, evidencePath, agent, taskId, timeoutMs);
|
|
143
|
-
}
|
|
144
|
-
emit("evidence_lock_contended", {
|
|
145
|
-
directory,
|
|
146
|
-
evidencePath,
|
|
147
|
-
agent,
|
|
148
|
-
taskId,
|
|
149
|
-
attempt
|
|
150
|
-
});
|
|
151
|
-
const delay = Math.min(backoffMs(attempt), deadline - Date.now());
|
|
152
|
-
if (delay > 0) {
|
|
153
|
-
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
154
|
-
}
|
|
155
|
-
attempt++;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export { tryAcquireLock, withEvidenceLock };
|