opencode-swarm 6.41.3 → 6.42.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.
- package/dist/cli/index.js +14 -2
- package/dist/hooks/curator-llm-factory.d.ts +11 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/knowledge-store.d.ts +1 -0
- package/dist/hooks/phase-monitor.d.ts +1 -1
- package/dist/hooks/review-receipt.d.ts +189 -0
- package/dist/index.js +741 -441
- package/dist/state.d.ts +3 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -18242,7 +18242,7 @@ var KnowledgeConfigSchema = exports_external.object({
|
|
|
18242
18242
|
max_encounter_score: exports_external.number().min(1).max(20).default(10)
|
|
18243
18243
|
});
|
|
18244
18244
|
var CuratorConfigSchema = exports_external.object({
|
|
18245
|
-
enabled: exports_external.boolean().default(
|
|
18245
|
+
enabled: exports_external.boolean().default(true),
|
|
18246
18246
|
init_enabled: exports_external.boolean().default(true),
|
|
18247
18247
|
phase_enabled: exports_external.boolean().default(true),
|
|
18248
18248
|
max_summary_tokens: exports_external.number().min(500).max(8000).default(2000),
|
|
@@ -18512,6 +18512,7 @@ var swarmState = {
|
|
|
18512
18512
|
activeAgent: new Map,
|
|
18513
18513
|
delegationChains: new Map,
|
|
18514
18514
|
pendingEvents: 0,
|
|
18515
|
+
opencodeClient: null,
|
|
18515
18516
|
lastBudgetPct: 0,
|
|
18516
18517
|
agentSessions: new Map,
|
|
18517
18518
|
pendingRehydrations: new Set
|
|
@@ -31690,6 +31691,13 @@ async function rewriteKnowledge(filePath, entries) {
|
|
|
31690
31691
|
}
|
|
31691
31692
|
}
|
|
31692
31693
|
}
|
|
31694
|
+
async function enforceKnowledgeCap(filePath, maxEntries) {
|
|
31695
|
+
const entries = await readKnowledge(filePath);
|
|
31696
|
+
if (entries.length > maxEntries) {
|
|
31697
|
+
const trimmed = entries.slice(entries.length - maxEntries);
|
|
31698
|
+
await rewriteKnowledge(filePath, trimmed);
|
|
31699
|
+
}
|
|
31700
|
+
}
|
|
31693
31701
|
async function appendRejectedLesson(directory, lesson) {
|
|
31694
31702
|
const filePath = resolveSwarmRejectedPath(directory);
|
|
31695
31703
|
const existing = await readRejectedLessons(directory);
|
|
@@ -32203,6 +32211,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
32203
32211
|
stored++;
|
|
32204
32212
|
existingEntries.push(entry);
|
|
32205
32213
|
}
|
|
32214
|
+
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
32206
32215
|
await runAutoPromotion(directory, config3);
|
|
32207
32216
|
return { stored, skipped, rejected };
|
|
32208
32217
|
}
|
|
@@ -33045,6 +33054,9 @@ async function checkHivePromotions(swarmEntries, config3) {
|
|
|
33045
33054
|
if (hiveModified) {
|
|
33046
33055
|
await rewriteKnowledge(resolveHiveKnowledgePath(), hiveEntries);
|
|
33047
33056
|
}
|
|
33057
|
+
if (newPromotions > 0 || hiveModified) {
|
|
33058
|
+
await enforceKnowledgeCap(resolveHiveKnowledgePath(), config3.hive_max_entries);
|
|
33059
|
+
}
|
|
33048
33060
|
return {
|
|
33049
33061
|
timestamp: new Date().toISOString(),
|
|
33050
33062
|
new_promotions: newPromotions,
|
|
@@ -33432,7 +33444,7 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
33432
33444
|
lesson,
|
|
33433
33445
|
category: "architecture",
|
|
33434
33446
|
tags: ["hidden-coupling", "co-change", "dark-matter"],
|
|
33435
|
-
scope: "
|
|
33447
|
+
scope: "global",
|
|
33436
33448
|
confidence,
|
|
33437
33449
|
status: "candidate",
|
|
33438
33450
|
confirmed_by: [],
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CuratorLLMDelegate } from './curator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a CuratorLLMDelegate that uses the opencode SDK to call
|
|
4
|
+
* the Explorer agent in CURATOR_INIT or CURATOR_PHASE mode.
|
|
5
|
+
*
|
|
6
|
+
* Uses an ephemeral session (create → prompt → delete) to avoid
|
|
7
|
+
* re-entrancy with the current session's message flow.
|
|
8
|
+
*
|
|
9
|
+
* Returns undefined if swarmState.opencodeClient is not set (e.g. in unit tests).
|
|
10
|
+
*/
|
|
11
|
+
export declare function createCuratorLLMDelegate(directory: string): CuratorLLMDelegate | undefined;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createAgentActivityHooks } from './agent-activity';
|
|
2
2
|
export { createCompactionCustomizerHook } from './compaction-customizer';
|
|
3
3
|
export { createContextBudgetHandler } from './context-budget';
|
|
4
|
+
export { createCuratorLLMDelegate } from './curator-llm-factory';
|
|
4
5
|
export { createDelegationGateHook } from './delegation-gate';
|
|
5
6
|
export { createDelegationSanitizerHook } from './delegation-sanitizer';
|
|
6
7
|
export { createDelegationTrackerHook } from './delegation-tracker';
|
|
@@ -11,6 +12,7 @@ export { consolidateSystemMessages } from './messages-transform';
|
|
|
11
12
|
export { extractModelInfo, NATIVE_MODEL_LIMITS, PROVIDER_CAPS, resolveModelLimit, } from './model-limits';
|
|
12
13
|
export { createPhaseMonitorHook } from './phase-monitor';
|
|
13
14
|
export { createPipelineTrackerHook } from './pipeline-tracker';
|
|
15
|
+
export { buildApprovedReceipt, buildReceiptContextForDrift, buildRejectedReceipt, persistReviewReceipt, readAllReceipts, readReceiptsByScopeHash, } from './review-receipt';
|
|
14
16
|
export { createSystemEnhancerHook } from './system-enhancer';
|
|
15
17
|
export { createToolSummarizerHook, resetSummaryIdCounter, } from './tool-summarizer';
|
|
16
18
|
export { composeHandlers, estimateTokens, readSwarmFileAsync, safeHook, validateSwarmPath, } from './utils';
|
|
@@ -9,6 +9,7 @@ export declare function readKnowledge<T>(filePath: string): Promise<T[]>;
|
|
|
9
9
|
export declare function readRejectedLessons(directory: string): Promise<RejectedLesson[]>;
|
|
10
10
|
export declare function appendKnowledge<T>(filePath: string, entry: T): Promise<void>;
|
|
11
11
|
export declare function rewriteKnowledge<T>(filePath: string, entries: T[]): Promise<void>;
|
|
12
|
+
export declare function enforceKnowledgeCap<T>(filePath: string, maxEntries: number): Promise<void>;
|
|
12
13
|
export declare function appendRejectedLesson(directory: string, lesson: RejectedLesson): Promise<void>;
|
|
13
14
|
export declare function normalize(text: string): string;
|
|
14
15
|
export declare function wordBigrams(text: string): Set<string>;
|
|
@@ -20,4 +20,4 @@ export type CuratorInitRunner = (directory: string, config: CuratorConfig, llmDe
|
|
|
20
20
|
* @param curatorRunner - Optional curator init runner (defaults to runCuratorInit; injectable for tests)
|
|
21
21
|
* @returns A safeHook-wrapped system.transform handler
|
|
22
22
|
*/
|
|
23
|
-
export declare function createPhaseMonitorHook(directory: string, preflightManager?: PreflightTriggerManager, curatorRunner?: CuratorInitRunner): (input: unknown, output: unknown) => Promise<void>;
|
|
23
|
+
export declare function createPhaseMonitorHook(directory: string, preflightManager?: PreflightTriggerManager, curatorRunner?: CuratorInitRunner, llmDelegate?: CuratorLLMDelegate): (input: unknown, output: unknown) => Promise<void>;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Review receipt persistence for opencode-swarm.
|
|
3
|
+
*
|
|
4
|
+
* Persists reviewer and curator review receipts to disk so that future
|
|
5
|
+
* re-reviews and drift verification have durable evidence of prior judgments.
|
|
6
|
+
*
|
|
7
|
+
* Two receipt types:
|
|
8
|
+
* RejectedReviewReceipt — full-detail artifact with blocking findings,
|
|
9
|
+
* exact evidence refs, scope fingerprint/hash,
|
|
10
|
+
* and re-review pass conditions.
|
|
11
|
+
* ApprovedReviewReceipt — compact artifact with what was checked, claims
|
|
12
|
+
* validated, scope fingerprint, and caveats.
|
|
13
|
+
*
|
|
14
|
+
* Storage: .swarm/review-receipts/<YYYY-MM-DD>-<id>.json (one file per receipt)
|
|
15
|
+
* .swarm/review-receipts/index.json (manifest for fast lookup)
|
|
16
|
+
*
|
|
17
|
+
* Staleness: receipts are invalidated when the scope fingerprint changes
|
|
18
|
+
* materially (any character-level change to the canonical diff/hash).
|
|
19
|
+
* Consumers MUST check isScopeStale() before trusting an approved receipt.
|
|
20
|
+
*
|
|
21
|
+
* Critic drift verification can consume prior receipts as supporting context
|
|
22
|
+
* but MUST NOT blindly trust them — staleness check is mandatory.
|
|
23
|
+
*/
|
|
24
|
+
export type ReceiptVerdict = 'rejected' | 'approved';
|
|
25
|
+
/** Identity of the reviewer/curator that produced the receipt. */
|
|
26
|
+
export interface ReviewerIdentity {
|
|
27
|
+
/** Agent name (e.g. 'reviewer', 'critic', 'curator') */
|
|
28
|
+
agent: string;
|
|
29
|
+
/** Optional session ID for traceability */
|
|
30
|
+
session_id?: string;
|
|
31
|
+
}
|
|
32
|
+
/** A canonical fingerprint/hash of the reviewed scope or diff. */
|
|
33
|
+
export interface ScopeFingerprint {
|
|
34
|
+
/** SHA-256 hex digest of the canonical scope content */
|
|
35
|
+
hash: string;
|
|
36
|
+
/** Short description of what was hashed (e.g. 'git-diff', 'file-content', 'spec-md') */
|
|
37
|
+
scope_description: string;
|
|
38
|
+
/** Length of the original content in characters */
|
|
39
|
+
content_length: number;
|
|
40
|
+
}
|
|
41
|
+
/** A blocking finding recorded in a rejected review. */
|
|
42
|
+
export interface BlockingFinding {
|
|
43
|
+
/** File path (relative) or identifier */
|
|
44
|
+
location: string;
|
|
45
|
+
/** One-line summary of the finding */
|
|
46
|
+
summary: string;
|
|
47
|
+
/** Line number if applicable */
|
|
48
|
+
line?: number;
|
|
49
|
+
/** Severity: 'critical' | 'high' | 'medium' */
|
|
50
|
+
severity: 'critical' | 'high' | 'medium';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Rejected review receipt.
|
|
54
|
+
* Full-detail artifact. Persisted for re-review reference.
|
|
55
|
+
*/
|
|
56
|
+
export interface RejectedReviewReceipt {
|
|
57
|
+
schema_version: 1;
|
|
58
|
+
id: string;
|
|
59
|
+
receipt_type: 'rejected';
|
|
60
|
+
verdict: 'rejected';
|
|
61
|
+
/** Reviewer/curator that produced this receipt */
|
|
62
|
+
reviewer: ReviewerIdentity;
|
|
63
|
+
/** ISO 8601 timestamp */
|
|
64
|
+
reviewed_at: string;
|
|
65
|
+
/** Fingerprint of the reviewed scope */
|
|
66
|
+
scope_fingerprint: ScopeFingerprint;
|
|
67
|
+
/** Blocking findings that caused rejection */
|
|
68
|
+
blocking_findings: BlockingFinding[];
|
|
69
|
+
/** Exact evidence references (file paths, line numbers, etc.) */
|
|
70
|
+
evidence_references: string[];
|
|
71
|
+
/** Conditions that must be met for a re-review to pass */
|
|
72
|
+
pass_conditions: string[];
|
|
73
|
+
/** Optional free-text summary */
|
|
74
|
+
summary?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Approved review receipt.
|
|
78
|
+
* Compact artifact. Supporting evidence, not durable proof.
|
|
79
|
+
*/
|
|
80
|
+
export interface ApprovedReviewReceipt {
|
|
81
|
+
schema_version: 1;
|
|
82
|
+
id: string;
|
|
83
|
+
receipt_type: 'approved';
|
|
84
|
+
verdict: 'approved';
|
|
85
|
+
/** Reviewer/curator that produced this receipt */
|
|
86
|
+
reviewer: ReviewerIdentity;
|
|
87
|
+
/** ISO 8601 timestamp */
|
|
88
|
+
reviewed_at: string;
|
|
89
|
+
/** Fingerprint of the reviewed scope */
|
|
90
|
+
scope_fingerprint: ScopeFingerprint;
|
|
91
|
+
/** What aspects were checked (e.g. ['security', 'correctness', 'test coverage']) */
|
|
92
|
+
checked_aspects: string[];
|
|
93
|
+
/** Claims that were validated during review */
|
|
94
|
+
validated_claims: string[];
|
|
95
|
+
/** Residual risk or caveats */
|
|
96
|
+
caveats?: string[];
|
|
97
|
+
}
|
|
98
|
+
export type ReviewReceipt = RejectedReviewReceipt | ApprovedReviewReceipt;
|
|
99
|
+
/** Index entry for fast lookup without reading every receipt file. */
|
|
100
|
+
export interface ReceiptIndexEntry {
|
|
101
|
+
id: string;
|
|
102
|
+
verdict: ReceiptVerdict;
|
|
103
|
+
reviewed_at: string;
|
|
104
|
+
scope_hash: string;
|
|
105
|
+
agent: string;
|
|
106
|
+
filename: string;
|
|
107
|
+
}
|
|
108
|
+
/** Receipt index manifest stored in .swarm/review-receipts/index.json */
|
|
109
|
+
export interface ReceiptIndex {
|
|
110
|
+
schema_version: 1;
|
|
111
|
+
entries: ReceiptIndexEntry[];
|
|
112
|
+
}
|
|
113
|
+
/** Returns the .swarm/review-receipts/ directory path. */
|
|
114
|
+
export declare function resolveReceiptsDir(directory: string): string;
|
|
115
|
+
/** Returns the index file path. */
|
|
116
|
+
export declare function resolveReceiptIndexPath(directory: string): string;
|
|
117
|
+
/**
|
|
118
|
+
* Compute a SHA-256 scope fingerprint for a given content string.
|
|
119
|
+
* The hash is deterministic: same content → same hash.
|
|
120
|
+
*/
|
|
121
|
+
export declare function computeScopeFingerprint(content: string, scopeDescription: string): ScopeFingerprint;
|
|
122
|
+
/**
|
|
123
|
+
* Returns true if the current scope content is materially different from
|
|
124
|
+
* the fingerprint recorded in the receipt. Any character-level change to the
|
|
125
|
+
* canonical content (same scopeDescription) invalidates the receipt.
|
|
126
|
+
*
|
|
127
|
+
* If `currentContent` is undefined (scope no longer available), the receipt
|
|
128
|
+
* is treated as stale (conservative: assume the scope has changed).
|
|
129
|
+
*/
|
|
130
|
+
export declare function isScopeStale(receipt: ReviewReceipt, currentContent: string | undefined): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Persist a review receipt (rejected or approved) to disk.
|
|
133
|
+
* Creates .swarm/review-receipts/<date>-<id>.json and updates the index.
|
|
134
|
+
* Returns the absolute path of the written receipt file.
|
|
135
|
+
*/
|
|
136
|
+
export declare function persistReviewReceipt(directory: string, receipt: ReviewReceipt): Promise<string>;
|
|
137
|
+
/**
|
|
138
|
+
* Read a single receipt by ID. Returns null if not found or unreadable.
|
|
139
|
+
*/
|
|
140
|
+
export declare function readReceiptById(directory: string, receiptId: string): Promise<ReviewReceipt | null>;
|
|
141
|
+
/**
|
|
142
|
+
* Read all receipts for a given scope hash (latest first).
|
|
143
|
+
* Useful for drift verification to find prior reviews of the same scope.
|
|
144
|
+
*/
|
|
145
|
+
export declare function readReceiptsByScopeHash(directory: string, scopeHash: string): Promise<ReviewReceipt[]>;
|
|
146
|
+
/**
|
|
147
|
+
* Read all receipts from the index (all verdicts, latest first).
|
|
148
|
+
* Useful for drift verification context.
|
|
149
|
+
*/
|
|
150
|
+
export declare function readAllReceipts(directory: string): Promise<ReviewReceipt[]>;
|
|
151
|
+
/**
|
|
152
|
+
* Build a RejectedReviewReceipt.
|
|
153
|
+
* `scopeContent` is hashed to produce the fingerprint.
|
|
154
|
+
*/
|
|
155
|
+
export declare function buildRejectedReceipt(opts: {
|
|
156
|
+
agent: string;
|
|
157
|
+
sessionId?: string;
|
|
158
|
+
scopeContent: string;
|
|
159
|
+
scopeDescription: string;
|
|
160
|
+
blockingFindings: BlockingFinding[];
|
|
161
|
+
evidenceReferences: string[];
|
|
162
|
+
passConditions: string[];
|
|
163
|
+
summary?: string;
|
|
164
|
+
}): RejectedReviewReceipt;
|
|
165
|
+
/**
|
|
166
|
+
* Build an ApprovedReviewReceipt.
|
|
167
|
+
* `scopeContent` is hashed to produce the fingerprint.
|
|
168
|
+
*/
|
|
169
|
+
export declare function buildApprovedReceipt(opts: {
|
|
170
|
+
agent: string;
|
|
171
|
+
sessionId?: string;
|
|
172
|
+
scopeContent: string;
|
|
173
|
+
scopeDescription: string;
|
|
174
|
+
checkedAspects: string[];
|
|
175
|
+
validatedClaims: string[];
|
|
176
|
+
caveats?: string[];
|
|
177
|
+
}): ApprovedReviewReceipt;
|
|
178
|
+
/**
|
|
179
|
+
* Build a structured context summary of prior receipts for critic drift
|
|
180
|
+
* verification. Returns a compact string that can be injected into context.
|
|
181
|
+
*
|
|
182
|
+
* Approved receipts that are scope-stale are flagged explicitly so the critic
|
|
183
|
+
* knows they are supporting evidence only, not proof of current state.
|
|
184
|
+
*
|
|
185
|
+
* @param receipts - Array of prior receipts (from readAllReceipts or readReceiptsByScopeHash)
|
|
186
|
+
* @param currentScopeContent - Optional current scope content for staleness check
|
|
187
|
+
* @param maxChars - Maximum output length (default 1000)
|
|
188
|
+
*/
|
|
189
|
+
export declare function buildReceiptContextForDrift(receipts: ReviewReceipt[], currentScopeContent?: string, maxChars?: number): string;
|