opencode-swarm 7.73.0 → 7.73.2
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
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "opencode-swarm",
|
|
55
|
-
version: "7.73.
|
|
55
|
+
version: "7.73.2",
|
|
56
56
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
57
57
|
main: "dist/index.js",
|
|
58
58
|
types: "dist/index.d.ts",
|
|
@@ -18752,7 +18752,8 @@ var init_schema = __esm(() => {
|
|
|
18752
18752
|
allowedPrefix: exports_external.array(exports_external.string()).optional(),
|
|
18753
18753
|
blockedZones: exports_external.array(exports_external.enum(["production", "test", "config", "generated", "docs", "build"])).optional(),
|
|
18754
18754
|
blockedGlobs: exports_external.array(exports_external.string()).optional(),
|
|
18755
|
-
allowedGlobs: exports_external.array(exports_external.string()).optional()
|
|
18755
|
+
allowedGlobs: exports_external.array(exports_external.string()).optional(),
|
|
18756
|
+
allowedCaseSensitiveGlobs: exports_external.array(exports_external.string()).optional()
|
|
18756
18757
|
});
|
|
18757
18758
|
AuthorityConfigSchema = exports_external.object({
|
|
18758
18759
|
enabled: exports_external.boolean().default(true),
|
|
@@ -40920,6 +40921,49 @@ var init_synonym_map = __esm(() => {
|
|
|
40920
40921
|
MIN_READ_CEILING_BYTES = 64 * 1024;
|
|
40921
40922
|
});
|
|
40922
40923
|
|
|
40924
|
+
// src/hooks/knowledge-reinforcement.ts
|
|
40925
|
+
function isActiveSwarmKnowledgeEntry(entry) {
|
|
40926
|
+
return !INACTIVE_STATUSES.has(entry.status);
|
|
40927
|
+
}
|
|
40928
|
+
function findActiveSwarmNearDuplicate(lesson, entries, threshold) {
|
|
40929
|
+
return findNearDuplicate(lesson, entries.filter(isActiveSwarmKnowledgeEntry), threshold);
|
|
40930
|
+
}
|
|
40931
|
+
function distinctPhaseCount(records) {
|
|
40932
|
+
const phases = new Set;
|
|
40933
|
+
for (const record3 of records ?? []) {
|
|
40934
|
+
if (Number.isInteger(record3.phase_number)) {
|
|
40935
|
+
phases.add(record3.phase_number);
|
|
40936
|
+
}
|
|
40937
|
+
}
|
|
40938
|
+
return phases.size;
|
|
40939
|
+
}
|
|
40940
|
+
function reinforceSwarmKnowledgeEntry(entry, confirmation) {
|
|
40941
|
+
if (!isActiveSwarmKnowledgeEntry(entry)) {
|
|
40942
|
+
return { entryId: entry.id, reinforced: false, reason: "inactive" };
|
|
40943
|
+
}
|
|
40944
|
+
if ((entry.confirmed_by ?? []).some((record3) => record3.phase_number === confirmation.phase_number)) {
|
|
40945
|
+
return {
|
|
40946
|
+
entryId: entry.id,
|
|
40947
|
+
reinforced: false,
|
|
40948
|
+
reason: "already_confirmed_phase"
|
|
40949
|
+
};
|
|
40950
|
+
}
|
|
40951
|
+
entry.confirmed_by = [...entry.confirmed_by ?? [], confirmation];
|
|
40952
|
+
entry.updated_at = confirmation.confirmed_at;
|
|
40953
|
+
entry.phases_alive = 0;
|
|
40954
|
+
entry.confidence = computeConfidence(distinctPhaseCount(entry.confirmed_by), entry.auto_generated ?? false);
|
|
40955
|
+
return { entryId: entry.id, reinforced: true, reason: "reinforced" };
|
|
40956
|
+
}
|
|
40957
|
+
var INACTIVE_STATUSES;
|
|
40958
|
+
var init_knowledge_reinforcement = __esm(() => {
|
|
40959
|
+
init_knowledge_store();
|
|
40960
|
+
INACTIVE_STATUSES = new Set([
|
|
40961
|
+
"archived",
|
|
40962
|
+
"quarantined",
|
|
40963
|
+
"quarantined_unactionable"
|
|
40964
|
+
]);
|
|
40965
|
+
});
|
|
40966
|
+
|
|
40923
40967
|
// src/hooks/skill-scoring.ts
|
|
40924
40968
|
import * as fs10 from "fs";
|
|
40925
40969
|
import * as path22 from "path";
|
|
@@ -42243,6 +42287,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
42243
42287
|
]);
|
|
42244
42288
|
const snapshotPlusNew = [...snapshot];
|
|
42245
42289
|
const toAdd = [];
|
|
42290
|
+
const pendingReinforcementIds = new Set;
|
|
42246
42291
|
for (const lesson of lessons) {
|
|
42247
42292
|
const tags = inferTags(lesson);
|
|
42248
42293
|
let category = "process";
|
|
@@ -42272,8 +42317,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
42272
42317
|
continue;
|
|
42273
42318
|
}
|
|
42274
42319
|
}
|
|
42275
|
-
const duplicate =
|
|
42320
|
+
const duplicate = findActiveSwarmNearDuplicate(lesson, snapshotPlusNew, config3.dedup_threshold);
|
|
42276
42321
|
if (duplicate) {
|
|
42322
|
+
pendingReinforcementIds.add(duplicate.id);
|
|
42277
42323
|
skipped++;
|
|
42278
42324
|
continue;
|
|
42279
42325
|
}
|
|
@@ -42354,7 +42400,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
42354
42400
|
} catch {}
|
|
42355
42401
|
continue;
|
|
42356
42402
|
}
|
|
42357
|
-
|
|
42403
|
+
const duplicate = findActiveSwarmNearDuplicate(entry.lesson, snapshotPlusNew, config3.dedup_threshold);
|
|
42404
|
+
if (duplicate) {
|
|
42405
|
+
pendingReinforcementIds.add(duplicate.id);
|
|
42358
42406
|
skipped++;
|
|
42359
42407
|
continue;
|
|
42360
42408
|
}
|
|
@@ -42363,15 +42411,48 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
42363
42411
|
}
|
|
42364
42412
|
} catch {}
|
|
42365
42413
|
let stored = 0;
|
|
42366
|
-
|
|
42414
|
+
let reinforced = 0;
|
|
42415
|
+
if (toAdd.length > 0 || pendingReinforcementIds.size > 0) {
|
|
42367
42416
|
await transactKnowledge(knowledgePath, (current) => {
|
|
42368
|
-
|
|
42369
|
-
const
|
|
42370
|
-
|
|
42371
|
-
|
|
42372
|
-
|
|
42373
|
-
|
|
42374
|
-
|
|
42417
|
+
let changed = false;
|
|
42418
|
+
for (const id of pendingReinforcementIds) {
|
|
42419
|
+
const existing = current.find((entry) => entry.id === id);
|
|
42420
|
+
if (!existing)
|
|
42421
|
+
continue;
|
|
42422
|
+
const result = reinforceSwarmKnowledgeEntry(existing, {
|
|
42423
|
+
phase_number: phaseInfo.phase_number,
|
|
42424
|
+
confirmed_at: new Date().toISOString(),
|
|
42425
|
+
project_name: projectName
|
|
42426
|
+
});
|
|
42427
|
+
if (result.reinforced) {
|
|
42428
|
+
reinforced++;
|
|
42429
|
+
changed = true;
|
|
42430
|
+
}
|
|
42431
|
+
}
|
|
42432
|
+
const trulyNew = [];
|
|
42433
|
+
for (const entry of toAdd) {
|
|
42434
|
+
const duplicate = findActiveSwarmNearDuplicate(entry.lesson, current, config3.dedup_threshold);
|
|
42435
|
+
if (duplicate) {
|
|
42436
|
+
skipped++;
|
|
42437
|
+
const result = reinforceSwarmKnowledgeEntry(duplicate, {
|
|
42438
|
+
phase_number: phaseInfo.phase_number,
|
|
42439
|
+
confirmed_at: new Date().toISOString(),
|
|
42440
|
+
project_name: projectName
|
|
42441
|
+
});
|
|
42442
|
+
if (result.reinforced) {
|
|
42443
|
+
reinforced++;
|
|
42444
|
+
changed = true;
|
|
42445
|
+
}
|
|
42446
|
+
continue;
|
|
42447
|
+
}
|
|
42448
|
+
trulyNew.push(entry);
|
|
42449
|
+
}
|
|
42450
|
+
if (trulyNew.length > 0) {
|
|
42451
|
+
current.push(...trulyNew);
|
|
42452
|
+
stored = trulyNew.length;
|
|
42453
|
+
changed = true;
|
|
42454
|
+
}
|
|
42455
|
+
return changed ? current : null;
|
|
42375
42456
|
});
|
|
42376
42457
|
}
|
|
42377
42458
|
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
@@ -42389,7 +42470,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
42389
42470
|
if (!options?.skipAutoPromotion) {
|
|
42390
42471
|
await _internals19.runAutoPromotion(directory, config3);
|
|
42391
42472
|
}
|
|
42392
|
-
return { stored, skipped, rejected, quarantined };
|
|
42473
|
+
return { stored, reinforced, skipped, rejected, quarantined };
|
|
42393
42474
|
}
|
|
42394
42475
|
async function runAutoPromotion(directory, config3) {
|
|
42395
42476
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -42502,6 +42583,7 @@ var init_knowledge_curator = __esm(() => {
|
|
|
42502
42583
|
init_synonym_map();
|
|
42503
42584
|
init_logger();
|
|
42504
42585
|
init_knowledge_events();
|
|
42586
|
+
init_knowledge_reinforcement();
|
|
42505
42587
|
init_knowledge_store();
|
|
42506
42588
|
init_knowledge_validator();
|
|
42507
42589
|
init_micro_reflector();
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -762,6 +762,7 @@ export declare const AgentAuthorityRuleSchema: z.ZodObject<{
|
|
|
762
762
|
}>>>;
|
|
763
763
|
blockedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
764
764
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
765
|
+
allowedCaseSensitiveGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
765
766
|
}, z.core.$strip>;
|
|
766
767
|
export type AgentAuthorityRule = z.infer<typeof AgentAuthorityRuleSchema>;
|
|
767
768
|
export declare const AuthorityConfigSchema: z.ZodObject<{
|
|
@@ -782,6 +783,7 @@ export declare const AuthorityConfigSchema: z.ZodObject<{
|
|
|
782
783
|
}>>>;
|
|
783
784
|
blockedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
784
785
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
786
|
+
allowedCaseSensitiveGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
785
787
|
}, z.core.$strip>>>;
|
|
786
788
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
787
789
|
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -1405,6 +1407,7 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1405
1407
|
}>>>;
|
|
1406
1408
|
blockedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1407
1409
|
allowedGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1410
|
+
allowedCaseSensitiveGlobs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1408
1411
|
}, z.core.$strip>>>;
|
|
1409
1412
|
universal_deny_prefixes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
1410
1413
|
verifier_config_paths: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PhaseConfirmationRecord, SwarmKnowledgeEntry } from './knowledge-types.js';
|
|
2
|
+
export type ReinforcementReason = 'reinforced' | 'already_confirmed_phase' | 'inactive';
|
|
3
|
+
export interface ReinforcementResult {
|
|
4
|
+
entryId: string;
|
|
5
|
+
reinforced: boolean;
|
|
6
|
+
reason: ReinforcementReason;
|
|
7
|
+
}
|
|
8
|
+
export declare function isActiveSwarmKnowledgeEntry(entry: SwarmKnowledgeEntry): boolean;
|
|
9
|
+
export declare function findActiveSwarmNearDuplicate(lesson: string, entries: SwarmKnowledgeEntry[], threshold: number): SwarmKnowledgeEntry | undefined;
|
|
10
|
+
export declare function reinforceSwarmKnowledgeEntry(entry: SwarmKnowledgeEntry, confirmation: PhaseConfirmationRecord): ReinforcementResult;
|
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ var package_default;
|
|
|
69
69
|
var init_package = __esm(() => {
|
|
70
70
|
package_default = {
|
|
71
71
|
name: "opencode-swarm",
|
|
72
|
-
version: "7.73.
|
|
72
|
+
version: "7.73.2",
|
|
73
73
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
74
74
|
main: "dist/index.js",
|
|
75
75
|
types: "dist/index.d.ts",
|
|
@@ -16085,7 +16085,8 @@ var init_schema = __esm(() => {
|
|
|
16085
16085
|
allowedPrefix: exports_external.array(exports_external.string()).optional(),
|
|
16086
16086
|
blockedZones: exports_external.array(exports_external.enum(["production", "test", "config", "generated", "docs", "build"])).optional(),
|
|
16087
16087
|
blockedGlobs: exports_external.array(exports_external.string()).optional(),
|
|
16088
|
-
allowedGlobs: exports_external.array(exports_external.string()).optional()
|
|
16088
|
+
allowedGlobs: exports_external.array(exports_external.string()).optional(),
|
|
16089
|
+
allowedCaseSensitiveGlobs: exports_external.array(exports_external.string()).optional()
|
|
16089
16090
|
});
|
|
16090
16091
|
AuthorityConfigSchema = exports_external.object({
|
|
16091
16092
|
enabled: exports_external.boolean().default(true),
|
|
@@ -25482,7 +25483,8 @@ function normalizePathWithCache(filePath, cwd) {
|
|
|
25482
25483
|
}
|
|
25483
25484
|
}
|
|
25484
25485
|
function getGlobMatcher(pattern, caseInsensitive = process.platform === "win32" || process.platform === "darwin") {
|
|
25485
|
-
const
|
|
25486
|
+
const cacheKey = `${caseInsensitive ? "nocase" : "case"}\x00${pattern}`;
|
|
25487
|
+
const cached2 = globMatcherCache.get(cacheKey);
|
|
25486
25488
|
if (cached2 !== undefined) {
|
|
25487
25489
|
return cached2;
|
|
25488
25490
|
}
|
|
@@ -25491,7 +25493,7 @@ function getGlobMatcher(pattern, caseInsensitive = process.platform === "win32"
|
|
|
25491
25493
|
dot: true,
|
|
25492
25494
|
nocase: caseInsensitive
|
|
25493
25495
|
});
|
|
25494
|
-
globMatcherCache.set(
|
|
25496
|
+
globMatcherCache.set(cacheKey, matcher);
|
|
25495
25497
|
return matcher;
|
|
25496
25498
|
} catch (err2) {
|
|
25497
25499
|
warn(`picomatch error for pattern "${pattern}": ${err2}`);
|
|
@@ -25553,7 +25555,8 @@ function buildEffectiveRules(authorityConfig) {
|
|
|
25553
25555
|
allowedPrefix: userRule.allowedPrefix ?? existing.allowedPrefix,
|
|
25554
25556
|
blockedZones: userRule.blockedZones ?? existing.blockedZones,
|
|
25555
25557
|
blockedGlobs: userRule.blockedGlobs ?? existing.blockedGlobs,
|
|
25556
|
-
allowedGlobs: userRule.allowedGlobs ?? existing.allowedGlobs
|
|
25558
|
+
allowedGlobs: userRule.allowedGlobs ?? existing.allowedGlobs,
|
|
25559
|
+
allowedCaseSensitiveGlobs: userRule.allowedCaseSensitiveGlobs ?? existing.allowedCaseSensitiveGlobs
|
|
25557
25560
|
};
|
|
25558
25561
|
}
|
|
25559
25562
|
return merged;
|
|
@@ -25657,6 +25660,15 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
|
|
|
25657
25660
|
return { allowed: true };
|
|
25658
25661
|
}
|
|
25659
25662
|
}
|
|
25663
|
+
if (rules.allowedCaseSensitiveGlobs && rules.allowedCaseSensitiveGlobs.length > 0) {
|
|
25664
|
+
const isCaseSensitiveGlobAllowed = rules.allowedCaseSensitiveGlobs.some((glob) => {
|
|
25665
|
+
const matcher = getGlobMatcher(glob, false);
|
|
25666
|
+
return matcher(normalizedPath);
|
|
25667
|
+
});
|
|
25668
|
+
if (isCaseSensitiveGlobAllowed) {
|
|
25669
|
+
return { allowed: true };
|
|
25670
|
+
}
|
|
25671
|
+
}
|
|
25660
25672
|
if (rules.blockedPrefix && rules.blockedPrefix.length > 0) {
|
|
25661
25673
|
for (const prefix of rules.blockedPrefix) {
|
|
25662
25674
|
if (normalizedPath.startsWith(prefix)) {
|
|
@@ -25745,7 +25757,25 @@ var init_file_authority = __esm(() => {
|
|
|
25745
25757
|
"**/test/**",
|
|
25746
25758
|
"**/__tests__/**",
|
|
25747
25759
|
"**/*.test.*",
|
|
25748
|
-
"**/*.spec.*"
|
|
25760
|
+
"**/*.spec.*",
|
|
25761
|
+
"test_*.py",
|
|
25762
|
+
"**/test_*.py",
|
|
25763
|
+
"*_test.py",
|
|
25764
|
+
"**/*_test.py",
|
|
25765
|
+
"*_test.go",
|
|
25766
|
+
"**/*_test.go",
|
|
25767
|
+
"*_spec.rb",
|
|
25768
|
+
"**/*_spec.rb",
|
|
25769
|
+
"*.Tests.ps1",
|
|
25770
|
+
"**/*.Tests.ps1"
|
|
25771
|
+
],
|
|
25772
|
+
allowedCaseSensitiveGlobs: [
|
|
25773
|
+
"*Test.java",
|
|
25774
|
+
"**/*Test.java",
|
|
25775
|
+
"*Test.kt",
|
|
25776
|
+
"**/*Test.kt",
|
|
25777
|
+
"*Tests.cs",
|
|
25778
|
+
"**/*Tests.cs"
|
|
25749
25779
|
],
|
|
25750
25780
|
blockedZones: ["generated"]
|
|
25751
25781
|
},
|
|
@@ -64255,6 +64285,49 @@ var init_synonym_map = __esm(() => {
|
|
|
64255
64285
|
MIN_READ_CEILING_BYTES = 64 * 1024;
|
|
64256
64286
|
});
|
|
64257
64287
|
|
|
64288
|
+
// src/hooks/knowledge-reinforcement.ts
|
|
64289
|
+
function isActiveSwarmKnowledgeEntry(entry) {
|
|
64290
|
+
return !INACTIVE_STATUSES.has(entry.status);
|
|
64291
|
+
}
|
|
64292
|
+
function findActiveSwarmNearDuplicate(lesson, entries, threshold) {
|
|
64293
|
+
return findNearDuplicate(lesson, entries.filter(isActiveSwarmKnowledgeEntry), threshold);
|
|
64294
|
+
}
|
|
64295
|
+
function distinctPhaseCount(records) {
|
|
64296
|
+
const phases = new Set;
|
|
64297
|
+
for (const record3 of records ?? []) {
|
|
64298
|
+
if (Number.isInteger(record3.phase_number)) {
|
|
64299
|
+
phases.add(record3.phase_number);
|
|
64300
|
+
}
|
|
64301
|
+
}
|
|
64302
|
+
return phases.size;
|
|
64303
|
+
}
|
|
64304
|
+
function reinforceSwarmKnowledgeEntry(entry, confirmation) {
|
|
64305
|
+
if (!isActiveSwarmKnowledgeEntry(entry)) {
|
|
64306
|
+
return { entryId: entry.id, reinforced: false, reason: "inactive" };
|
|
64307
|
+
}
|
|
64308
|
+
if ((entry.confirmed_by ?? []).some((record3) => record3.phase_number === confirmation.phase_number)) {
|
|
64309
|
+
return {
|
|
64310
|
+
entryId: entry.id,
|
|
64311
|
+
reinforced: false,
|
|
64312
|
+
reason: "already_confirmed_phase"
|
|
64313
|
+
};
|
|
64314
|
+
}
|
|
64315
|
+
entry.confirmed_by = [...entry.confirmed_by ?? [], confirmation];
|
|
64316
|
+
entry.updated_at = confirmation.confirmed_at;
|
|
64317
|
+
entry.phases_alive = 0;
|
|
64318
|
+
entry.confidence = computeConfidence(distinctPhaseCount(entry.confirmed_by), entry.auto_generated ?? false);
|
|
64319
|
+
return { entryId: entry.id, reinforced: true, reason: "reinforced" };
|
|
64320
|
+
}
|
|
64321
|
+
var INACTIVE_STATUSES;
|
|
64322
|
+
var init_knowledge_reinforcement = __esm(() => {
|
|
64323
|
+
init_knowledge_store();
|
|
64324
|
+
INACTIVE_STATUSES = new Set([
|
|
64325
|
+
"archived",
|
|
64326
|
+
"quarantined",
|
|
64327
|
+
"quarantined_unactionable"
|
|
64328
|
+
]);
|
|
64329
|
+
});
|
|
64330
|
+
|
|
64258
64331
|
// src/hooks/skill-scoring.ts
|
|
64259
64332
|
import * as fs21 from "node:fs";
|
|
64260
64333
|
import * as path41 from "node:path";
|
|
@@ -65808,6 +65881,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
65808
65881
|
]);
|
|
65809
65882
|
const snapshotPlusNew = [...snapshot];
|
|
65810
65883
|
const toAdd = [];
|
|
65884
|
+
const pendingReinforcementIds = new Set;
|
|
65811
65885
|
for (const lesson of lessons) {
|
|
65812
65886
|
const tags = inferTags(lesson);
|
|
65813
65887
|
let category = "process";
|
|
@@ -65837,8 +65911,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
65837
65911
|
continue;
|
|
65838
65912
|
}
|
|
65839
65913
|
}
|
|
65840
|
-
const duplicate =
|
|
65914
|
+
const duplicate = findActiveSwarmNearDuplicate(lesson, snapshotPlusNew, config3.dedup_threshold);
|
|
65841
65915
|
if (duplicate) {
|
|
65916
|
+
pendingReinforcementIds.add(duplicate.id);
|
|
65842
65917
|
skipped++;
|
|
65843
65918
|
continue;
|
|
65844
65919
|
}
|
|
@@ -65919,7 +65994,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
65919
65994
|
} catch {}
|
|
65920
65995
|
continue;
|
|
65921
65996
|
}
|
|
65922
|
-
|
|
65997
|
+
const duplicate = findActiveSwarmNearDuplicate(entry.lesson, snapshotPlusNew, config3.dedup_threshold);
|
|
65998
|
+
if (duplicate) {
|
|
65999
|
+
pendingReinforcementIds.add(duplicate.id);
|
|
65923
66000
|
skipped++;
|
|
65924
66001
|
continue;
|
|
65925
66002
|
}
|
|
@@ -65928,15 +66005,48 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
65928
66005
|
}
|
|
65929
66006
|
} catch {}
|
|
65930
66007
|
let stored = 0;
|
|
65931
|
-
|
|
66008
|
+
let reinforced = 0;
|
|
66009
|
+
if (toAdd.length > 0 || pendingReinforcementIds.size > 0) {
|
|
65932
66010
|
await transactKnowledge(knowledgePath, (current) => {
|
|
65933
|
-
|
|
65934
|
-
const
|
|
65935
|
-
|
|
65936
|
-
|
|
65937
|
-
|
|
65938
|
-
|
|
65939
|
-
|
|
66011
|
+
let changed = false;
|
|
66012
|
+
for (const id of pendingReinforcementIds) {
|
|
66013
|
+
const existing = current.find((entry) => entry.id === id);
|
|
66014
|
+
if (!existing)
|
|
66015
|
+
continue;
|
|
66016
|
+
const result = reinforceSwarmKnowledgeEntry(existing, {
|
|
66017
|
+
phase_number: phaseInfo.phase_number,
|
|
66018
|
+
confirmed_at: new Date().toISOString(),
|
|
66019
|
+
project_name: projectName
|
|
66020
|
+
});
|
|
66021
|
+
if (result.reinforced) {
|
|
66022
|
+
reinforced++;
|
|
66023
|
+
changed = true;
|
|
66024
|
+
}
|
|
66025
|
+
}
|
|
66026
|
+
const trulyNew = [];
|
|
66027
|
+
for (const entry of toAdd) {
|
|
66028
|
+
const duplicate = findActiveSwarmNearDuplicate(entry.lesson, current, config3.dedup_threshold);
|
|
66029
|
+
if (duplicate) {
|
|
66030
|
+
skipped++;
|
|
66031
|
+
const result = reinforceSwarmKnowledgeEntry(duplicate, {
|
|
66032
|
+
phase_number: phaseInfo.phase_number,
|
|
66033
|
+
confirmed_at: new Date().toISOString(),
|
|
66034
|
+
project_name: projectName
|
|
66035
|
+
});
|
|
66036
|
+
if (result.reinforced) {
|
|
66037
|
+
reinforced++;
|
|
66038
|
+
changed = true;
|
|
66039
|
+
}
|
|
66040
|
+
continue;
|
|
66041
|
+
}
|
|
66042
|
+
trulyNew.push(entry);
|
|
66043
|
+
}
|
|
66044
|
+
if (trulyNew.length > 0) {
|
|
66045
|
+
current.push(...trulyNew);
|
|
66046
|
+
stored = trulyNew.length;
|
|
66047
|
+
changed = true;
|
|
66048
|
+
}
|
|
66049
|
+
return changed ? current : null;
|
|
65940
66050
|
});
|
|
65941
66051
|
}
|
|
65942
66052
|
await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
|
|
@@ -65954,7 +66064,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
65954
66064
|
if (!options?.skipAutoPromotion) {
|
|
65955
66065
|
await _internals30.runAutoPromotion(directory, config3);
|
|
65956
66066
|
}
|
|
65957
|
-
return { stored, skipped, rejected, quarantined };
|
|
66067
|
+
return { stored, reinforced, skipped, rejected, quarantined };
|
|
65958
66068
|
}
|
|
65959
66069
|
async function runAutoPromotion(directory, config3) {
|
|
65960
66070
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -66067,6 +66177,7 @@ var init_knowledge_curator = __esm(() => {
|
|
|
66067
66177
|
init_synonym_map();
|
|
66068
66178
|
init_logger();
|
|
66069
66179
|
init_knowledge_events();
|
|
66180
|
+
init_knowledge_reinforcement();
|
|
66070
66181
|
init_knowledge_store();
|
|
66071
66182
|
init_knowledge_validator();
|
|
66072
66183
|
init_micro_reflector();
|
|
@@ -124912,10 +125023,10 @@ var knowledge_ack = createSwarmTool({
|
|
|
124912
125023
|
// src/tools/knowledge-add.ts
|
|
124913
125024
|
init_zod();
|
|
124914
125025
|
init_config();
|
|
125026
|
+
init_knowledge_reinforcement();
|
|
124915
125027
|
init_knowledge_store();
|
|
124916
125028
|
init_knowledge_validator();
|
|
124917
125029
|
init_manager();
|
|
124918
|
-
init_utils();
|
|
124919
125030
|
init_create_tool();
|
|
124920
125031
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
124921
125032
|
var VALID_CATEGORIES2 = [
|
|
@@ -125007,9 +125118,13 @@ var knowledge_add = createSwarmTool({
|
|
|
125007
125118
|
});
|
|
125008
125119
|
}
|
|
125009
125120
|
let project_name = "";
|
|
125121
|
+
let phase_number = 1;
|
|
125010
125122
|
try {
|
|
125011
125123
|
const plan = await loadPlan(directory);
|
|
125012
125124
|
project_name = plan?.title ?? "";
|
|
125125
|
+
if (typeof plan?.current_phase === "number") {
|
|
125126
|
+
phase_number = plan.current_phase;
|
|
125127
|
+
}
|
|
125013
125128
|
} catch {}
|
|
125014
125129
|
const entry = {
|
|
125015
125130
|
id: randomUUID15(),
|
|
@@ -125054,19 +125169,6 @@ var knowledge_add = createSwarmTool({
|
|
|
125054
125169
|
}
|
|
125055
125170
|
}
|
|
125056
125171
|
} catch {}
|
|
125057
|
-
try {
|
|
125058
|
-
const existingEntries = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
125059
|
-
const duplicate = findNearDuplicate(lesson, existingEntries, dedupThreshold);
|
|
125060
|
-
if (duplicate) {
|
|
125061
|
-
return JSON.stringify({
|
|
125062
|
-
success: false,
|
|
125063
|
-
id: duplicate.id,
|
|
125064
|
-
message: "near-duplicate of existing entry"
|
|
125065
|
-
});
|
|
125066
|
-
}
|
|
125067
|
-
} catch (err2) {
|
|
125068
|
-
warn("knowledge_add: dedup check failed — skipping near-duplicate detection", err2);
|
|
125069
|
-
}
|
|
125070
125172
|
const actionability = validateActionability(entry);
|
|
125071
125173
|
if (!actionability.actionable) {
|
|
125072
125174
|
try {
|
|
@@ -125082,7 +125184,55 @@ var knowledge_add = createSwarmTool({
|
|
|
125082
125184
|
}
|
|
125083
125185
|
try {
|
|
125084
125186
|
const maxEntries = config3?.knowledge?.swarm_max_entries ?? 100;
|
|
125085
|
-
|
|
125187
|
+
let duplicateResponse;
|
|
125188
|
+
await transactKnowledge(resolveSwarmKnowledgePath(directory), (existingEntries) => {
|
|
125189
|
+
const activeDuplicate = findActiveSwarmNearDuplicate(lesson, existingEntries, dedupThreshold);
|
|
125190
|
+
if (activeDuplicate) {
|
|
125191
|
+
const result = reinforceSwarmKnowledgeEntry(activeDuplicate, {
|
|
125192
|
+
phase_number,
|
|
125193
|
+
confirmed_at: new Date().toISOString(),
|
|
125194
|
+
project_name
|
|
125195
|
+
});
|
|
125196
|
+
duplicateResponse = {
|
|
125197
|
+
id: activeDuplicate.id,
|
|
125198
|
+
reinforced: result.reinforced,
|
|
125199
|
+
idempotent: result.reason === "already_confirmed_phase",
|
|
125200
|
+
inactive: false
|
|
125201
|
+
};
|
|
125202
|
+
return result.reinforced ? existingEntries : null;
|
|
125203
|
+
}
|
|
125204
|
+
const inactiveDuplicate = findNearDuplicate(lesson, existingEntries, dedupThreshold);
|
|
125205
|
+
if (inactiveDuplicate) {
|
|
125206
|
+
duplicateResponse = {
|
|
125207
|
+
id: inactiveDuplicate.id,
|
|
125208
|
+
reinforced: false,
|
|
125209
|
+
idempotent: false,
|
|
125210
|
+
inactive: true
|
|
125211
|
+
};
|
|
125212
|
+
return null;
|
|
125213
|
+
}
|
|
125214
|
+
const updated = [...existingEntries, entry];
|
|
125215
|
+
if (updated.length > maxEntries) {
|
|
125216
|
+
return updated.slice(updated.length - maxEntries);
|
|
125217
|
+
}
|
|
125218
|
+
return updated;
|
|
125219
|
+
});
|
|
125220
|
+
if (duplicateResponse) {
|
|
125221
|
+
if (duplicateResponse.inactive) {
|
|
125222
|
+
return JSON.stringify({
|
|
125223
|
+
success: false,
|
|
125224
|
+
id: duplicateResponse.id,
|
|
125225
|
+
message: "near-duplicate of inactive existing entry"
|
|
125226
|
+
});
|
|
125227
|
+
}
|
|
125228
|
+
return JSON.stringify({
|
|
125229
|
+
success: true,
|
|
125230
|
+
id: duplicateResponse.id,
|
|
125231
|
+
reinforced: duplicateResponse.reinforced,
|
|
125232
|
+
idempotent: duplicateResponse.idempotent,
|
|
125233
|
+
message: duplicateResponse.reinforced ? "near-duplicate reinforced existing entry" : "near-duplicate already confirmed for this phase"
|
|
125234
|
+
});
|
|
125235
|
+
}
|
|
125086
125236
|
} catch (err2) {
|
|
125087
125237
|
const message = err2 instanceof Error ? err2.message : "Unknown error";
|
|
125088
125238
|
return JSON.stringify({
|
|
@@ -130167,7 +130317,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
130167
130317
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
130168
130318
|
if (sessionState) {
|
|
130169
130319
|
sessionState.pendingAdvisoryMessages ??= [];
|
|
130170
|
-
sessionState.pendingAdvisoryMessages.push(`[CURATOR] Knowledge curation: ${curationResult.stored} stored, ${curationResult.skipped} skipped, ${curationResult.rejected} rejected, ${curationResult.quarantined} quarantined (unactionable).`);
|
|
130320
|
+
sessionState.pendingAdvisoryMessages.push(`[CURATOR] Knowledge curation: ${curationResult.stored} stored, ${curationResult.reinforced} reinforced, ${curationResult.skipped} skipped, ${curationResult.rejected} rejected, ${curationResult.quarantined} quarantined (unactionable).`);
|
|
130171
130321
|
}
|
|
130172
130322
|
}
|
|
130173
130323
|
await updateRetrievalOutcome(dir, `Phase ${phase}`, true);
|
|
@@ -141926,6 +142076,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
141926
142076
|
};
|
|
141927
142077
|
const evidencePath = writeSupervisorReport(dirResult.directory, report);
|
|
141928
142078
|
let knowledgeProposed = 0;
|
|
142079
|
+
let knowledgeReinforced = 0;
|
|
141929
142080
|
let knowledgeQuarantined = 0;
|
|
141930
142081
|
try {
|
|
141931
142082
|
const config3 = loadPluginConfig(dirResult.directory);
|
|
@@ -141942,6 +142093,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
141942
142093
|
}
|
|
141943
142094
|
});
|
|
141944
142095
|
knowledgeProposed = result.stored;
|
|
142096
|
+
knowledgeReinforced = result.reinforced;
|
|
141945
142097
|
knowledgeQuarantined = result.quarantined;
|
|
141946
142098
|
}
|
|
141947
142099
|
} catch {}
|
|
@@ -141963,6 +142115,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
|
|
|
141963
142115
|
verdict: args2.verdict,
|
|
141964
142116
|
findings_count: args2.findings.length,
|
|
141965
142117
|
knowledge_proposed: knowledgeProposed,
|
|
142118
|
+
knowledge_reinforced: knowledgeReinforced,
|
|
141966
142119
|
knowledge_quarantined: knowledgeQuarantined,
|
|
141967
142120
|
skills_proposed: skillsProposed,
|
|
141968
142121
|
evidence_path: evidencePath
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.73.
|
|
3
|
+
"version": "7.73.2",
|
|
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",
|