opencode-swarm 7.125.0 → 7.125.1
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-feedback/SKILL.md +11 -127
- package/.opencode/skills/swarm-pr-feedback/references/bot-claim-verification.md +71 -0
- package/.opencode/skills/swarm-pr-feedback/references/operational-gotchas.md +49 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +6 -346
- package/.opencode/skills/swarm-pr-review/references/parser-dry-run.md +235 -0
- package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +103 -0
- package/.opencode/skills/writing-tests/SKILL.md +4 -123
- package/.opencode/skills/writing-tests/references/mock-and-seam-inventory.md +43 -0
- package/dist/cli/{config-doctor-be9sxqx8.js → config-doctor-g3m2q646.js} +2 -2
- package/dist/cli/{curation-policy-52kt6d7t.js → curation-policy-vgbx8530.js} +2 -2
- package/dist/cli/{curator-llm-factory-frde1955.js → curator-llm-factory-7pvqy94w.js} +13 -13
- package/dist/cli/{curator-hbst8nbc.js → curator-xk4g1nx2.js} +13 -13
- package/dist/cli/{evidence-summary-service-9hq7n9k9.js → evidence-summary-service-v4h2w487.js} +1 -1
- package/dist/cli/{guardrail-explain-112kqmbc.js → guardrail-explain-wfk16bpr.js} +14 -14
- package/dist/cli/{guardrail-log-c8zcab91.js → guardrail-log-5zz9xx6z.js} +3 -3
- package/dist/cli/{hive-promoter-448xs2tp.js → hive-promoter-njwc5rt0.js} +13 -13
- package/dist/cli/{index-kt0awv1n.js → index-3k8pg467.js} +1 -1
- package/dist/cli/{index-n6chz2g8.js → index-83rwq7pb.js} +1 -1
- package/dist/cli/{index-xattnmyb.js → index-8yvqkbw7.js} +3 -1
- package/dist/cli/{index-99ed0h32.js → index-93cq8t5b.js} +5 -5
- package/dist/cli/{index-9hbwa5x1.js → index-cz6fv84h.js} +15 -15
- package/dist/cli/{index-amspa811.js → index-dsf1yv4s.js} +119 -44
- package/dist/cli/{index-4rzzzjtg.js → index-fs02c7tz.js} +277 -16
- package/dist/cli/{index-dx2c2wjt.js → index-ghteqdy1.js} +2 -2
- package/dist/cli/{index-67hqr2zv.js → index-kvrk3h8p.js} +1 -1
- package/dist/cli/{index-09vd53pz.js → index-kws8zn6y.js} +1 -1
- package/dist/cli/{index-7j3sm7h8.js → index-mhhmecsw.js} +2 -2
- package/dist/cli/{index-yt1v62pv.js → index-mwdcvh0e.js} +4 -4
- package/dist/cli/{index-6vfvc36k.js → index-pbjenws7.js} +1 -1
- package/dist/cli/{index-958hf0yr.js → index-rpg8qqjs.js} +2 -2
- package/dist/cli/{index-vtwqjr4z.js → index-tn3shyqj.js} +3 -3
- package/dist/cli/{index-jh6s75f6.js → index-txragda9.js} +1 -1
- package/dist/cli/{index-0y6tmm9v.js → index-z4sc6yxc.js} +1 -1
- package/dist/cli/index.js +13 -13
- package/dist/cli/{knowledge-escalator-htafbhxg.js → knowledge-escalator-jtyykzqc.js} +3 -3
- package/dist/cli/{knowledge-events-havw8c4t.js → knowledge-events-qhr97sy9.js} +1 -1
- package/dist/cli/{knowledge-store-hqngpt2v.js → knowledge-store-332x3pjv.js} +1 -1
- package/dist/cli/{knowledge-validator-g7mpnazh.js → knowledge-validator-3t8tgzsz.js} +4 -4
- package/dist/cli/{scan-cursor-sx7cvh8v.js → scan-cursor-q21c9k9q.js} +2 -2
- package/dist/cli/{schema-2418eqy3.js → schema-y2d7j2jk.js} +1 -1
- package/dist/cli/{skill-generator-zggy797r.js → skill-generator-3gkxx98d.js} +5 -5
- package/dist/commands/close.d.ts +4 -2
- package/dist/config/schema.d.ts +4 -0
- package/dist/evidence/documents-retention.d.ts +116 -0
- package/dist/evidence/manager.d.ts +17 -0
- package/dist/index.js +374 -366
- package/package.json +1 -1
|
@@ -33,12 +33,12 @@ import {
|
|
|
33
33
|
sanitizeSlug,
|
|
34
34
|
selectCandidateEntries,
|
|
35
35
|
writeEvalStub
|
|
36
|
-
} from "./index-
|
|
37
|
-
import"./index-
|
|
38
|
-
import"./index-
|
|
36
|
+
} from "./index-tn3shyqj.js";
|
|
37
|
+
import"./index-ghteqdy1.js";
|
|
38
|
+
import"./index-kvrk3h8p.js";
|
|
39
39
|
import"./index-rtry5xyf.js";
|
|
40
|
-
import"./index-
|
|
41
|
-
import"./index-
|
|
40
|
+
import"./index-mwdcvh0e.js";
|
|
41
|
+
import"./index-83rwq7pb.js";
|
|
42
42
|
import"./index-ae75rja9.js";
|
|
43
43
|
import"./index-q27bajqb.js";
|
|
44
44
|
import"./index-bk5tah7q.js";
|
package/dist/commands/close.d.ts
CHANGED
|
@@ -134,8 +134,10 @@ export declare function runFinalizeStage(ctx: CloseStageContext): Promise<void>;
|
|
|
134
134
|
export declare function runArchiveStage(ctx: CloseStageContext): Promise<void>;
|
|
135
135
|
/**
|
|
136
136
|
* Runs the evidence-retention sub-logic of STAGE 2 (ARCHIVE).
|
|
137
|
-
* Reads max_age_days / max_bundles
|
|
138
|
-
*
|
|
137
|
+
* Reads max_age_days / max_bundles / cache_max_bytes / cache_max_records from
|
|
138
|
+
* config.evidence (FR-016, issue #1184) and calls archiveEvidence. The report
|
|
139
|
+
* overload is used so the documents-cache prune runs when cache caps are set.
|
|
140
|
+
* Fail-open: pushes a warning on error but never throws.
|
|
139
141
|
*/
|
|
140
142
|
export declare function runArchiveEvidenceRetention(ctx: ArchiveStageContext): Promise<void>;
|
|
141
143
|
/**
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -262,6 +262,8 @@ export declare const EvidenceConfigSchema: z.ZodObject<{
|
|
|
262
262
|
max_age_days: z.ZodDefault<z.ZodNumber>;
|
|
263
263
|
max_bundles: z.ZodDefault<z.ZodNumber>;
|
|
264
264
|
auto_archive: z.ZodDefault<z.ZodBoolean>;
|
|
265
|
+
cache_max_bytes: z.ZodOptional<z.ZodNumber>;
|
|
266
|
+
cache_max_records: z.ZodOptional<z.ZodNumber>;
|
|
265
267
|
}, z.core.$strip>;
|
|
266
268
|
export type EvidenceConfig = z.infer<typeof EvidenceConfigSchema>;
|
|
267
269
|
export declare const GateFeatureSchema: z.ZodObject<{
|
|
@@ -1805,6 +1807,8 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1805
1807
|
max_age_days: z.ZodDefault<z.ZodNumber>;
|
|
1806
1808
|
max_bundles: z.ZodDefault<z.ZodNumber>;
|
|
1807
1809
|
auto_archive: z.ZodDefault<z.ZodBoolean>;
|
|
1810
|
+
cache_max_bytes: z.ZodOptional<z.ZodNumber>;
|
|
1811
|
+
cache_max_records: z.ZodOptional<z.ZodNumber>;
|
|
1808
1812
|
}, z.core.$strip>>;
|
|
1809
1813
|
summaries: z.ZodOptional<z.ZodObject<{
|
|
1810
1814
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retention for the web_search / web_fetch documents cache at
|
|
3
|
+
* `.swarm/evidence-cache/documents.jsonl`.
|
|
4
|
+
*
|
|
5
|
+
* Background (issue #1184): `writeEvidenceDocuments` in `./documents.ts` is
|
|
6
|
+
* purely append-only. Without this module the cache grows without bound.
|
|
7
|
+
* This module provides a bounded, project-root-contained, atomic-rewrite
|
|
8
|
+
* prune that is invoked only via `/swarm archive` and `/swarm finalize`
|
|
9
|
+
* (never on the plugin init path — AGENTS.md invariant #1).
|
|
10
|
+
*
|
|
11
|
+
* Design contract (mirrors `archiveEvaluationArtifacts` in
|
|
12
|
+
* `../evaluation/retention.ts` where applicable):
|
|
13
|
+
* - Optional byte cap and optional record-count cap. When both are unset the
|
|
14
|
+
* prune is a no-op (current append-only behavior preserved exactly).
|
|
15
|
+
* - Corrupt rows (failed `JSON.parse`) are dropped from the rewrite and
|
|
16
|
+
* reported via `corrupt` count. They are NOT relocated to a sidecar —
|
|
17
|
+
* matches the "report, don't relocate" precedent in
|
|
18
|
+
* `archiveEvaluationArtifacts` (retention.ts:246-254), while still
|
|
19
|
+
* preserving the bounded-growth contract (a corrupt row otherwise counts
|
|
20
|
+
* toward caps forever).
|
|
21
|
+
* - Atomic rewrite via temp file + fsync + rename. NOT under
|
|
22
|
+
* `withEvidenceLock`: web_search/web_fetch are hot paths and forcing a
|
|
23
|
+
* lockfile round-trip on every capture is an unjustified latency tax
|
|
24
|
+
* (issue-tracer critic item #2). The append-vs-rewrite race is a known,
|
|
25
|
+
* accepted data-loss window: a concurrent `appendFile` whose write is in
|
|
26
|
+
* flight when the prune renames the temp over the target will, on POSIX,
|
|
27
|
+
* complete against the now-unlinked old inode (the appended row is
|
|
28
|
+
* silently lost from the cache). This is accepted because refs are
|
|
29
|
+
* content-addressed (`evd_<sha256[:16]>`) so a lost row's ref
|
|
30
|
+
* re-materializes on the next capture of the same content, and because
|
|
31
|
+
* the prune runs only via explicit `/swarm archive` / `/swarm finalize`,
|
|
32
|
+
* not on every write.
|
|
33
|
+
* - Read is streamed line-by-line via `node:readline` with a hard 100 MiB
|
|
34
|
+
* cap. On cap breach the prune aborts, writes nothing, and leaves the
|
|
35
|
+
* file byte-identical.
|
|
36
|
+
* - Windows-safe rename: `EPERM`/`EBUSY`/`ENOTEMPTY`/`EACCES` are retried
|
|
37
|
+
* with bounded backoff (5× / 10ms). On final failure the temp file is
|
|
38
|
+
* removed and the original is left untouched (fail-safe).
|
|
39
|
+
*
|
|
40
|
+
* Memory tradeoff (L6-002): valid rows are parsed into a `ParsedRow[]` and
|
|
41
|
+
* retained in memory (raw string + parsed object per row) before selection.
|
|
42
|
+
* The 100 MiB read cap bounds input bytes, but the in-process heap footprint
|
|
43
|
+
* is higher (V8 string + object overhead). This is an accepted tradeoff: the
|
|
44
|
+
* prune runs once per explicit `/swarm archive` / `/swarm finalize` (never on
|
|
45
|
+
* a hot path), the input is bounded, and a streaming rewrite would be a
|
|
46
|
+
* materially larger refactor. If the cache ever needs to scale beyond the
|
|
47
|
+
* current cap, switch `readCacheRows` + `selectSurvivors` to a streaming
|
|
48
|
+
* selection (single pass, write survivors directly to the temp file).
|
|
49
|
+
*/
|
|
50
|
+
import * as fs from 'node:fs';
|
|
51
|
+
export interface DocumentsRetentionResult {
|
|
52
|
+
/** Total valid (parseable) rows read before pruning. Excludes corrupt rows. */
|
|
53
|
+
inventory: number;
|
|
54
|
+
/** Rows marked for deletion by the policy (same as `inventory - surviving`). */
|
|
55
|
+
selected: number;
|
|
56
|
+
/** Rows actually removed from the file. Always 0 when `dryRun` or `aborted`. */
|
|
57
|
+
archived: number;
|
|
58
|
+
/** Unparseable rows dropped from the rewrite (count only; not preserved). */
|
|
59
|
+
corrupt: number;
|
|
60
|
+
/** File size in bytes before the prune (0 if the file did not exist). */
|
|
61
|
+
bytesBefore: number;
|
|
62
|
+
/** File size in bytes after the prune. Equal to `bytesBefore` on no-op. */
|
|
63
|
+
bytesAfter: number;
|
|
64
|
+
/** True when the prune produced no file mutation. */
|
|
65
|
+
dryRun: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* True when the read cap (`MAX_READ_BYTES`) was exceeded. On abort the file
|
|
68
|
+
* is left byte-identical — no temp file, no rewrite, no sidecar.
|
|
69
|
+
*/
|
|
70
|
+
aborted: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface PruneEvidenceDocumentsArgs {
|
|
73
|
+
directory: string;
|
|
74
|
+
/** Optional byte cap. When omitted, no byte-based pruning. */
|
|
75
|
+
maxBytes?: number;
|
|
76
|
+
/** Optional record-count cap. When omitted, no count-based pruning. */
|
|
77
|
+
maxRecords?: number;
|
|
78
|
+
/** When true, compute the plan but write nothing. */
|
|
79
|
+
dryRun?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** Internal DI seam (AGENTS.md invariant #7 — preferred over mock.module). */
|
|
82
|
+
export declare const _internals: {
|
|
83
|
+
stat: (path: string) => Promise<fs.Stats>;
|
|
84
|
+
createReadStream: (path: string, options: {
|
|
85
|
+
encoding: BufferEncoding;
|
|
86
|
+
highWaterMark: number;
|
|
87
|
+
}) => fs.ReadStream;
|
|
88
|
+
openSync: (path: string, flags: fs.OpenMode) => number;
|
|
89
|
+
writeSync: (fd: number, data: string, position?: number | null) => number;
|
|
90
|
+
fsyncSync: (fd: number) => void;
|
|
91
|
+
closeSync: (fd: number) => void;
|
|
92
|
+
renameWithRetry: (src: string, dst: string) => Promise<void>;
|
|
93
|
+
unlink: (path: string) => Promise<void>;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Atomic rename with bounded retry for Windows.
|
|
97
|
+
*
|
|
98
|
+
* On Windows, `fs.rename` over an existing file can fail with `EPERM` when
|
|
99
|
+
* another handle (e.g. a concurrent `appendFile` from web_search) holds the
|
|
100
|
+
* target. We retry the rename a bounded number of times with a short backoff
|
|
101
|
+
* (the `readSwarmFileAsync` precedent in `hooks/utils.ts:263` uses the same
|
|
102
|
+
* 5× / 10ms shape for the macOS rename-visibility race). On final failure we
|
|
103
|
+
* rethrow — the caller is responsible for cleaning up the temp file.
|
|
104
|
+
*
|
|
105
|
+
* The optional `renameFn` is a test seam (defaults to `fsp.rename`) so the
|
|
106
|
+
* retry loop can be exercised deterministically on non-Windows hosts.
|
|
107
|
+
*/
|
|
108
|
+
export declare function atomicRenameWithRetry(src: string, dst: string, renameFn?: (s: string, d: string) => Promise<void>): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Apply the configured byte/count retention policy to the documents cache.
|
|
111
|
+
*
|
|
112
|
+
* Safe to call on a missing file (returns an idempotent zeroed result) and
|
|
113
|
+
* safe to call with both caps unset (no-op). Never throws for routine cases;
|
|
114
|
+
* surfaces unexpected I/O errors to the caller (archive command fails open).
|
|
115
|
+
*/
|
|
116
|
+
export declare function pruneEvidenceDocuments(args: PruneEvidenceDocumentsArgs): Promise<DocumentsRetentionResult>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type BuildEvidence, type Evidence, type EvidenceBundle, type PlaceholderEvidence, type QualityBudgetEvidence, type SastEvidence, type SbomEvidence, type SecretscanEvidence, type SyntaxEvidence } from '../config/evidence-schema';
|
|
2
2
|
import { type EvaluationRetentionResult } from '../evaluation/retention.js';
|
|
3
|
+
import { type DocumentsRetentionResult, pruneEvidenceDocuments } from './documents-retention.js';
|
|
3
4
|
/**
|
|
4
5
|
* Discriminated union returned by loadEvidence.
|
|
5
6
|
* - 'found': file exists and passed Zod schema validation
|
|
@@ -101,11 +102,26 @@ export type EvidenceArchiveReport = {
|
|
|
101
102
|
archivedEvidence: string[];
|
|
102
103
|
failedEvidence: string[];
|
|
103
104
|
evaluation: EvaluationRetentionResult;
|
|
105
|
+
/**
|
|
106
|
+
* Documents-cache retention result (issue #1184). Always present in the
|
|
107
|
+
* report shape — a zeroed result ({ inventory: 0, selected: 0, ... })
|
|
108
|
+
* indicates the cache was not pruned (no caps configured, file missing,
|
|
109
|
+
* or prune disabled).
|
|
110
|
+
*/
|
|
111
|
+
documentsCache: DocumentsRetentionResult;
|
|
104
112
|
};
|
|
105
113
|
export type EvidenceArchiveReportOptions = {
|
|
106
114
|
report: true;
|
|
107
115
|
dryRun?: boolean;
|
|
108
116
|
now?: Date;
|
|
117
|
+
/**
|
|
118
|
+
* Optional documents-cache retention caps (issue #1184). When either is a
|
|
119
|
+
* positive number, `archiveEvidence` also prunes
|
|
120
|
+
* `.swarm/evidence-cache/documents.jsonl` after the bundle/evaluation
|
|
121
|
+
* sweep. When both are unset, the cache is left untouched (append-only).
|
|
122
|
+
*/
|
|
123
|
+
cacheMaxBytes?: number;
|
|
124
|
+
cacheMaxRecords?: number;
|
|
109
125
|
};
|
|
110
126
|
export declare function archiveEvidence(directory: string, maxAgeDays: number, maxBundles?: number): Promise<string[]>;
|
|
111
127
|
export declare function archiveEvidence(directory: string, maxAgeDays: number, maxBundles: number | undefined, options: EvidenceArchiveReportOptions): Promise<EvidenceArchiveReport>;
|
|
@@ -125,6 +141,7 @@ export declare const _internals: {
|
|
|
125
141
|
validateEvidence: typeof validateEvidence;
|
|
126
142
|
saveEvidence: typeof saveEvidence;
|
|
127
143
|
deleteEvidence: typeof deleteEvidence;
|
|
144
|
+
pruneEvidenceDocuments: typeof pruneEvidenceDocuments;
|
|
128
145
|
now: () => Date;
|
|
129
146
|
};
|
|
130
147
|
export {};
|