opencode-swarm 6.73.0 → 6.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,6 +18,14 @@ export interface PreCheckBatchInput {
18
18
  sast_threshold?: 'low' | 'medium' | 'high' | 'critical';
19
19
  /** Optional plugin config */
20
20
  config?: PluginConfig;
21
+ /**
22
+ * Current phase number (positive integer >= 1).
23
+ * When provided, enables SAST baseline diffing: only findings absent from the
24
+ * phase-scoped baseline (.swarm/evidence/{phase}/sast-baseline.json) drive the
25
+ * fail verdict. Capture the baseline before first coder delegation via sast_scan
26
+ * with capture_baseline:true.
27
+ */
28
+ phase?: number;
21
29
  }
22
30
  export interface ToolResult<T> {
23
31
  /** Whether the tool was executed */
@@ -0,0 +1,126 @@
1
+ /**
2
+ * SAST Baseline — phase-scoped snapshot of pre-existing security findings.
3
+ *
4
+ * Enables baseline diffing so only NEW findings (introduced since baseline capture)
5
+ * drive the fail verdict in subsequent sast_scan calls.
6
+ *
7
+ * Storage: .swarm/evidence/{phase}/sast-baseline.json
8
+ * Mirrors the phase-scoped convention used by write-drift-evidence.ts and
9
+ * write-hallucination-evidence.ts (path.join('evidence', String(phase), filename)
10
+ * passed to validateSwarmPath).
11
+ *
12
+ * Fingerprint format (stable):
13
+ * `${relFile}|${rule_id}|${sha256(3lineWindow).slice(0,16)}|#${occurrenceIndex}`
14
+ *
15
+ * Fingerprint format (unstable — file unreadable or path escapes workspace):
16
+ * `${relFile}|${rule_id}|L${line}|UNSTABLE|#${occurrenceIndex}`
17
+ * Unstable fingerprints are ALWAYS treated as NEW findings (fail-closed).
18
+ *
19
+ * Merge semantics:
20
+ * On every capture for a set of files, ALL prior fingerprints for those files
21
+ * are removed (full prune, engine-agnostic) before inserting current findings.
22
+ * This prevents stale cross-engine fingerprints from causing false-pass verdicts.
23
+ */
24
+ import type { SastScanFinding } from './sast-scan';
25
+ export declare const BASELINE_SCHEMA_VERSION: "1.0.0";
26
+ /** Maximum findings to store in baseline (heuristic — open for tuning). */
27
+ export declare const MAX_BASELINE_FINDINGS = 2000;
28
+ export interface SastBaselineFile {
29
+ schema_version: '1.0.0';
30
+ phase: number;
31
+ created_at: string;
32
+ updated_at: string;
33
+ engine: 'tier_a' | 'tier_a+tier_b';
34
+ /** Canonical relative paths of files indexed into this baseline. */
35
+ files_indexed: string[];
36
+ /** Fingerprint strings for all indexed findings. */
37
+ fingerprints: string[];
38
+ /** Full findings snapshot (for auditing / debugging). */
39
+ findings_snapshot: SastScanFinding[];
40
+ /** True if the snapshot was truncated at MAX_BASELINE_FINDINGS. */
41
+ truncated: boolean;
42
+ }
43
+ export type LoadBaselineResult = {
44
+ status: 'found';
45
+ fingerprints: Set<string>;
46
+ bundle: SastBaselineFile;
47
+ } | {
48
+ status: 'not_found';
49
+ } | {
50
+ status: 'invalid_schema';
51
+ errors: string[];
52
+ };
53
+ export interface FingerprintResult {
54
+ fingerprint: string;
55
+ /** False when the file was unreadable or the path escapes the workspace. */
56
+ stable: boolean;
57
+ }
58
+ export interface IndexedFinding {
59
+ finding: SastScanFinding;
60
+ index: number;
61
+ stable: boolean;
62
+ fingerprint: string;
63
+ }
64
+ export type CaptureResult = {
65
+ status: 'written';
66
+ path: string;
67
+ fingerprint_count: number;
68
+ } | {
69
+ status: 'merged';
70
+ path: string;
71
+ fingerprint_count: number;
72
+ } | {
73
+ status: 'error';
74
+ message: string;
75
+ };
76
+ /**
77
+ * Return the canonical relative path for a finding file.
78
+ * Mirrors the normalization in pre-check-batch.ts classifySastFindings.
79
+ */
80
+ export declare function normalizeFindingPath(directory: string, file: string): string;
81
+ /**
82
+ * Compute a stable or unstable fingerprint for a single finding.
83
+ *
84
+ * Stable uses a 3-line content window (N-1, N, N+1) so the fingerprint
85
+ * survives line-number shifts caused by insertions above the finding.
86
+ *
87
+ * Unstable is produced when the file cannot be read or the path escapes
88
+ * the workspace — such findings are always classified NEW (fail-closed).
89
+ */
90
+ export declare function fingerprintFinding(finding: SastScanFinding, directory: string, occurrenceIndex: number): FingerprintResult;
91
+ /**
92
+ * Assign occurrence indices to a batch of findings.
93
+ *
94
+ * Two findings that produce the same (relFile, rule_id, contentHash) tuple
95
+ * — e.g., copy-pasted vulnerable lines — receive different indices so they
96
+ * get distinct fingerprints and can be individually classified.
97
+ */
98
+ export declare function assignOccurrenceIndices(findings: SastScanFinding[], directory: string): IndexedFinding[];
99
+ /**
100
+ * Capture or merge SAST findings into the phase-scoped baseline.
101
+ *
102
+ * Merge semantics:
103
+ * For every file in `scannedFiles`, ALL prior fingerprints for that file are
104
+ * removed from the baseline before inserting the current scan's fingerprints.
105
+ * This full-prune (engine-agnostic) prevents stale cross-engine entries from
106
+ * causing false-pass verdicts on later full-engine diff scans.
107
+ *
108
+ * Severity threshold:
109
+ * Callers MUST pass ALL findings regardless of severity threshold so the
110
+ * baseline captures the full pre-existing surface. Threshold filtering is
111
+ * the diff caller's responsibility.
112
+ *
113
+ * Idempotency:
114
+ * Calling twice with identical inputs produces an identical baseline file.
115
+ * Calling with a new file set adds/replaces only those files' fingerprints.
116
+ */
117
+ export declare function captureOrMergeBaseline(directory: string, phase: number, findings: SastScanFinding[], engine: 'tier_a' | 'tier_a+tier_b', scannedFiles: string[], opts?: {
118
+ force?: boolean;
119
+ }): Promise<CaptureResult>;
120
+ /**
121
+ * Load the SAST baseline for a given phase.
122
+ *
123
+ * Returns 'not_found' when no baseline file exists (first run for phase).
124
+ * Returns 'invalid_schema' when the file is present but unparseable.
125
+ */
126
+ export declare function loadBaseline(directory: string, phase: number): LoadBaselineResult;
@@ -10,6 +10,21 @@ export interface SastScanInput {
10
10
  changed_files: string[];
11
11
  /** Minimum severity that causes failure (default: 'medium') */
12
12
  severity_threshold?: 'low' | 'medium' | 'high' | 'critical';
13
+ /**
14
+ * When true, capture/merge a phase-scoped baseline snapshot and return
15
+ * status:'baseline_captured'. Subsequent scans with the same phase will
16
+ * diff against this baseline so only NEW findings drive the fail verdict.
17
+ *
18
+ * Capture mode ignores severity_threshold — all severities are recorded.
19
+ * Requires `phase` to be provided.
20
+ */
21
+ capture_baseline?: boolean;
22
+ /**
23
+ * Current phase number (positive integer, >= 1). Required when
24
+ * capture_baseline is true. When provided without capture_baseline, enables
25
+ * baseline diff mode: only findings absent from the phase baseline fail.
26
+ */
27
+ phase?: number;
13
28
  }
14
29
  export interface SastScanResult {
15
30
  /** Overall verdict: pass if no findings above threshold, fail otherwise */
@@ -32,6 +47,18 @@ export interface SastScanResult {
32
47
  low: number;
33
48
  };
34
49
  };
50
+ /** 'baseline_captured' when capture_baseline:true succeeded */
51
+ status?: 'baseline_captured' | 'baseline_merged';
52
+ /** Number of findings recorded in the baseline (capture mode only) */
53
+ finding_count?: number;
54
+ /** Findings NOT present in the baseline (diff mode only) */
55
+ new_findings?: SastScanFinding[];
56
+ /** Findings that match the baseline (diff mode only) */
57
+ pre_existing_findings?: SastScanFinding[];
58
+ /** True when a baseline was loaded and diff mode was active */
59
+ baseline_used?: boolean;
60
+ /** True when pre_existing_findings were truncated to fit result limits */
61
+ truncated_pre_existing?: boolean;
35
62
  }
36
63
  export interface SastScanFinding {
37
64
  rule_id: string;
@@ -21,6 +21,13 @@ export interface SavePlanArgs {
21
21
  }>;
22
22
  }>;
23
23
  working_directory?: string;
24
+ /**
25
+ * When true, all task statuses are reset to 'pending' and existing completed
26
+ * statuses are NOT preserved. Use this when creating a fresh revision of a
27
+ * plan where prior completion state should no longer apply (e.g., re-planning
28
+ * after a failed phase). Defaults to false (existing statuses preserved).
29
+ */
30
+ reset_statuses?: boolean;
24
31
  }
25
32
  /**
26
33
  * Result from executing save_plan
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "6.73.0",
3
+ "version": "6.74.0",
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",