opencode-swarm 7.137.5 → 7.138.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/dist/cli/{config-doctor-kv6hgx4a.js → config-doctor-m79sx8b2.js} +2 -2
- package/dist/cli/{curation-policy-92ecp6y6.js → curation-policy-dkx4s5va.js} +2 -2
- package/dist/cli/{curator-dwnsf527.js → curator-jjf5x6bn.js} +14 -14
- package/dist/cli/{curator-llm-factory-9p2eajyj.js → curator-llm-factory-sprc6pm3.js} +14 -14
- package/dist/cli/{evidence-summary-service-1azhyeft.js → evidence-summary-service-6cttrkzw.js} +2 -2
- package/dist/cli/{guardrail-explain-8r62kbz8.js → guardrail-explain-zs3hq02c.js} +15 -15
- package/dist/cli/{guardrail-log-evq3pke7.js → guardrail-log-90dnv508.js} +3 -3
- package/dist/cli/{hive-promoter-9f8e7csh.js → hive-promoter-zkay2ffy.js} +14 -14
- package/dist/cli/{index-w8kddryz.js → index-06zw53mf.js} +1 -1
- package/dist/cli/{index-yrqf3b44.js → index-5fdztrpt.js} +2 -2
- package/dist/cli/{index-fc3pppmj.js → index-6f6nt0c9.js} +16 -16
- package/dist/cli/{index-5ykb4nfj.js → index-8xqnp3gw.js} +4 -4
- package/dist/cli/{index-gmkjwk07.js → index-9vvskh03.js} +1 -1
- package/dist/cli/{index-a2xw89st.js → index-aeyktf9q.js} +1 -1
- package/dist/cli/{index-k7m0q2nz.js → index-d4t92fa3.js} +2 -2
- package/dist/cli/{index-sww6s8r5.js → index-e2eedz1b.js} +1 -1
- package/dist/cli/{index-qdk110fr.js → index-e78pqbkj.js} +1 -1
- package/dist/cli/{index-k5jrywpr.js → index-gprxjmm7.js} +6 -1
- package/dist/cli/{index-891ym5hz.js → index-kqzzdxc1.js} +1 -1
- package/dist/cli/{index-s1d1k64e.js → index-mnw8g9bs.js} +1996 -1231
- package/dist/cli/{index-g691qtx1.js → index-mzqgtzxq.js} +3 -3
- package/dist/cli/{index-cyew7vak.js → index-navw2ezf.js} +5 -5
- package/dist/cli/{index-ahkb1nty.js → index-p7fn5byt.js} +1 -1
- package/dist/cli/{index-akka5gyb.js → index-vmff7b40.js} +3 -3
- package/dist/cli/{index-ywyxtq1a.js → index-vp3mwsd1.js} +1 -1
- package/dist/cli/{index-fmh15wxb.js → index-y06a43sk.js} +1 -1
- package/dist/cli/index.js +14 -14
- package/dist/cli/{knowledge-escalator-av6ve14j.js → knowledge-escalator-6y5x8vat.js} +3 -3
- package/dist/cli/{knowledge-events-3h7a1edr.js → knowledge-events-bnr4weyn.js} +1 -1
- package/dist/cli/{knowledge-store-595cq24n.js → knowledge-store-4mcmb2rj.js} +1 -1
- package/dist/cli/{knowledge-validator-cvdj3atv.js → knowledge-validator-pf377mtx.js} +4 -4
- package/dist/cli/{scan-cursor-0sbrsd5q.js → scan-cursor-we0561wc.js} +2 -2
- package/dist/cli/{schema-8gp25rde.js → schema-1xtxr4d9.js} +1 -1
- package/dist/cli/{skill-generator-gdqvy68y.js → skill-generator-kns0dae2.js} +5 -5
- package/dist/commands/close.d.ts +22 -0
- package/dist/config/evidence-schema.d.ts +15 -0
- package/dist/index.js +291 -282
- package/dist/services/preflight-service.d.ts +2 -0
- package/dist/services/session-reflection.d.ts +171 -0
- package/dist/tools/pre-check-batch.d.ts +2 -0
- package/dist/tools/secretscan.d.ts +17 -0
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* Returns deterministic structured result with per-check status + overall verdict.
|
|
12
12
|
* Callable by background flow (from preflight.requested events).
|
|
13
13
|
*/
|
|
14
|
+
import { runSecretscan } from '../tools/secretscan';
|
|
14
15
|
/** Preflight check types */
|
|
15
16
|
export type PreflightCheckType = 'lint' | 'tests' | 'secrets' | 'evidence' | 'version' | 'req_coverage';
|
|
16
17
|
/** Individual check status */
|
|
@@ -122,6 +123,7 @@ export declare const _internals: {
|
|
|
122
123
|
runVersionCheck: typeof runVersionCheck;
|
|
123
124
|
runLintCheck: typeof runLintCheck;
|
|
124
125
|
runTestsCheck: typeof runTestsCheck;
|
|
126
|
+
runSecretscan: typeof runSecretscan;
|
|
125
127
|
runSecretsCheck: typeof runSecretsCheck;
|
|
126
128
|
runEvidenceCheck: typeof runEvidenceCheck;
|
|
127
129
|
runRequirementCoverageCheck: typeof runRequirementCoverageCheck;
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
* When no LLM client is available, phase 2 falls back to a deterministic
|
|
15
15
|
* summary so finalize never blocks on missing infrastructure.
|
|
16
16
|
*/
|
|
17
|
+
import { readKnowledge, readRejectedLessons } from '../hooks/knowledge-store';
|
|
17
18
|
import { type SkillImproverLLMDelegate } from '../hooks/skill-improver-llm-factory';
|
|
19
|
+
import { readSkillUsageEntriesTail } from '../hooks/skill-usage-log';
|
|
18
20
|
import type { ToolAggregate } from '../state';
|
|
19
21
|
export interface ToolProblem {
|
|
20
22
|
tool: string;
|
|
@@ -33,6 +35,68 @@ export interface GateFailureSummary {
|
|
|
33
35
|
taskId: string;
|
|
34
36
|
count: number;
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Knowledge-delta surface for the reflection report (issue #2077).
|
|
40
|
+
*
|
|
41
|
+
* `admitted` / `reinforcedRealtime` / `rejectedCurator` are recovered
|
|
42
|
+
* READ-ONLY from durable markers stamped by the realtime admission path
|
|
43
|
+
* (`src/learning/admission.ts`) and the curator rejected-lessons file —
|
|
44
|
+
* the in-memory `DrainSummary` is discarded at `src/index.ts` (issue
|
|
45
|
+
* #1821), but the outcomes it summarized persist on the entries
|
|
46
|
+
* themselves, so the counts are reconstructable here without any new
|
|
47
|
+
* writes. Realtime *rejections* (screened-out candidates that never
|
|
48
|
+
* reached the store) remain unobservable and are flagged in the report.
|
|
49
|
+
*/
|
|
50
|
+
export interface KnowledgeDelta {
|
|
51
|
+
/** Entries created this session (count, from countSessionKnowledgeEntries). */
|
|
52
|
+
sessionKnowledgeCreated: number;
|
|
53
|
+
/** FR-015 dedup: retro lessons dropped as already-known. */
|
|
54
|
+
dedupDropped: number;
|
|
55
|
+
/** False when the dedup read failed (fail-open) — distinguishes "0 deduped" from "dedup did not run". */
|
|
56
|
+
dedupAvailable: boolean;
|
|
57
|
+
/** Retro lessons that survived dedup and were curated. */
|
|
58
|
+
retroLessonTotal: number;
|
|
59
|
+
/** Close-time curation counts (finalize retro-lesson batch). */
|
|
60
|
+
curation?: {
|
|
61
|
+
stored: number;
|
|
62
|
+
reinforced: number;
|
|
63
|
+
skipped: number;
|
|
64
|
+
rejected: number;
|
|
65
|
+
quarantined: number;
|
|
66
|
+
};
|
|
67
|
+
/** Entries admitted this session (created_at >= sessionStart AND carry an `insight:` provenance marker). */
|
|
68
|
+
admitted?: number;
|
|
69
|
+
/** Pre-existing entries reinforced this session (some confirmed_by[].confirmed_at >= sessionStart). */
|
|
70
|
+
reinforcedRealtime?: number;
|
|
71
|
+
/** Curator-path rejections this session (rejected_at >= sessionStart, from .swarm/knowledge-rejected.jsonl). */
|
|
72
|
+
rejectedCurator?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface SkillViolationSignal {
|
|
75
|
+
skillPath: string;
|
|
76
|
+
violations: number;
|
|
77
|
+
total: number;
|
|
78
|
+
/** Always true — the 64 KB tail may truncate the denominator. */
|
|
79
|
+
tailBounded: boolean;
|
|
80
|
+
/** 'session' when filtered by sessionID; 'all_sessions' when no sessionID was available. */
|
|
81
|
+
scope: 'session' | 'all_sessions';
|
|
82
|
+
}
|
|
83
|
+
export interface ContradictionCandidate {
|
|
84
|
+
newLesson: string;
|
|
85
|
+
newEntryId: string;
|
|
86
|
+
conflictsWithId: string;
|
|
87
|
+
conflictsWithLesson: string;
|
|
88
|
+
similarity: number;
|
|
89
|
+
}
|
|
90
|
+
export type ReflectionActionKind = 'supersede' | 'file_issue' | 'draft_skill';
|
|
91
|
+
export interface ReflectionActionProposal {
|
|
92
|
+
kind: ReflectionActionKind;
|
|
93
|
+
/** Short human-readable label for the menu line. */
|
|
94
|
+
label: string;
|
|
95
|
+
/** Longer body (issue body, lesson text, etc.). */
|
|
96
|
+
detail: string;
|
|
97
|
+
/** Existing tool/command to route to, e.g. '/swarm curate'. */
|
|
98
|
+
routing: string;
|
|
99
|
+
}
|
|
36
100
|
export interface SessionReflectionData {
|
|
37
101
|
timestamp: string;
|
|
38
102
|
totalToolCalls: number;
|
|
@@ -42,11 +106,22 @@ export interface SessionReflectionData {
|
|
|
42
106
|
gateFailures: GateFailureSummary[];
|
|
43
107
|
lessonsFromRetros: string[];
|
|
44
108
|
errorTaxonomy: Record<string, number>;
|
|
109
|
+
knowledgeDelta?: KnowledgeDelta;
|
|
110
|
+
skillViolations: SkillViolationSignal[];
|
|
111
|
+
contradictionCandidates: ContradictionCandidate[];
|
|
45
112
|
}
|
|
46
113
|
export interface SessionReflectionResult {
|
|
47
114
|
data: SessionReflectionData;
|
|
48
115
|
architectReport: string;
|
|
116
|
+
/**
|
|
117
|
+
* Always-rendered signals block (issue #2077). Surfaced UNCONDITIONALLY
|
|
118
|
+
* by close.ts (not gated by the narrative-report `hasSignals` check) so
|
|
119
|
+
* the "0 captured; N deduped" / NOOP line appears even in a clean
|
|
120
|
+
* session. Present on BOTH the llm and deterministic paths.
|
|
121
|
+
*/
|
|
122
|
+
signalsReport: string;
|
|
49
123
|
source: 'llm' | 'deterministic';
|
|
124
|
+
actionProposals: ReflectionActionProposal[];
|
|
50
125
|
}
|
|
51
126
|
declare function gatherToolProblems(toolAggregates: Map<string, ToolAggregate>): {
|
|
52
127
|
problems: ToolProblem[];
|
|
@@ -63,7 +138,83 @@ declare function gatherRetroLessonsAndTaxonomy(directory: string): Promise<{
|
|
|
63
138
|
taxonomy: Record<string, number>;
|
|
64
139
|
}>;
|
|
65
140
|
declare function gatherGateFailures(directory: string): Promise<GateFailureSummary[]>;
|
|
141
|
+
/**
|
|
142
|
+
* Top skills by violation this session (issue #2077).
|
|
143
|
+
*
|
|
144
|
+
* Reads the bounded tail of `.swarm/skill-usage.jsonl`, groups by
|
|
145
|
+
* `skillPath`, and counts entries where the normalized compliance
|
|
146
|
+
* verdict is `'violated'`. Returns `[]` when `sessionId` is undefined:
|
|
147
|
+
* without a session filter the tail is cumulative cross-session data
|
|
148
|
+
* and MUST NOT be labeled "this session" (issue #2077 critic item 8).
|
|
149
|
+
* `tailBounded` is always true — the 64 KB tail may truncate the
|
|
150
|
+
* denominator.
|
|
151
|
+
*/
|
|
152
|
+
export declare function gatherSkillViolations(directory: string, sessionId?: string): SkillViolationSignal[];
|
|
153
|
+
/**
|
|
154
|
+
* Contradiction candidates among session-created knowledge (issue #2077).
|
|
155
|
+
*
|
|
156
|
+
* IMPORTANT (issue #2077 critic item 3): the realtime admission and
|
|
157
|
+
* curator write paths dedup at `dedup_threshold` (default 0.6) BEFORE an
|
|
158
|
+
* entry becomes active, so two active entries with Jaccard similarity
|
|
159
|
+
* ≥ that threshold cannot coexist. A detector run at the dedup threshold
|
|
160
|
+
* would therefore return `[]` in every real session. Instead this looks
|
|
161
|
+
* in a sub-threshold band `[CONTRADICTION_LOWER, dedupThreshold)` AND
|
|
162
|
+
* requires negation-polarity divergence — the only shape that can occur
|
|
163
|
+
* in production. Uses the exported `wordBigrams`/`jaccardBigram`
|
|
164
|
+
* primitives directly so the score is available (the
|
|
165
|
+
* `findActiveSwarmNearDuplicate` helper returns only the entry, with no
|
|
166
|
+
* score and no self-exclusion). Detect-only: never writes, never
|
|
167
|
+
* auto-supersedes. Supersession is operationally deletion
|
|
168
|
+
* (`superseded_by IS NULL` read filter) and is surfaced only as a menu
|
|
169
|
+
* item the user opts into.
|
|
170
|
+
*/
|
|
171
|
+
export declare function gatherContradictionCandidates(directory: string, sessionStart?: string, dedupThreshold?: number): Promise<ContradictionCandidate[]>;
|
|
172
|
+
/**
|
|
173
|
+
* Realtime admission counts recovered READ-ONLY from durable markers
|
|
174
|
+
* (issue #2077 critic item 4). The in-memory `DrainSummary` is
|
|
175
|
+
* discarded at `src/index.ts`, but the outcomes persist:
|
|
176
|
+
* - admitted: entries created this session with an `insight:` provenance marker
|
|
177
|
+
* (stamped by `admitCandidate` via `unionSourceKnowledgeIds`).
|
|
178
|
+
* - reinforced: pre-existing entries with a `confirmed_by` record
|
|
179
|
+
* stamped this session (the realtime reinforce path).
|
|
180
|
+
* - rejected: curator-path rejections this session, from
|
|
181
|
+
* `.swarm/knowledge-rejected.jsonl`.
|
|
182
|
+
* Returns `undefined` when `sessionStart` is undefined (counts are
|
|
183
|
+
* session-scoped). Realtime *rejections* (screened-out candidates that
|
|
184
|
+
* never reached the store) are NOT recoverable and are flagged in the
|
|
185
|
+
* report as tracked by #1821.
|
|
186
|
+
*/
|
|
187
|
+
export declare function gatherRealtimeAdmissionCounts(directory: string, sessionStart?: string): Promise<{
|
|
188
|
+
admitted: number;
|
|
189
|
+
reinforced: number;
|
|
190
|
+
rejected: number;
|
|
191
|
+
} | undefined>;
|
|
66
192
|
declare function buildReflectionDataSummary(data: SessionReflectionData): string;
|
|
193
|
+
/**
|
|
194
|
+
* Always-rendered signals block (issue #2077). Rendered UNCONDITIONALLY
|
|
195
|
+
* by close.ts (not gated by the narrative-report `hasSignals` check) so
|
|
196
|
+
* the "0 captured; N deduped" / NOOP line appears even in a clean
|
|
197
|
+
* session. Surfaces all six signal classes: knowledge delta, skill
|
|
198
|
+
* violations, contradiction candidates, negatives, drafted issues.
|
|
199
|
+
*/
|
|
200
|
+
export declare function buildSignalsBlock(data: SessionReflectionData): string;
|
|
201
|
+
/**
|
|
202
|
+
* Assemble a numbered action menu from reflection proposals (issue #2077
|
|
203
|
+
* Phase B). Advisory only — application happens in a later user turn via
|
|
204
|
+
* the named existing tools. Under full-auto the "reply with numbers"
|
|
205
|
+
* prompt is suppressed (reported-only) so the run is not blocked waiting
|
|
206
|
+
* on human input. Returns '' when there are no proposals.
|
|
207
|
+
*/
|
|
208
|
+
export declare function buildActionMenu(proposals: ReflectionActionProposal[], fullAuto: boolean): string;
|
|
209
|
+
/**
|
|
210
|
+
* Build action proposals from gathered signals (issue #2077 Phase B).
|
|
211
|
+
* The `capture` kind is intentionally absent (issue #2077 critic item 7):
|
|
212
|
+
* aggregate curation counts cannot derive per-lesson outcomes, and
|
|
213
|
+
* re-proposing quarantined lessons would fail the actionability gate
|
|
214
|
+
* identically when applied. A menu item guaranteed to be rejected is
|
|
215
|
+
* worse than no menu item.
|
|
216
|
+
*/
|
|
217
|
+
export declare function buildActionProposals(data: SessionReflectionData): ReflectionActionProposal[];
|
|
67
218
|
declare function buildDeterministicReport(data: SessionReflectionData): string;
|
|
68
219
|
export interface SessionReflectionInput {
|
|
69
220
|
directory: string;
|
|
@@ -72,6 +223,17 @@ export interface SessionReflectionInput {
|
|
|
72
223
|
sessionId?: string;
|
|
73
224
|
signal?: AbortSignal;
|
|
74
225
|
delegate?: SkillImproverLLMDelegate;
|
|
226
|
+
/** Issue #2077: knowledge-delta surface (close-time curation counts + dedup state). */
|
|
227
|
+
knowledgeDelta?: KnowledgeDelta;
|
|
228
|
+
/** Issue #2077: session start (ISO), used to scope session-created entries. */
|
|
229
|
+
sessionStart?: string;
|
|
230
|
+
/**
|
|
231
|
+
* Issue #2077: configured dedup threshold (upper bound of the contradiction
|
|
232
|
+
* band). Read from `config.dedup_threshold` so a user-tuned threshold (e.g.
|
|
233
|
+
* 0.8) does not cause advisory false negatives for pairs in [0.6, 0.8) that
|
|
234
|
+
* can coexist in the active store. Defaults to 0.6 (the schema default).
|
|
235
|
+
*/
|
|
236
|
+
dedupThreshold?: number;
|
|
75
237
|
}
|
|
76
238
|
export declare function runSessionReflection(input: SessionReflectionInput): Promise<SessionReflectionResult>;
|
|
77
239
|
export declare function writeSessionReflection(directory: string, result: SessionReflectionResult): Promise<string>;
|
|
@@ -82,5 +244,14 @@ export declare const _internals: {
|
|
|
82
244
|
gatherGateFailures: typeof gatherGateFailures;
|
|
83
245
|
buildReflectionDataSummary: typeof buildReflectionDataSummary;
|
|
84
246
|
buildDeterministicReport: typeof buildDeterministicReport;
|
|
247
|
+
gatherSkillViolations: typeof gatherSkillViolations;
|
|
248
|
+
gatherContradictionCandidates: typeof gatherContradictionCandidates;
|
|
249
|
+
gatherRealtimeAdmissionCounts: typeof gatherRealtimeAdmissionCounts;
|
|
250
|
+
buildSignalsBlock: typeof buildSignalsBlock;
|
|
251
|
+
buildActionMenu: typeof buildActionMenu;
|
|
252
|
+
buildActionProposals: typeof buildActionProposals;
|
|
253
|
+
readSkillUsageEntriesTail: typeof readSkillUsageEntriesTail;
|
|
254
|
+
readKnowledge: typeof readKnowledge;
|
|
255
|
+
readRejectedLessons: typeof readRejectedLessons;
|
|
85
256
|
};
|
|
86
257
|
export {};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { tool } from '@opencode-ai/plugin';
|
|
7
7
|
import type { PluginConfig } from '../config';
|
|
8
|
+
import { saveEvidence } from '../evidence/manager.js';
|
|
8
9
|
import type { LintResult } from './lint';
|
|
9
10
|
import type { QualityBudgetResult } from './quality-budget';
|
|
10
11
|
import { qualityBudget } from './quality-budget';
|
|
@@ -17,6 +18,7 @@ export declare const _internals: {
|
|
|
17
18
|
runSastScanWrapped: typeof runSastScanWrapped;
|
|
18
19
|
runQualityBudgetWrapped: typeof runQualityBudgetWrapped;
|
|
19
20
|
getChangedLineRanges: typeof getChangedLineRanges;
|
|
21
|
+
saveEvidence: typeof saveEvidence;
|
|
20
22
|
};
|
|
21
23
|
export interface PreCheckBatchInput {
|
|
22
24
|
/** List of specific files to check (optional) */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
1
2
|
import { createSwarmTool } from './create-tool';
|
|
2
3
|
type SecretType = 'api_key' | 'aws_access_key' | 'aws_secret_key' | 'private_key' | 'password' | 'secret_token' | 'bearer_token' | 'basic_auth' | 'database_url' | 'jwt' | 'github_token' | 'slack_token' | 'stripe_key' | 'sendgrid_key' | 'twilio_key' | 'generic_token' | 'high_entropy';
|
|
3
4
|
type Confidence = 'high' | 'medium' | 'low';
|
|
@@ -17,8 +18,15 @@ export interface SecretscanResult {
|
|
|
17
18
|
count: number;
|
|
18
19
|
files_scanned: number;
|
|
19
20
|
skipped_files: number;
|
|
21
|
+
/** Files requested or discovered but not completely examined. */
|
|
22
|
+
incomplete_files: number;
|
|
23
|
+
incomplete_paths: IncompletePath[];
|
|
20
24
|
message?: string;
|
|
21
25
|
}
|
|
26
|
+
export interface IncompletePath {
|
|
27
|
+
path: string;
|
|
28
|
+
reason: 'cleanup_failed' | 'deadline' | 'directory_limit' | 'max_files' | 'non_file' | 'oversized' | 'read_error' | 'scope_escape' | 'symlink' | 'truncated';
|
|
29
|
+
}
|
|
22
30
|
export interface SecretscanErrorResult {
|
|
23
31
|
error: string;
|
|
24
32
|
scan_dir: string;
|
|
@@ -35,6 +43,7 @@ interface SecretPattern {
|
|
|
35
43
|
redactTemplate: (match: string) => string;
|
|
36
44
|
}
|
|
37
45
|
declare const SECRET_PATTERNS: SecretPattern[];
|
|
46
|
+
declare function yieldToEventLoop(): Promise<void>;
|
|
38
47
|
export declare const secretscan: ReturnType<typeof createSwarmTool>;
|
|
39
48
|
/**
|
|
40
49
|
* Run secretscan programmatically
|
|
@@ -55,5 +64,13 @@ export declare const _internals: {
|
|
|
55
64
|
runSecretscan: typeof runSecretscan;
|
|
56
65
|
runSecretscanOnFiles: typeof runSecretscanOnFiles;
|
|
57
66
|
SECRET_PATTERNS: typeof SECRET_PATTERNS;
|
|
67
|
+
now: () => number;
|
|
68
|
+
yieldToEventLoop: typeof yieldToEventLoop;
|
|
69
|
+
openFile: typeof fs.openSync;
|
|
70
|
+
fstatFile: typeof fs.fstatSync;
|
|
71
|
+
readFileChunk: typeof fs.readSync;
|
|
72
|
+
closeFile: typeof fs.closeSync;
|
|
73
|
+
lstatFile: typeof fs.lstatSync;
|
|
74
|
+
closeDirectory: (directory: fs.Dir) => void;
|
|
58
75
|
};
|
|
59
76
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.138.1",
|
|
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",
|