opencode-swarm 7.79.5 → 7.79.6
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 +114 -17
- package/dist/hooks/knowledge-validator.d.ts +16 -0
- package/dist/index.js +121 -30
- package/package.json +1 -1
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.79.
|
|
55
|
+
version: "7.79.6",
|
|
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",
|
|
@@ -39424,6 +39424,51 @@ import * as path18 from "path";
|
|
|
39424
39424
|
function normalizeText(text) {
|
|
39425
39425
|
return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
39426
39426
|
}
|
|
39427
|
+
function extractContextWords(text, word, contextWindow = 3) {
|
|
39428
|
+
const words = text.split(" ");
|
|
39429
|
+
const context = new Set;
|
|
39430
|
+
if (!word.includes(" ")) {
|
|
39431
|
+
let from = 0;
|
|
39432
|
+
let idx = words.indexOf(word, from);
|
|
39433
|
+
while (idx !== -1) {
|
|
39434
|
+
const start = Math.max(0, idx - contextWindow);
|
|
39435
|
+
const end = Math.min(words.length, idx + contextWindow + 1);
|
|
39436
|
+
for (let i2 = start;i2 < end; i2++) {
|
|
39437
|
+
if (i2 !== idx && words[i2] && words[i2].length > 0) {
|
|
39438
|
+
context.add(words[i2]);
|
|
39439
|
+
}
|
|
39440
|
+
}
|
|
39441
|
+
from = idx + 1;
|
|
39442
|
+
idx = words.indexOf(word, from);
|
|
39443
|
+
}
|
|
39444
|
+
return context;
|
|
39445
|
+
}
|
|
39446
|
+
const termLen = word.split(" ").length;
|
|
39447
|
+
let i = 0;
|
|
39448
|
+
while (i <= words.length - termLen) {
|
|
39449
|
+
const slice = words.slice(i, i + termLen).join(" ");
|
|
39450
|
+
if (slice === word) {
|
|
39451
|
+
const start = Math.max(0, i - contextWindow);
|
|
39452
|
+
const end = Math.min(words.length, i + termLen + contextWindow);
|
|
39453
|
+
for (let j = start;j < end; j++) {
|
|
39454
|
+
if (j < i || j >= i + termLen) {
|
|
39455
|
+
if (words[j] && words[j].length > 0) {
|
|
39456
|
+
context.add(words[j]);
|
|
39457
|
+
}
|
|
39458
|
+
}
|
|
39459
|
+
}
|
|
39460
|
+
i += termLen;
|
|
39461
|
+
} else {
|
|
39462
|
+
i += 1;
|
|
39463
|
+
}
|
|
39464
|
+
}
|
|
39465
|
+
return context;
|
|
39466
|
+
}
|
|
39467
|
+
function hasSignificantOverlap(set1, set22) {
|
|
39468
|
+
if (set1.size === 0 || set22.size === 0)
|
|
39469
|
+
return false;
|
|
39470
|
+
return [...set1].some((word) => set22.has(word));
|
|
39471
|
+
}
|
|
39427
39472
|
function detectContradiction(candidate, existingLessons) {
|
|
39428
39473
|
const candidateTags = inferTags(candidate);
|
|
39429
39474
|
if (candidateTags.length === 0)
|
|
@@ -39436,10 +39481,20 @@ function detectContradiction(candidate, existingLessons) {
|
|
|
39436
39481
|
continue;
|
|
39437
39482
|
const existingNorm = normalizeText(existing);
|
|
39438
39483
|
for (const [wordA, wordB] of NEGATION_PAIRS) {
|
|
39439
|
-
|
|
39440
|
-
|
|
39441
|
-
|
|
39442
|
-
|
|
39484
|
+
if (candidateNorm.includes(wordA) && existingNorm.includes(wordB)) {
|
|
39485
|
+
const contextA = extractContextWords(candidateNorm, wordA);
|
|
39486
|
+
const contextB = extractContextWords(existingNorm, wordB);
|
|
39487
|
+
if (hasSignificantOverlap(contextA, contextB)) {
|
|
39488
|
+
return true;
|
|
39489
|
+
}
|
|
39490
|
+
}
|
|
39491
|
+
if (candidateNorm.includes(wordB) && existingNorm.includes(wordA)) {
|
|
39492
|
+
const contextB = extractContextWords(candidateNorm, wordB);
|
|
39493
|
+
const contextA = extractContextWords(existingNorm, wordA);
|
|
39494
|
+
if (hasSignificantOverlap(contextA, contextB)) {
|
|
39495
|
+
return true;
|
|
39496
|
+
}
|
|
39497
|
+
}
|
|
39443
39498
|
}
|
|
39444
39499
|
}
|
|
39445
39500
|
return false;
|
|
@@ -41771,12 +41826,52 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
41771
41826
|
if (!_internals17.existsSync(resolved)) {
|
|
41772
41827
|
return { pruned: 0, remaining: 0 };
|
|
41773
41828
|
}
|
|
41774
|
-
const
|
|
41775
|
-
|
|
41829
|
+
const raw = _internals17.readFileSync(resolved, "utf-8");
|
|
41830
|
+
const lines = raw.split(`
|
|
41831
|
+
`);
|
|
41832
|
+
const entries = [];
|
|
41833
|
+
const preservedMarkers = [];
|
|
41834
|
+
for (const line of lines) {
|
|
41835
|
+
const trimmed = line.trim();
|
|
41836
|
+
if (!trimmed)
|
|
41837
|
+
continue;
|
|
41838
|
+
try {
|
|
41839
|
+
const parsed = JSON.parse(trimmed);
|
|
41840
|
+
const marker = parseFeedbackMarker(parsed);
|
|
41841
|
+
if (marker) {
|
|
41842
|
+
preservedMarkers.push(trimmed);
|
|
41843
|
+
continue;
|
|
41844
|
+
}
|
|
41845
|
+
const entry = parseSkillUsageEntry(parsed);
|
|
41846
|
+
if (entry) {
|
|
41847
|
+
entries.push(entry);
|
|
41848
|
+
}
|
|
41849
|
+
} catch {}
|
|
41850
|
+
}
|
|
41851
|
+
if (entries.length === 0) {
|
|
41852
|
+
if (preservedMarkers.length > 0) {
|
|
41853
|
+
const dir2 = path23.dirname(resolved);
|
|
41854
|
+
const tmpPath2 = path23.join(dir2, `skill-usage-${Date.now()}.tmp`);
|
|
41855
|
+
const content2 = preservedMarkers.join(`
|
|
41856
|
+
`).concat(preservedMarkers.length > 0 ? `
|
|
41857
|
+
` : "");
|
|
41858
|
+
try {
|
|
41859
|
+
_internals17.writeFileSync(tmpPath2, content2, "utf-8");
|
|
41860
|
+
_internals17.renameSync(tmpPath2, resolved);
|
|
41861
|
+
} catch (writeErr) {
|
|
41862
|
+
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
41863
|
+
try {
|
|
41864
|
+
if (_internals17.existsSync(tmpPath2)) {
|
|
41865
|
+
_internals17.writeFileSync(tmpPath2, "", "utf-8");
|
|
41866
|
+
}
|
|
41867
|
+
} catch {}
|
|
41868
|
+
return { pruned: 0, remaining: 0, error: msg };
|
|
41869
|
+
}
|
|
41870
|
+
}
|
|
41776
41871
|
return { pruned: 0, remaining: 0 };
|
|
41777
41872
|
}
|
|
41778
41873
|
const groups = new Map;
|
|
41779
|
-
for (const entry of
|
|
41874
|
+
for (const entry of entries) {
|
|
41780
41875
|
const list = groups.get(entry.skillPath);
|
|
41781
41876
|
if (list)
|
|
41782
41877
|
list.push(entry);
|
|
@@ -41785,22 +41880,24 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
41785
41880
|
}
|
|
41786
41881
|
let pruned = 0;
|
|
41787
41882
|
const surviving = [];
|
|
41788
|
-
groups.forEach((
|
|
41789
|
-
if (
|
|
41790
|
-
surviving.push(...
|
|
41883
|
+
groups.forEach((skillEntries) => {
|
|
41884
|
+
if (skillEntries.length <= maxEntriesPerSkill) {
|
|
41885
|
+
surviving.push(...skillEntries);
|
|
41791
41886
|
return;
|
|
41792
41887
|
}
|
|
41793
|
-
|
|
41794
|
-
const kept =
|
|
41795
|
-
pruned +=
|
|
41888
|
+
skillEntries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
|
|
41889
|
+
const kept = skillEntries.slice(0, maxEntriesPerSkill);
|
|
41890
|
+
pruned += skillEntries.length - kept.length;
|
|
41796
41891
|
surviving.push(...kept);
|
|
41797
41892
|
});
|
|
41798
41893
|
if (pruned === 0) {
|
|
41799
|
-
return { pruned: 0, remaining:
|
|
41894
|
+
return { pruned: 0, remaining: entries.length };
|
|
41800
41895
|
}
|
|
41801
41896
|
const dir = path23.dirname(resolved);
|
|
41802
41897
|
const tmpPath = path23.join(dir, `skill-usage-${Date.now()}.tmp`);
|
|
41803
|
-
const
|
|
41898
|
+
const entryLines = surviving.map((e) => JSON.stringify(e));
|
|
41899
|
+
const allLines = [...entryLines, ...preservedMarkers];
|
|
41900
|
+
const content = allLines.join(`
|
|
41804
41901
|
`).concat(`
|
|
41805
41902
|
`);
|
|
41806
41903
|
try {
|
|
@@ -41813,7 +41910,7 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
41813
41910
|
_internals17.writeFileSync(tmpPath, "", "utf-8");
|
|
41814
41911
|
}
|
|
41815
41912
|
} catch {}
|
|
41816
|
-
return { pruned: 0, remaining:
|
|
41913
|
+
return { pruned: 0, remaining: entries.length, error: msg };
|
|
41817
41914
|
}
|
|
41818
41915
|
return { pruned, remaining: surviving.length };
|
|
41819
41916
|
}
|
|
@@ -12,6 +12,20 @@ export declare const DANGEROUS_COMMAND_PATTERNS: RegExp[];
|
|
|
12
12
|
export declare const SECURITY_DEGRADING_PATTERNS: RegExp[];
|
|
13
13
|
export declare const INVISIBLE_FORMAT_CHARS: RegExp;
|
|
14
14
|
export declare const INJECTION_PATTERNS: RegExp[];
|
|
15
|
+
/**
|
|
16
|
+
* Extract context words around each occurrence of a target word (single tokens within a window).
|
|
17
|
+
* Context window is 3 words before and after, excluding the target word itself.
|
|
18
|
+
* Handles multi-word terms (e.g. "must not", "don't use") by scanning word slices.
|
|
19
|
+
*
|
|
20
|
+
* Note: this is an exact-word-match heuristic. Synonyms (e.g. "use" / "utilize")
|
|
21
|
+
* will not match across lessons. The 3-token window is bounded; more distant
|
|
22
|
+
* negation attachments will not be detected as contradictions.
|
|
23
|
+
*/
|
|
24
|
+
declare function extractContextWords(text: string, word: string, contextWindow?: number): Set<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Check if two sets of words have significant overlap (at least one word in common).
|
|
27
|
+
*/
|
|
28
|
+
declare function hasSignificantOverlap(set1: Set<string>, set2: Set<string>): boolean;
|
|
15
29
|
export declare function validateLesson(candidate: string, existingLessons: string[], meta: {
|
|
16
30
|
category: KnowledgeCategory;
|
|
17
31
|
scope: string;
|
|
@@ -90,4 +104,6 @@ export declare const _internals: {
|
|
|
90
104
|
auditEntryHealth: typeof auditEntryHealth;
|
|
91
105
|
quarantineEntry: typeof quarantineEntry;
|
|
92
106
|
restoreEntry: typeof restoreEntry;
|
|
107
|
+
extractContextWords: typeof extractContextWords;
|
|
108
|
+
hasSignificantOverlap: typeof hasSignificantOverlap;
|
|
93
109
|
};
|
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.79.
|
|
72
|
+
version: "7.79.6",
|
|
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",
|
|
@@ -61771,6 +61771,51 @@ import * as path36 from "node:path";
|
|
|
61771
61771
|
function normalizeText(text) {
|
|
61772
61772
|
return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
61773
61773
|
}
|
|
61774
|
+
function extractContextWords(text, word, contextWindow = 3) {
|
|
61775
|
+
const words = text.split(" ");
|
|
61776
|
+
const context = new Set;
|
|
61777
|
+
if (!word.includes(" ")) {
|
|
61778
|
+
let from = 0;
|
|
61779
|
+
let idx = words.indexOf(word, from);
|
|
61780
|
+
while (idx !== -1) {
|
|
61781
|
+
const start2 = Math.max(0, idx - contextWindow);
|
|
61782
|
+
const end = Math.min(words.length, idx + contextWindow + 1);
|
|
61783
|
+
for (let i3 = start2;i3 < end; i3++) {
|
|
61784
|
+
if (i3 !== idx && words[i3] && words[i3].length > 0) {
|
|
61785
|
+
context.add(words[i3]);
|
|
61786
|
+
}
|
|
61787
|
+
}
|
|
61788
|
+
from = idx + 1;
|
|
61789
|
+
idx = words.indexOf(word, from);
|
|
61790
|
+
}
|
|
61791
|
+
return context;
|
|
61792
|
+
}
|
|
61793
|
+
const termLen = word.split(" ").length;
|
|
61794
|
+
let i2 = 0;
|
|
61795
|
+
while (i2 <= words.length - termLen) {
|
|
61796
|
+
const slice = words.slice(i2, i2 + termLen).join(" ");
|
|
61797
|
+
if (slice === word) {
|
|
61798
|
+
const start2 = Math.max(0, i2 - contextWindow);
|
|
61799
|
+
const end = Math.min(words.length, i2 + termLen + contextWindow);
|
|
61800
|
+
for (let j = start2;j < end; j++) {
|
|
61801
|
+
if (j < i2 || j >= i2 + termLen) {
|
|
61802
|
+
if (words[j] && words[j].length > 0) {
|
|
61803
|
+
context.add(words[j]);
|
|
61804
|
+
}
|
|
61805
|
+
}
|
|
61806
|
+
}
|
|
61807
|
+
i2 += termLen;
|
|
61808
|
+
} else {
|
|
61809
|
+
i2 += 1;
|
|
61810
|
+
}
|
|
61811
|
+
}
|
|
61812
|
+
return context;
|
|
61813
|
+
}
|
|
61814
|
+
function hasSignificantOverlap(set1, set22) {
|
|
61815
|
+
if (set1.size === 0 || set22.size === 0)
|
|
61816
|
+
return false;
|
|
61817
|
+
return [...set1].some((word) => set22.has(word));
|
|
61818
|
+
}
|
|
61774
61819
|
function detectContradiction(candidate, existingLessons) {
|
|
61775
61820
|
const candidateTags = inferTags(candidate);
|
|
61776
61821
|
if (candidateTags.length === 0)
|
|
@@ -61783,10 +61828,20 @@ function detectContradiction(candidate, existingLessons) {
|
|
|
61783
61828
|
continue;
|
|
61784
61829
|
const existingNorm = normalizeText(existing);
|
|
61785
61830
|
for (const [wordA, wordB] of NEGATION_PAIRS) {
|
|
61786
|
-
|
|
61787
|
-
|
|
61788
|
-
|
|
61789
|
-
|
|
61831
|
+
if (candidateNorm.includes(wordA) && existingNorm.includes(wordB)) {
|
|
61832
|
+
const contextA = extractContextWords(candidateNorm, wordA);
|
|
61833
|
+
const contextB = extractContextWords(existingNorm, wordB);
|
|
61834
|
+
if (hasSignificantOverlap(contextA, contextB)) {
|
|
61835
|
+
return true;
|
|
61836
|
+
}
|
|
61837
|
+
}
|
|
61838
|
+
if (candidateNorm.includes(wordB) && existingNorm.includes(wordA)) {
|
|
61839
|
+
const contextB = extractContextWords(candidateNorm, wordB);
|
|
61840
|
+
const contextA = extractContextWords(existingNorm, wordA);
|
|
61841
|
+
if (hasSignificantOverlap(contextA, contextB)) {
|
|
61842
|
+
return true;
|
|
61843
|
+
}
|
|
61844
|
+
}
|
|
61790
61845
|
}
|
|
61791
61846
|
}
|
|
61792
61847
|
return false;
|
|
@@ -64410,12 +64465,52 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
64410
64465
|
if (!_internals27.existsSync(resolved)) {
|
|
64411
64466
|
return { pruned: 0, remaining: 0 };
|
|
64412
64467
|
}
|
|
64413
|
-
const
|
|
64414
|
-
|
|
64468
|
+
const raw = _internals27.readFileSync(resolved, "utf-8");
|
|
64469
|
+
const lines = raw.split(`
|
|
64470
|
+
`);
|
|
64471
|
+
const entries = [];
|
|
64472
|
+
const preservedMarkers = [];
|
|
64473
|
+
for (const line of lines) {
|
|
64474
|
+
const trimmed = line.trim();
|
|
64475
|
+
if (!trimmed)
|
|
64476
|
+
continue;
|
|
64477
|
+
try {
|
|
64478
|
+
const parsed = JSON.parse(trimmed);
|
|
64479
|
+
const marker = parseFeedbackMarker(parsed);
|
|
64480
|
+
if (marker) {
|
|
64481
|
+
preservedMarkers.push(trimmed);
|
|
64482
|
+
continue;
|
|
64483
|
+
}
|
|
64484
|
+
const entry = parseSkillUsageEntry(parsed);
|
|
64485
|
+
if (entry) {
|
|
64486
|
+
entries.push(entry);
|
|
64487
|
+
}
|
|
64488
|
+
} catch {}
|
|
64489
|
+
}
|
|
64490
|
+
if (entries.length === 0) {
|
|
64491
|
+
if (preservedMarkers.length > 0) {
|
|
64492
|
+
const dir2 = path41.dirname(resolved);
|
|
64493
|
+
const tmpPath2 = path41.join(dir2, `skill-usage-${Date.now()}.tmp`);
|
|
64494
|
+
const content2 = preservedMarkers.join(`
|
|
64495
|
+
`).concat(preservedMarkers.length > 0 ? `
|
|
64496
|
+
` : "");
|
|
64497
|
+
try {
|
|
64498
|
+
_internals27.writeFileSync(tmpPath2, content2, "utf-8");
|
|
64499
|
+
_internals27.renameSync(tmpPath2, resolved);
|
|
64500
|
+
} catch (writeErr) {
|
|
64501
|
+
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
64502
|
+
try {
|
|
64503
|
+
if (_internals27.existsSync(tmpPath2)) {
|
|
64504
|
+
_internals27.writeFileSync(tmpPath2, "", "utf-8");
|
|
64505
|
+
}
|
|
64506
|
+
} catch {}
|
|
64507
|
+
return { pruned: 0, remaining: 0, error: msg };
|
|
64508
|
+
}
|
|
64509
|
+
}
|
|
64415
64510
|
return { pruned: 0, remaining: 0 };
|
|
64416
64511
|
}
|
|
64417
64512
|
const groups = new Map;
|
|
64418
|
-
for (const entry of
|
|
64513
|
+
for (const entry of entries) {
|
|
64419
64514
|
const list = groups.get(entry.skillPath);
|
|
64420
64515
|
if (list)
|
|
64421
64516
|
list.push(entry);
|
|
@@ -64424,22 +64519,24 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
64424
64519
|
}
|
|
64425
64520
|
let pruned = 0;
|
|
64426
64521
|
const surviving = [];
|
|
64427
|
-
groups.forEach((
|
|
64428
|
-
if (
|
|
64429
|
-
surviving.push(...
|
|
64522
|
+
groups.forEach((skillEntries) => {
|
|
64523
|
+
if (skillEntries.length <= maxEntriesPerSkill) {
|
|
64524
|
+
surviving.push(...skillEntries);
|
|
64430
64525
|
return;
|
|
64431
64526
|
}
|
|
64432
|
-
|
|
64433
|
-
const kept =
|
|
64434
|
-
pruned +=
|
|
64527
|
+
skillEntries.sort((a, b) => b.timestamp > a.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0);
|
|
64528
|
+
const kept = skillEntries.slice(0, maxEntriesPerSkill);
|
|
64529
|
+
pruned += skillEntries.length - kept.length;
|
|
64435
64530
|
surviving.push(...kept);
|
|
64436
64531
|
});
|
|
64437
64532
|
if (pruned === 0) {
|
|
64438
|
-
return { pruned: 0, remaining:
|
|
64533
|
+
return { pruned: 0, remaining: entries.length };
|
|
64439
64534
|
}
|
|
64440
64535
|
const dir = path41.dirname(resolved);
|
|
64441
64536
|
const tmpPath = path41.join(dir, `skill-usage-${Date.now()}.tmp`);
|
|
64442
|
-
const
|
|
64537
|
+
const entryLines = surviving.map((e) => JSON.stringify(e));
|
|
64538
|
+
const allLines = [...entryLines, ...preservedMarkers];
|
|
64539
|
+
const content = allLines.join(`
|
|
64443
64540
|
`).concat(`
|
|
64444
64541
|
`);
|
|
64445
64542
|
try {
|
|
@@ -64452,7 +64549,7 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
64452
64549
|
_internals27.writeFileSync(tmpPath, "", "utf-8");
|
|
64453
64550
|
}
|
|
64454
64551
|
} catch {}
|
|
64455
|
-
return { pruned: 0, remaining:
|
|
64552
|
+
return { pruned: 0, remaining: entries.length, error: msg };
|
|
64456
64553
|
}
|
|
64457
64554
|
return { pruned, remaining: surviving.length };
|
|
64458
64555
|
}
|
|
@@ -98327,6 +98424,11 @@ Every listed directive ID MUST appear exactly once. If a directive carries a ver
|
|
|
98327
98424
|
FIXES: required changes if rejected
|
|
98328
98425
|
Use INFO only inside ISSUES for non-blocking suggestions. RISK reflects the highest blocking severity, so it never uses INFO.
|
|
98329
98426
|
|
|
98427
|
+
## OUTPUT ORDER FOR SKILL COMPLIANCE (when applicable)
|
|
98428
|
+
When SKILLS_USED_BY_CODER is provided, output TASK: immediately followed by SKILL_COMPLIANCE to ensure proper attribution:
|
|
98429
|
+
TASK: <task-id-or-unknown>
|
|
98430
|
+
SKILL_COMPLIANCE: <verdict> — <details>
|
|
98431
|
+
|
|
98330
98432
|
## RULES
|
|
98331
98433
|
- Be specific with line numbers
|
|
98332
98434
|
- Only flag real issues, not theoretical
|
|
@@ -131064,7 +131166,7 @@ async function withTurboStateLock(directory, sessionID, fn2, timeoutMs = 30000)
|
|
|
131064
131166
|
} catch (acquireErr) {
|
|
131065
131167
|
console.warn(`[lean-turbo] state lock acquisition error for ${sessionID} (${lockPath}), will retry: ${acquireErr instanceof Error ? acquireErr.message : String(acquireErr)}`);
|
|
131066
131168
|
}
|
|
131067
|
-
if (result
|
|
131169
|
+
if (result?.acquired) {
|
|
131068
131170
|
const lock = result.lock;
|
|
131069
131171
|
try {
|
|
131070
131172
|
return await fn2();
|
|
@@ -134666,18 +134768,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
|
|
|
134666
134768
|
safeWarn("[phase_complete] Design-doc drift check error (non-blocking):", docDriftError);
|
|
134667
134769
|
}
|
|
134668
134770
|
try {
|
|
134669
|
-
const
|
|
134670
|
-
let sinceTimestamp;
|
|
134671
|
-
try {
|
|
134672
|
-
const markerData = JSON.parse(fs111.readFileSync(markerPath, "utf-8"));
|
|
134673
|
-
sinceTimestamp = markerData.lastProcessedTimestamp;
|
|
134674
|
-
} catch {}
|
|
134675
|
-
const feedbackResult = await applySkillUsageFeedback(dir, {
|
|
134676
|
-
sinceTimestamp
|
|
134677
|
-
});
|
|
134678
|
-
try {
|
|
134679
|
-
fs111.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
|
|
134680
|
-
} catch {}
|
|
134771
|
+
const feedbackResult = await applySkillUsageFeedback(dir);
|
|
134681
134772
|
if (feedbackResult.processed > 0) {
|
|
134682
134773
|
const sessionState = swarmState.agentSessions.get(sessionID);
|
|
134683
134774
|
if (sessionState) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.79.
|
|
3
|
+
"version": "7.79.6",
|
|
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",
|