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.
Files changed (110) hide show
  1. package/.opencode/skills/phase-wrap/SKILL.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/background/stage-b-gates.d.ts +5 -1
  4. package/dist/background/task-envelope.d.ts +4 -4
  5. package/dist/cli/{config-doctor-hrb61yqe.js → config-doctor-whxr386t.js} +6 -6
  6. package/dist/cli/{core-g2dfh9fq.js → core-aj5g7an6.js} +5 -5
  7. package/dist/cli/{curation-policy-4tp0mbcb.js → curation-policy-anym2y3v.js} +8 -8
  8. package/dist/cli/{curator-drift-vfh07mqy.js → curator-drift-49p3jnte.js} +7 -7
  9. package/dist/cli/{curator-vpcs1p1v.js → curator-e8cvb55d.js} +41 -41
  10. package/dist/cli/curator-llm-factory-h9xbpgmw.js +61 -0
  11. package/dist/cli/{dispatch-b1fge4xk.js → dispatch-2s23fbcs.js} +4 -4
  12. package/dist/cli/{evidence-summary-service-kzxr71yd.js → evidence-summary-service-g82bsjqa.js} +16 -16
  13. package/dist/cli/{gate-evidence-z2b1ymnw.js → gate-evidence-72cgrvs2.js} +6 -5
  14. package/dist/cli/guardrail-explain-0be7msvq.js +62 -0
  15. package/dist/cli/{guardrail-log-2ftew0p3.js → guardrail-log-9mm5443g.js} +9 -9
  16. package/dist/cli/{hive-promoter-mpf0cfkk.js → hive-promoter-nnzs5x1r.js} +41 -41
  17. package/dist/cli/{index-w71cq27a.js → index-0e95eck5.js} +5 -5
  18. package/dist/cli/{index-5zyk8qgv.js → index-0xkjhgrf.js} +5 -5
  19. package/dist/cli/{index-q7ezzgwq.js → index-1kyex7z2.js} +1 -1
  20. package/dist/cli/{index-668dpw5e.js → index-33skgk1a.js} +1 -1
  21. package/dist/cli/{index-vm4xw9z3.js → index-41hkt36g.js} +2 -2
  22. package/dist/cli/{index-y111zefa.js → index-4nt52yr9.js} +80 -31
  23. package/dist/cli/{index-3jcyn8g6.js → index-4wjk296r.js} +1 -1
  24. package/dist/cli/{index-3radty3f.js → index-5azdnaty.js} +2 -2
  25. package/dist/cli/{index-8p9pasnp.js → index-5s23pfsy.js} +8 -8
  26. package/dist/cli/{index-5w7ekpy3.js → index-5z2xps64.js} +2 -2
  27. package/dist/cli/{index-0wp67gqj.js → index-6nzmp937.js} +61 -111
  28. package/dist/cli/{index-gvhvz176.js → index-6r522srn.js} +2 -2
  29. package/dist/cli/{index-4xbyy6aw.js → index-6rxgb5r9.js} +10 -6
  30. package/dist/cli/{index-cyw81ngh.js → index-6vh6vrnk.js} +10 -10
  31. package/dist/cli/{index-a12906mj.js → index-6z0a940s.js} +8 -8
  32. package/dist/cli/{index-wsdnttf4.js → index-74hpm6sh.js} +1 -1
  33. package/dist/cli/{index-6w1re1qn.js → index-9cdj4020.js} +6 -6
  34. package/dist/cli/{index-y47dwge1.js → index-e1k9vpqn.js} +5 -5
  35. package/dist/cli/{index-y64jv2pe.js → index-ejbcpbzp.js} +7 -7
  36. package/dist/cli/{index-6c5f309q.js → index-gfmrw2f5.js} +2 -2
  37. package/dist/cli/{index-prmb5qfp.js → index-j77frjq8.js} +7 -7
  38. package/dist/cli/{index-ffpmqx30.js → index-jnfyxeap.js} +4 -4
  39. package/dist/cli/{index-e9tx99ds.js → index-k41dn8me.js} +3 -3
  40. package/dist/cli/{index-x9q4bbhd.js → index-k46me75h.js} +4 -4
  41. package/dist/cli/{index-s608d3hw.js → index-nrx08gcr.js} +6 -2
  42. package/dist/cli/{index-ktagrqxw.js → index-pg84msyc.js} +7 -7
  43. package/dist/cli/{index-a5eba0t8.js → index-rsrx77fg.js} +6 -6
  44. package/dist/cli/index-s0qc4gj6.js +298 -0
  45. package/dist/cli/{index-q11t5erh.js → index-s58vghgj.js} +7 -7
  46. package/dist/cli/{index-se8xc78k.js → index-sa15nfgg.js} +45 -45
  47. package/dist/cli/{index-wrt6m5ze.js → index-sd657fkp.js} +291 -75
  48. package/dist/cli/{index-yr6x707c.js → index-vfsqpcz6.js} +16 -16
  49. package/dist/cli/{index-a7nh382r.js → index-vyqd1hzm.js} +20593 -19882
  50. package/dist/cli/{index-8gftfvpp.js → index-xb1zq933.js} +1 -1
  51. package/dist/cli/{index-3eddtgxt.js → index-xmhhhjjw.js} +39 -4
  52. package/dist/cli/index.js +43 -43
  53. package/dist/cli/{knowledge-escalator-n9pmx4qr.js → knowledge-escalator-a6z30y9p.js} +10 -10
  54. package/dist/cli/{knowledge-events-raevm18w.js → knowledge-events-deq0ds8e.js} +7 -7
  55. package/dist/cli/{knowledge-link-3tq8w6gs.js → knowledge-link-bmbatt8s.js} +6 -6
  56. package/dist/cli/{knowledge-store-bcfqz8fr.js → knowledge-store-vdr19mnq.js} +8 -8
  57. package/dist/cli/{knowledge-validator-jxqj96cx.js → knowledge-validator-5hgacnrf.js} +11 -11
  58. package/dist/cli/{pending-delegations-tmyf18p4.js → pending-delegations-7ayryxbg.js} +8 -8
  59. package/dist/cli/{pr-subscriptions-hhx6yk24.js → pr-subscriptions-w5y08ebc.js} +8 -8
  60. package/dist/cli/{runner-w30gazew.js → runner-h7vmgkth.js} +7 -6
  61. package/dist/cli/{scan-cursor-ah5swtyh.js → scan-cursor-d6qcg9hr.js} +9 -9
  62. package/dist/cli/{schema-f7jgrtxj.js → schema-y1zekrag.js} +3 -3
  63. package/dist/cli/{scope-persistence-3f0d4fwv.js → scope-persistence-tj6qway9.js} +7 -7
  64. package/dist/cli/{skill-generator-hp7as46c.js → skill-generator-bw8xhzzn.js} +13 -13
  65. package/dist/cli/{task-envelope-qn0qtnh0.js → task-envelope-jp2fdsvn.js} +11 -8
  66. package/dist/cli/{telemetry-4tgrfhaz.js → telemetry-62cn5t24.js} +1 -1
  67. package/dist/cli/{workspace-snapshot-h5rzw37b.js → workspace-snapshot-w3tg4ne5.js} +2 -2
  68. package/dist/cli/{worktree-collision-ownership-vexb0b6r.js → worktree-collision-ownership-hs5c2qzp.js} +9 -9
  69. package/dist/commands/approve-plan-critic.d.ts +2 -2
  70. package/dist/commands/registry.d.ts +1 -1
  71. package/dist/config/agent-model.d.ts +35 -0
  72. package/dist/db/qa-gate-profile.d.ts +11 -3
  73. package/dist/evidence/manager.d.ts +5 -2
  74. package/dist/evidence/phase-participation.d.ts +44 -0
  75. package/dist/hooks/compaction-customizer.d.ts +30 -2
  76. package/dist/hooks/context-budget.d.ts +1 -1
  77. package/dist/hooks/delegation-gate.d.ts +3 -3
  78. package/dist/hooks/guardrails/index.d.ts +5 -1
  79. package/dist/hooks/guardrails/messages-transform.d.ts +2 -0
  80. package/dist/hooks/guardrails/pre-check-result.d.ts +20 -0
  81. package/dist/index.js +616 -609
  82. package/dist/prm/escalation.d.ts +34 -0
  83. package/dist/prm/index.d.ts +6 -2
  84. package/dist/prm/pattern-detector.d.ts +22 -1
  85. package/dist/prm/types.d.ts +12 -2
  86. package/dist/sast/semgrep.d.ts +15 -32
  87. package/dist/services/compaction-service.d.ts +3 -1
  88. package/dist/session/snapshot-writer.d.ts +1 -0
  89. package/dist/state.d.ts +119 -19
  90. package/dist/summaries/schema.d.ts +2 -2
  91. package/dist/tools/context-status.d.ts +4 -1
  92. package/dist/tools/convene-council.d.ts +1 -1
  93. package/dist/tools/lint.d.ts +48 -22
  94. package/dist/tools/pre-check-batch.d.ts +41 -13
  95. package/dist/tools/quality-budget.d.ts +3 -2
  96. package/dist/tools/resolve-working-directory.d.ts +4 -4
  97. package/dist/tools/sast-baseline.d.ts +1 -0
  98. package/dist/tools/sast-scan.d.ts +4 -1
  99. package/dist/tools/secretscan.d.ts +2 -2
  100. package/dist/tools/set-qa-gates.d.ts +5 -4
  101. package/dist/tools/submit-phase-council-verdicts.d.ts +1 -1
  102. package/dist/tools/write-final-council-evidence.d.ts +1 -1
  103. package/dist/utils/bun-compat.d.ts +20 -0
  104. package/dist/utils/external-tool-runner.d.ts +10 -0
  105. package/dist/utils/project-boundary.d.ts +34 -0
  106. package/package.json +1 -1
  107. package/dist/cli/curator-llm-factory-hvw13hmr.js +0 -61
  108. package/dist/cli/guardrail-explain-k62h3c92.js +0 -62
  109. package/dist/cli/index-5j6chvj8.js +0 -159
  110. 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 type { LintResult } from './lint';
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 changed line ranges for the current branch vs its base.
90
- * Tries three strategies in order:
91
- * 1. merge-base diff against main/master (captures all branch changes, works after commit)
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 write-time validateProjectRoot guard
27
- * in evidence/manager.ts, which DOES use realpathSync. These two functions form a
28
- * defense-in-depth pair: resolveWorkingDirectory is the fast entry filter,
29
- * validateProjectRoot is the authoritative canonical check at write time.
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: typeof fs.fstatSync;
70
+ fstatFile: (fd: number) => fs.BigIntStats;
71
71
  readFileChunk: typeof fs.readSync;
72
72
  closeFile: typeof fs.closeSync;
73
- lstatFile: typeof fs.lstatSync;
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). Ratchet-tighter only cannot disable gates that are
6
- * already enabled. Rejects all writes once the profile is locked.
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 if missing, then applies the requested
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 {
@@ -15,8 +15,8 @@ export declare const ArgsSchema: z.ZodObject<{
15
15
  }>;
16
16
  verdict: z.ZodEnum<{
17
17
  APPROVE: "APPROVE";
18
- CONCERNS: "CONCERNS";
19
18
  REJECT: "REJECT";
19
+ CONCERNS: "CONCERNS";
20
20
  }>;
21
21
  confidence: z.ZodNumber;
22
22
  findings: z.ZodArray<z.ZodObject<{
@@ -16,8 +16,8 @@ export declare const ArgsSchema: z.ZodObject<{
16
16
  }>;
17
17
  verdict: z.ZodEnum<{
18
18
  APPROVE: "APPROVE";
19
- CONCERNS: "CONCERNS";
20
19
  REJECT: "REJECT";
20
+ CONCERNS: "CONCERNS";
21
21
  }>;
22
22
  confidence: z.ZodNumber;
23
23
  findings: z.ZodArray<z.ZodObject<{
@@ -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.2",
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 };
@@ -1,10 +1,10 @@
1
1
  // @bun
2
- import {
3
- init_merge
4
- } from "./index-zjygnfay.js";
5
2
  import {
6
3
  init_logger
7
4
  } from "./index-zgwm4ryv.js";
5
+ import {
6
+ init_merge
7
+ } from "./index-zjygnfay.js";
8
8
 
9
9
  // src/utils/errors.ts
10
10
  class SwarmError extends Error {