opencode-swarm 7.74.0 → 7.74.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 +474 -192
- package/dist/config/schema.d.ts +14 -0
- package/dist/hooks/knowledge-application.d.ts +1 -0
- package/dist/hooks/knowledge-curator.d.ts +7 -2
- package/dist/hooks/knowledge-events.d.ts +16 -9
- package/dist/hooks/knowledge-injector.d.ts +1 -1
- package/dist/hooks/knowledge-reader.d.ts +1 -0
- package/dist/hooks/knowledge-store.d.ts +3 -0
- package/dist/hooks/knowledge-types.d.ts +5 -0
- package/dist/hooks/knowledge-validator.d.ts +5 -6
- package/dist/hooks/micro-reflector.d.ts +2 -1
- package/dist/hooks/skill-scoring.d.ts +1 -1
- package/dist/hooks/skill-usage-log.d.ts +7 -2
- package/dist/index.js +834 -317
- package/dist/services/external-content-scanner.d.ts +67 -0
- package/dist/services/external-skill-validator.d.ts +3 -0
- package/dist/services/skill-generator.d.ts +5 -0
- package/dist/services/skill-improver-quota.d.ts +6 -4
- package/dist/services/skill-improver.d.ts +6 -2
- package/dist/services/unactionable-hardening.d.ts +2 -2
- package/package.json +1 -1
- package/dist/skills/index.d.ts +0 -30
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.74.
|
|
55
|
+
version: "7.74.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",
|
|
@@ -17572,7 +17572,7 @@ var init_tool_metadata = __esm(() => {
|
|
|
17572
17572
|
agents: ["architect", "coder"]
|
|
17573
17573
|
},
|
|
17574
17574
|
knowledge_archive: {
|
|
17575
|
-
description: "archive (default), quarantine, or purge a swarm knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
|
|
17575
|
+
description: "archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
|
|
17576
17576
|
agents: ["architect"]
|
|
17577
17577
|
},
|
|
17578
17578
|
swarm_memory_recall: {
|
|
@@ -18588,7 +18588,11 @@ var init_schema = __esm(() => {
|
|
|
18588
18588
|
cold_start_max_age_phases: exports_external.number().int().min(0).max(100).default(3),
|
|
18589
18589
|
synonym_min_cooccurrence: exports_external.number().int().min(1).max(100).default(3),
|
|
18590
18590
|
synonym_map_max_pairs: exports_external.number().int().min(1).max(1e4).default(500)
|
|
18591
|
-
}).optional()
|
|
18591
|
+
}).optional(),
|
|
18592
|
+
enrichment: exports_external.object({
|
|
18593
|
+
max_calls_per_day: exports_external.number().int().min(0).max(1000).default(30),
|
|
18594
|
+
quota_window: exports_external.enum(["utc", "local"]).default("utc")
|
|
18595
|
+
}).default({ max_calls_per_day: 30, quota_window: "utc" })
|
|
18592
18596
|
});
|
|
18593
18597
|
MemoryConfigSchema = exports_external.object({
|
|
18594
18598
|
enabled: exports_external.boolean().default(false),
|
|
@@ -18655,7 +18659,7 @@ var init_schema = __esm(() => {
|
|
|
18655
18659
|
llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000),
|
|
18656
18660
|
skill_generation_enabled: exports_external.boolean().default(true),
|
|
18657
18661
|
skill_generation_mode: exports_external.enum(["draft", "active"]).default("draft"),
|
|
18658
|
-
min_skill_confidence: exports_external.number().min(0).max(1).default(0.
|
|
18662
|
+
min_skill_confidence: exports_external.number().min(0).max(1).default(0.7),
|
|
18659
18663
|
min_skill_confirmations: exports_external.number().int().min(1).max(50).default(2)
|
|
18660
18664
|
});
|
|
18661
18665
|
ArchitecturalSupervisionConfigSchema = exports_external.object({
|
|
@@ -37561,34 +37565,56 @@ var init_event_bus = __esm(() => {
|
|
|
37561
37565
|
init_utils();
|
|
37562
37566
|
});
|
|
37563
37567
|
|
|
37568
|
+
// src/evidence/task-file.ts
|
|
37569
|
+
import { renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
|
|
37570
|
+
import * as path12 from "path";
|
|
37571
|
+
function taskEvidenceRelPath(taskId) {
|
|
37572
|
+
return path12.join("evidence", `${taskId}.json`);
|
|
37573
|
+
}
|
|
37574
|
+
function taskEvidencePath(directory, taskId) {
|
|
37575
|
+
return path12.join(directory, ".swarm", taskEvidenceRelPath(taskId));
|
|
37576
|
+
}
|
|
37577
|
+
async function atomicWriteFile(targetPath, content) {
|
|
37578
|
+
const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
37579
|
+
try {
|
|
37580
|
+
await bunWrite(tempPath, content);
|
|
37581
|
+
_internals14.renameSync(tempPath, targetPath);
|
|
37582
|
+
} finally {
|
|
37583
|
+
try {
|
|
37584
|
+
_internals14.unlinkSync(tempPath);
|
|
37585
|
+
} catch {}
|
|
37586
|
+
}
|
|
37587
|
+
}
|
|
37588
|
+
var _internals14;
|
|
37589
|
+
var init_task_file = __esm(() => {
|
|
37590
|
+
init_bun_compat();
|
|
37591
|
+
init_lock();
|
|
37592
|
+
_internals14 = {
|
|
37593
|
+
renameSync: renameSync6,
|
|
37594
|
+
unlinkSync: unlinkSync4
|
|
37595
|
+
};
|
|
37596
|
+
});
|
|
37597
|
+
|
|
37564
37598
|
// src/hooks/knowledge-events.ts
|
|
37565
37599
|
import { existsSync as existsSync9 } from "fs";
|
|
37566
|
-
import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile2,
|
|
37567
|
-
import * as
|
|
37600
|
+
import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
37601
|
+
import * as path13 from "path";
|
|
37568
37602
|
function resolveKnowledgeEventsPath(directory) {
|
|
37569
|
-
return
|
|
37603
|
+
return path13.join(directory, ".swarm", "knowledge-events.jsonl");
|
|
37604
|
+
}
|
|
37605
|
+
function resolveKnowledgeCounterBaselinePath(directory) {
|
|
37606
|
+
return path13.join(directory, ".swarm", "knowledge-counter-baseline.json");
|
|
37570
37607
|
}
|
|
37571
37608
|
function resolveLegacyApplicationLogPath(directory) {
|
|
37572
|
-
return
|
|
37609
|
+
return path13.join(directory, ".swarm", "knowledge-application.jsonl");
|
|
37573
37610
|
}
|
|
37574
37611
|
async function readKnowledgeEvents(directory) {
|
|
37575
37612
|
const filePath = resolveKnowledgeEventsPath(directory);
|
|
37576
37613
|
if (!existsSync9(filePath))
|
|
37577
37614
|
return [];
|
|
37578
37615
|
const content = await readFile2(filePath, "utf-8");
|
|
37579
|
-
|
|
37580
|
-
|
|
37581
|
-
`)) {
|
|
37582
|
-
const trimmed = line.trim();
|
|
37583
|
-
if (!trimmed)
|
|
37584
|
-
continue;
|
|
37585
|
-
try {
|
|
37586
|
-
out.push(JSON.parse(trimmed));
|
|
37587
|
-
} catch {
|
|
37588
|
-
warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
|
|
37589
|
-
}
|
|
37590
|
-
}
|
|
37591
|
-
return out;
|
|
37616
|
+
return parseEventLines(content.split(`
|
|
37617
|
+
`), filePath);
|
|
37592
37618
|
}
|
|
37593
37619
|
async function readLegacyApplicationRecords(directory) {
|
|
37594
37620
|
const filePath = resolveLegacyApplicationLogPath(directory);
|
|
@@ -37624,6 +37650,29 @@ function emptyRollup() {
|
|
|
37624
37650
|
violation_timestamps: []
|
|
37625
37651
|
};
|
|
37626
37652
|
}
|
|
37653
|
+
function cloneRollup(input) {
|
|
37654
|
+
return {
|
|
37655
|
+
...emptyRollup(),
|
|
37656
|
+
...input,
|
|
37657
|
+
violation_timestamps: [...input.violation_timestamps ?? []]
|
|
37658
|
+
};
|
|
37659
|
+
}
|
|
37660
|
+
function cloneRollupMap(input) {
|
|
37661
|
+
const out = new Map;
|
|
37662
|
+
for (const [id, rollup] of input) {
|
|
37663
|
+
out.set(id, cloneRollup(rollup));
|
|
37664
|
+
}
|
|
37665
|
+
return out;
|
|
37666
|
+
}
|
|
37667
|
+
function normalizeRollupTimestamps(rollup) {
|
|
37668
|
+
if (rollup.violation_timestamps.length > 1) {
|
|
37669
|
+
rollup.violation_timestamps.sort((a, b) => a < b ? 1 : a > b ? -1 : 0);
|
|
37670
|
+
}
|
|
37671
|
+
if (rollup.violation_timestamps.length > MAX_VIOLATION_TIMESTAMPS) {
|
|
37672
|
+
rollup.violation_timestamps = rollup.violation_timestamps.slice(0, MAX_VIOLATION_TIMESTAMPS);
|
|
37673
|
+
}
|
|
37674
|
+
return rollup;
|
|
37675
|
+
}
|
|
37627
37676
|
function get(map3, id) {
|
|
37628
37677
|
let r = map3.get(id);
|
|
37629
37678
|
if (!r) {
|
|
@@ -37637,9 +37686,72 @@ function maxIso(current, candidate) {
|
|
|
37637
37686
|
return candidate;
|
|
37638
37687
|
return candidate > current ? candidate : current;
|
|
37639
37688
|
}
|
|
37640
|
-
function
|
|
37689
|
+
async function readCounterBaseline(directory) {
|
|
37690
|
+
const filePath = resolveKnowledgeCounterBaselinePath(directory);
|
|
37691
|
+
if (!existsSync9(filePath))
|
|
37692
|
+
return new Map;
|
|
37693
|
+
const raw = JSON.parse(await readFile2(filePath, "utf-8"));
|
|
37694
|
+
const map3 = new Map;
|
|
37695
|
+
for (const [id, rollup] of Object.entries(raw)) {
|
|
37696
|
+
map3.set(id, normalizeRollupTimestamps(cloneRollup(rollup)));
|
|
37697
|
+
}
|
|
37698
|
+
return map3;
|
|
37699
|
+
}
|
|
37700
|
+
async function statCacheKey(filePath) {
|
|
37701
|
+
try {
|
|
37702
|
+
const fileStat = await stat2(filePath);
|
|
37703
|
+
return `${fileStat.mtimeMs}:${fileStat.ctimeMs}:${fileStat.size}`;
|
|
37704
|
+
} catch (err) {
|
|
37705
|
+
if (err?.code === "ENOENT")
|
|
37706
|
+
return "missing";
|
|
37707
|
+
throw err;
|
|
37708
|
+
}
|
|
37709
|
+
}
|
|
37710
|
+
async function buildCounterRollupCacheKey(directory) {
|
|
37711
|
+
const [eventsKey, legacyKey, baselineKey] = await Promise.all([
|
|
37712
|
+
statCacheKey(resolveKnowledgeEventsPath(directory)),
|
|
37713
|
+
statCacheKey(resolveLegacyApplicationLogPath(directory)),
|
|
37714
|
+
statCacheKey(resolveKnowledgeCounterBaselinePath(directory))
|
|
37715
|
+
]);
|
|
37716
|
+
return `${eventsKey}|${legacyKey}|${baselineKey}`;
|
|
37717
|
+
}
|
|
37718
|
+
function setCounterRollupCache(directory, key, rollups) {
|
|
37719
|
+
if (counterRollupCache.has(directory)) {
|
|
37720
|
+
counterRollupCache.delete(directory);
|
|
37721
|
+
}
|
|
37722
|
+
counterRollupCache.set(directory, {
|
|
37723
|
+
key,
|
|
37724
|
+
rollups: cloneRollupMap(rollups)
|
|
37725
|
+
});
|
|
37726
|
+
while (counterRollupCache.size > MAX_COUNTER_ROLLUP_CACHE_DIRS) {
|
|
37727
|
+
const oldestKey = counterRollupCache.keys().next().value;
|
|
37728
|
+
if (oldestKey === undefined)
|
|
37729
|
+
break;
|
|
37730
|
+
counterRollupCache.delete(oldestKey);
|
|
37731
|
+
}
|
|
37732
|
+
}
|
|
37733
|
+
function parseEventLines(lines, filePath) {
|
|
37734
|
+
const out = [];
|
|
37735
|
+
for (const line of lines) {
|
|
37736
|
+
const trimmed = line.trim();
|
|
37737
|
+
if (!trimmed)
|
|
37738
|
+
continue;
|
|
37739
|
+
try {
|
|
37740
|
+
out.push(JSON.parse(trimmed));
|
|
37741
|
+
} catch {
|
|
37742
|
+
warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
|
|
37743
|
+
}
|
|
37744
|
+
}
|
|
37745
|
+
return out;
|
|
37746
|
+
}
|
|
37747
|
+
function recomputeCounters(events, legacyRecords = [], baseline = new Map) {
|
|
37641
37748
|
const map3 = new Map;
|
|
37642
37749
|
const retrievedIds = new Set;
|
|
37750
|
+
for (const [id, rollup] of baseline) {
|
|
37751
|
+
map3.set(id, cloneRollup(rollup));
|
|
37752
|
+
if ((rollup.shown_count ?? 0) > 0)
|
|
37753
|
+
retrievedIds.add(id);
|
|
37754
|
+
}
|
|
37643
37755
|
for (const e of events) {
|
|
37644
37756
|
switch (e.type) {
|
|
37645
37757
|
case "retrieved": {
|
|
@@ -37715,22 +37827,27 @@ function recomputeCounters(events, legacyRecords = []) {
|
|
|
37715
37827
|
}
|
|
37716
37828
|
}
|
|
37717
37829
|
for (const r of map3.values()) {
|
|
37718
|
-
|
|
37719
|
-
r.violation_timestamps.sort((a, b) => a < b ? 1 : a > b ? -1 : 0);
|
|
37720
|
-
}
|
|
37721
|
-
if (r.violation_timestamps.length > MAX_VIOLATION_TIMESTAMPS) {
|
|
37722
|
-
r.violation_timestamps = r.violation_timestamps.slice(0, MAX_VIOLATION_TIMESTAMPS);
|
|
37723
|
-
}
|
|
37830
|
+
normalizeRollupTimestamps(r);
|
|
37724
37831
|
}
|
|
37725
37832
|
return map3;
|
|
37726
37833
|
}
|
|
37727
37834
|
async function readKnowledgeCounterRollups(directory) {
|
|
37728
37835
|
try {
|
|
37729
|
-
const
|
|
37836
|
+
const cacheKey = await buildCounterRollupCacheKey(directory);
|
|
37837
|
+
const cached3 = counterRollupCache.get(directory);
|
|
37838
|
+
if (cached3?.key === cacheKey) {
|
|
37839
|
+
counterRollupCache.delete(directory);
|
|
37840
|
+
counterRollupCache.set(directory, cached3);
|
|
37841
|
+
return cloneRollupMap(cached3.rollups);
|
|
37842
|
+
}
|
|
37843
|
+
const [events, legacyRecords, baseline] = await Promise.all([
|
|
37730
37844
|
readKnowledgeEvents(directory),
|
|
37731
|
-
readLegacyApplicationRecords(directory)
|
|
37845
|
+
readLegacyApplicationRecords(directory),
|
|
37846
|
+
readCounterBaseline(directory)
|
|
37732
37847
|
]);
|
|
37733
|
-
|
|
37848
|
+
const rollups = recomputeCounters(events, legacyRecords, baseline);
|
|
37849
|
+
setCounterRollupCache(directory, cacheKey, rollups);
|
|
37850
|
+
return cloneRollupMap(rollups);
|
|
37734
37851
|
} catch (err) {
|
|
37735
37852
|
warn(`[knowledge-events] readKnowledgeCounterRollups failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
37736
37853
|
return new Map;
|
|
@@ -37749,10 +37866,12 @@ function effectiveRetrievalOutcomes(stored, rollup) {
|
|
|
37749
37866
|
...rollup
|
|
37750
37867
|
};
|
|
37751
37868
|
}
|
|
37752
|
-
var import_proper_lockfile3, RECEIPT_EVENT_TYPES, MAX_VIOLATION_TIMESTAMPS = 10;
|
|
37869
|
+
var import_proper_lockfile3, counterRollupCache, MAX_COUNTER_ROLLUP_CACHE_DIRS = 32, RECEIPT_EVENT_TYPES, MAX_VIOLATION_TIMESTAMPS = 10;
|
|
37753
37870
|
var init_knowledge_events = __esm(() => {
|
|
37871
|
+
init_task_file();
|
|
37754
37872
|
init_logger();
|
|
37755
37873
|
import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
37874
|
+
counterRollupCache = new Map;
|
|
37756
37875
|
RECEIPT_EVENT_TYPES = new Set([
|
|
37757
37876
|
"acknowledged",
|
|
37758
37877
|
"applied",
|
|
@@ -37764,36 +37883,6 @@ var init_knowledge_events = __esm(() => {
|
|
|
37764
37883
|
]);
|
|
37765
37884
|
});
|
|
37766
37885
|
|
|
37767
|
-
// src/evidence/task-file.ts
|
|
37768
|
-
import { renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
|
|
37769
|
-
import * as path13 from "path";
|
|
37770
|
-
function taskEvidenceRelPath(taskId) {
|
|
37771
|
-
return path13.join("evidence", `${taskId}.json`);
|
|
37772
|
-
}
|
|
37773
|
-
function taskEvidencePath(directory, taskId) {
|
|
37774
|
-
return path13.join(directory, ".swarm", taskEvidenceRelPath(taskId));
|
|
37775
|
-
}
|
|
37776
|
-
async function atomicWriteFile(targetPath, content) {
|
|
37777
|
-
const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
37778
|
-
try {
|
|
37779
|
-
await bunWrite(tempPath, content);
|
|
37780
|
-
_internals14.renameSync(tempPath, targetPath);
|
|
37781
|
-
} finally {
|
|
37782
|
-
try {
|
|
37783
|
-
_internals14.unlinkSync(tempPath);
|
|
37784
|
-
} catch {}
|
|
37785
|
-
}
|
|
37786
|
-
}
|
|
37787
|
-
var _internals14;
|
|
37788
|
-
var init_task_file = __esm(() => {
|
|
37789
|
-
init_bun_compat();
|
|
37790
|
-
init_lock();
|
|
37791
|
-
_internals14 = {
|
|
37792
|
-
renameSync: renameSync6,
|
|
37793
|
-
unlinkSync: unlinkSync4
|
|
37794
|
-
};
|
|
37795
|
-
});
|
|
37796
|
-
|
|
37797
37886
|
// src/hooks/knowledge-store.ts
|
|
37798
37887
|
import { existsSync as existsSync10 } from "fs";
|
|
37799
37888
|
import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile3 } from "fs/promises";
|
|
@@ -37998,9 +38087,46 @@ async function enforceKnowledgeCap(filePath, maxEntries) {
|
|
|
37998
38087
|
await transactKnowledge(filePath, (entries) => {
|
|
37999
38088
|
if (entries.length <= maxEntries)
|
|
38000
38089
|
return null;
|
|
38001
|
-
return
|
|
38090
|
+
return selectKnowledgeCapSurvivors(entries, maxEntries);
|
|
38002
38091
|
});
|
|
38003
38092
|
}
|
|
38093
|
+
function selectKnowledgeCapSurvivors(entries, maxEntries) {
|
|
38094
|
+
if (entries.length <= maxEntries)
|
|
38095
|
+
return entries;
|
|
38096
|
+
if (maxEntries <= 0)
|
|
38097
|
+
return [];
|
|
38098
|
+
const candidates = entries.map((entry, index) => {
|
|
38099
|
+
const maybeKnowledge = entry;
|
|
38100
|
+
return {
|
|
38101
|
+
entry,
|
|
38102
|
+
index,
|
|
38103
|
+
status: maybeKnowledge.status,
|
|
38104
|
+
outcomeSignal: computeOutcomeSignal(maybeKnowledge.retrieval_outcomes)
|
|
38105
|
+
};
|
|
38106
|
+
});
|
|
38107
|
+
const allPromoted = candidates.every((c) => c.status === "promoted");
|
|
38108
|
+
const evictable = allPromoted ? candidates : candidates.filter((c) => c.status !== "promoted");
|
|
38109
|
+
const targetDropCount = entries.length - maxEntries;
|
|
38110
|
+
const dropCount = Math.min(targetDropCount, evictable.length);
|
|
38111
|
+
if (dropCount <= 0)
|
|
38112
|
+
return entries;
|
|
38113
|
+
const drop = new Set([...evictable].sort((a, b) => {
|
|
38114
|
+
const inactiveDelta = getKnowledgeCapStatusPriority(a.status) - getKnowledgeCapStatusPriority(b.status);
|
|
38115
|
+
if (inactiveDelta !== 0)
|
|
38116
|
+
return inactiveDelta;
|
|
38117
|
+
const signalDelta = a.outcomeSignal - b.outcomeSignal;
|
|
38118
|
+
if (signalDelta !== 0)
|
|
38119
|
+
return signalDelta;
|
|
38120
|
+
return a.index - b.index;
|
|
38121
|
+
}).slice(0, dropCount).map((c) => c.index));
|
|
38122
|
+
return candidates.filter((c) => !drop.has(c.index)).map((c) => c.entry);
|
|
38123
|
+
}
|
|
38124
|
+
function getKnowledgeCapStatusPriority(status) {
|
|
38125
|
+
if (status === "archived" || status === "quarantined" || status === "quarantined_unactionable") {
|
|
38126
|
+
return 0;
|
|
38127
|
+
}
|
|
38128
|
+
return 1;
|
|
38129
|
+
}
|
|
38004
38130
|
async function appendRejectedLesson(directory, lesson, maxEntries = 20) {
|
|
38005
38131
|
const filePath = resolveSwarmRejectedPath(directory);
|
|
38006
38132
|
await transactKnowledge(filePath, (existing) => {
|
|
@@ -38661,7 +38787,7 @@ function validateLesson(candidate, existingLessons, meta3) {
|
|
|
38661
38787
|
};
|
|
38662
38788
|
}
|
|
38663
38789
|
const normalizedCandidate = candidate.normalize("NFKC").replace(INVISIBLE_FORMAT_CHARS, " ").replace(/\s+/g, " ").toLowerCase();
|
|
38664
|
-
for (const pattern of
|
|
38790
|
+
for (const pattern of DANGEROUS_COMMAND_ERROR_PATTERNS) {
|
|
38665
38791
|
if (pattern.test(normalizedCandidate)) {
|
|
38666
38792
|
return {
|
|
38667
38793
|
valid: false,
|
|
@@ -38671,6 +38797,16 @@ function validateLesson(candidate, existingLessons, meta3) {
|
|
|
38671
38797
|
};
|
|
38672
38798
|
}
|
|
38673
38799
|
}
|
|
38800
|
+
for (const pattern of DANGEROUS_COMMAND_WARNING_PATTERNS) {
|
|
38801
|
+
if (pattern.test(normalizedCandidate)) {
|
|
38802
|
+
return {
|
|
38803
|
+
valid: true,
|
|
38804
|
+
layer: 2,
|
|
38805
|
+
reason: "potentially dangerous command pattern queued for review",
|
|
38806
|
+
severity: "warning"
|
|
38807
|
+
};
|
|
38808
|
+
}
|
|
38809
|
+
}
|
|
38674
38810
|
for (const pattern of SECURITY_DEGRADING_PATTERNS) {
|
|
38675
38811
|
if (pattern.test(normalizedCandidate)) {
|
|
38676
38812
|
return {
|
|
@@ -38693,10 +38829,10 @@ function validateLesson(candidate, existingLessons, meta3) {
|
|
|
38693
38829
|
}
|
|
38694
38830
|
if (detectContradiction(candidate, existingLessons)) {
|
|
38695
38831
|
return {
|
|
38696
|
-
valid:
|
|
38832
|
+
valid: true,
|
|
38697
38833
|
layer: 3,
|
|
38698
|
-
reason: "
|
|
38699
|
-
severity: "
|
|
38834
|
+
reason: "possible contradiction with an existing lesson with shared tags",
|
|
38835
|
+
severity: "warning"
|
|
38700
38836
|
};
|
|
38701
38837
|
}
|
|
38702
38838
|
if (isVagueLesson(candidate)) {
|
|
@@ -38836,31 +38972,22 @@ async function appendUnactionable(directory, entry, reason) {
|
|
|
38836
38972
|
const filePath = resolveUnactionablePath(directory);
|
|
38837
38973
|
const dirPath = path15.dirname(filePath);
|
|
38838
38974
|
await mkdir4(dirPath, { recursive: true });
|
|
38839
|
-
|
|
38840
|
-
try {
|
|
38841
|
-
release = await import_proper_lockfile5.default.lock(dirPath, {
|
|
38842
|
-
retries: { retries: 50, minTimeout: 10, maxTimeout: 100 },
|
|
38843
|
-
stale: 5000
|
|
38844
|
-
});
|
|
38975
|
+
await transactKnowledge(filePath, (existing) => {
|
|
38845
38976
|
const record3 = {
|
|
38846
38977
|
...entry,
|
|
38847
38978
|
status: "quarantined_unactionable",
|
|
38848
38979
|
unactionable_reason: reason,
|
|
38849
38980
|
quarantined_at: new Date().toISOString()
|
|
38850
38981
|
};
|
|
38851
|
-
|
|
38852
|
-
|
|
38853
|
-
|
|
38854
|
-
|
|
38855
|
-
|
|
38856
|
-
await atomicWriteFile(filePath, `${trimmed.map((e) => JSON.stringify(e)).join(`
|
|
38857
|
-
`)}
|
|
38858
|
-
`);
|
|
38982
|
+
const duplicate = findNearDuplicate(record3.lesson, existing, 0.6);
|
|
38983
|
+
if (duplicate?.unactionable_reason === reason) {
|
|
38984
|
+
duplicate.quarantined_at = record3.quarantined_at;
|
|
38985
|
+
duplicate.updated_at = record3.updated_at;
|
|
38986
|
+
return existing;
|
|
38859
38987
|
}
|
|
38860
|
-
|
|
38861
|
-
|
|
38862
|
-
|
|
38863
|
-
}
|
|
38988
|
+
const next = [...existing, record3];
|
|
38989
|
+
return next.length > 200 ? next.slice(-200) : next;
|
|
38990
|
+
});
|
|
38864
38991
|
}
|
|
38865
38992
|
async function quarantineEntry(directory, entryId, reason, reportedBy) {
|
|
38866
38993
|
if (!directory || directory.includes("..")) {
|
|
@@ -38994,28 +39121,34 @@ async function restoreEntry(directory, entryId) {
|
|
|
38994
39121
|
}
|
|
38995
39122
|
}
|
|
38996
39123
|
}
|
|
38997
|
-
var import_proper_lockfile5, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, ACTIONABLE_STRING_MAX = 200, ACTIONABLE_LIST_MAX = 20, NAME_PATTERN, SOURCE_REF_FORBIDDEN, ALLOWED_SKILL_PATH_PREFIXES, VALID_DIRECTIVE_PRIORITIES;
|
|
39124
|
+
var import_proper_lockfile5, DANGEROUS_COMMAND_ERROR_PATTERNS, DANGEROUS_COMMAND_WARNING_PATTERNS, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, ACTIONABLE_STRING_MAX = 200, ACTIONABLE_LIST_MAX = 20, NAME_PATTERN, SOURCE_REF_FORBIDDEN, ALLOWED_SKILL_PATH_PREFIXES, VALID_DIRECTIVE_PRIORITIES;
|
|
38998
39125
|
var init_knowledge_validator = __esm(() => {
|
|
38999
39126
|
init_task_file();
|
|
39000
39127
|
init_logger();
|
|
39001
39128
|
init_knowledge_store();
|
|
39002
39129
|
import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
|
|
39003
|
-
|
|
39130
|
+
DANGEROUS_COMMAND_ERROR_PATTERNS = [
|
|
39004
39131
|
/\brm\s+-rf\b/,
|
|
39005
39132
|
/\bsudo\s+rm\b/,
|
|
39006
|
-
/\bformat\b/,
|
|
39007
39133
|
/\bmkfs\b/,
|
|
39008
39134
|
/\bdd\s+if=/,
|
|
39009
39135
|
/:\(\)\s*\{/,
|
|
39010
39136
|
/\bchmod\s+-R\s+777\b/i,
|
|
39011
39137
|
/\bdeltree\b/,
|
|
39012
|
-
/\brmdir\s+\/s\b
|
|
39138
|
+
/\brmdir\s+\/s\b/
|
|
39139
|
+
];
|
|
39140
|
+
DANGEROUS_COMMAND_WARNING_PATTERNS = [
|
|
39141
|
+
/\bformat\b/,
|
|
39013
39142
|
/\bkill\s+-9\b/,
|
|
39014
39143
|
/\bpkill\b/,
|
|
39015
39144
|
/\bkillall\b/,
|
|
39016
39145
|
/`[^`]*`/,
|
|
39017
39146
|
/\$\([^)]*\)/
|
|
39018
39147
|
];
|
|
39148
|
+
DANGEROUS_COMMAND_PATTERNS = [
|
|
39149
|
+
...DANGEROUS_COMMAND_ERROR_PATTERNS,
|
|
39150
|
+
...DANGEROUS_COMMAND_WARNING_PATTERNS
|
|
39151
|
+
];
|
|
39019
39152
|
SECURITY_DEGRADING_PATTERNS = [
|
|
39020
39153
|
/disable\s+.{0,50}firewall/i,
|
|
39021
39154
|
/turn\s+off\s+.{0,50}security/i,
|
|
@@ -39117,7 +39250,7 @@ var init_knowledge_validator = __esm(() => {
|
|
|
39117
39250
|
});
|
|
39118
39251
|
|
|
39119
39252
|
// src/services/skill-changelog.ts
|
|
39120
|
-
import { appendFile as appendFile5, mkdir as mkdir5, readFile as readFile4, writeFile as
|
|
39253
|
+
import { appendFile as appendFile5, mkdir as mkdir5, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
39121
39254
|
import * as path16 from "path";
|
|
39122
39255
|
function resolveSkillChangelogPath(directory, slug) {
|
|
39123
39256
|
if (slug.includes("..") || slug.includes("/") || slug.includes("\\")) {
|
|
@@ -39137,7 +39270,7 @@ async function appendSkillChangelog(directory, slug, entry) {
|
|
|
39137
39270
|
`).filter((line) => line.trim().length > 0);
|
|
39138
39271
|
if (lines.length > MAX_CHANGELOG_ENTRIES_PER_SKILL) {
|
|
39139
39272
|
const trimmed = lines.slice(lines.length - MAX_CHANGELOG_ENTRIES_PER_SKILL);
|
|
39140
|
-
await
|
|
39273
|
+
await writeFile3(filePath, `${trimmed.join(`
|
|
39141
39274
|
`)}
|
|
39142
39275
|
`, "utf-8");
|
|
39143
39276
|
}
|
|
@@ -39152,7 +39285,7 @@ var init_skill_changelog = __esm(() => {
|
|
|
39152
39285
|
|
|
39153
39286
|
// src/services/skill-generator.ts
|
|
39154
39287
|
import { existsSync as existsSync11, unlinkSync as unlinkSync5 } from "fs";
|
|
39155
|
-
import { mkdir as mkdir6, readFile as readFile5, rename as rename3, writeFile as
|
|
39288
|
+
import { mkdir as mkdir6, readFile as readFile5, rename as rename3, writeFile as writeFile4 } from "fs/promises";
|
|
39156
39289
|
import * as path17 from "path";
|
|
39157
39290
|
function sanitizeSlug(input) {
|
|
39158
39291
|
const lc = input.toLowerCase().trim();
|
|
@@ -39177,18 +39310,35 @@ async function selectCandidateEntries(directory, opts) {
|
|
|
39177
39310
|
const hivePath = resolveHiveKnowledgePath();
|
|
39178
39311
|
const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
|
|
39179
39312
|
const all = [...swarm, ...hive];
|
|
39180
|
-
|
|
39313
|
+
const counterRollups = await readKnowledgeCounterRollups(directory);
|
|
39314
|
+
const selected = [];
|
|
39315
|
+
for (const e of all) {
|
|
39181
39316
|
if (e.status === "archived")
|
|
39182
|
-
|
|
39183
|
-
if (e.confidence < opts.minConfidence)
|
|
39184
|
-
return false;
|
|
39185
|
-
const confirmations = (e.confirmed_by ?? []).length;
|
|
39186
|
-
if (confirmations < opts.minConfirmations)
|
|
39187
|
-
return false;
|
|
39317
|
+
continue;
|
|
39188
39318
|
if (e.generated_skill_slug)
|
|
39189
|
-
|
|
39190
|
-
|
|
39191
|
-
|
|
39319
|
+
continue;
|
|
39320
|
+
const outcomes = effectiveRetrievalOutcomes(e.retrieval_outcomes, counterRollups.get(e.id));
|
|
39321
|
+
if (!isSkillMaturityEligible(e, opts, outcomes))
|
|
39322
|
+
continue;
|
|
39323
|
+
selected.push({ ...e, retrieval_outcomes: outcomes });
|
|
39324
|
+
}
|
|
39325
|
+
return selected;
|
|
39326
|
+
}
|
|
39327
|
+
function hasStrongSkillOutcomeRecord(outcomes) {
|
|
39328
|
+
return (outcomes?.applied_explicit_count ?? 0) >= STRONG_SKILL_OUTCOME_COUNT || (outcomes?.succeeded_after_shown_count ?? 0) >= STRONG_SKILL_OUTCOME_COUNT;
|
|
39329
|
+
}
|
|
39330
|
+
function isHighPriorityDirective(entry) {
|
|
39331
|
+
return entry.directive_priority === "critical" || entry.directive_priority === "high";
|
|
39332
|
+
}
|
|
39333
|
+
function isSkillMaturityEligible(entry, opts, outcomes = entry.retrieval_outcomes) {
|
|
39334
|
+
const outcomeSignal = computeOutcomeSignal(outcomes);
|
|
39335
|
+
if (outcomeSignal < 0)
|
|
39336
|
+
return false;
|
|
39337
|
+
const strongOutcomes = hasStrongSkillOutcomeRecord(outcomes);
|
|
39338
|
+
if (entry.confidence < opts.minConfidence && !strongOutcomes)
|
|
39339
|
+
return false;
|
|
39340
|
+
const confirmations = (entry.confirmed_by ?? []).length;
|
|
39341
|
+
return confirmations >= opts.minConfirmations || strongOutcomes;
|
|
39192
39342
|
}
|
|
39193
39343
|
function jaccardSimilarity(setA, setB) {
|
|
39194
39344
|
const normA = setA.map((s) => s.toLowerCase());
|
|
@@ -39228,8 +39378,9 @@ function clusterEntries(entries) {
|
|
|
39228
39378
|
}
|
|
39229
39379
|
const result = [];
|
|
39230
39380
|
for (const c of clusters) {
|
|
39231
|
-
if (c.members.length < MIN_CLUSTER_SIZE)
|
|
39381
|
+
if (c.members.length < MIN_CLUSTER_SIZE && !isSkillSingletonEligible(c.members[0])) {
|
|
39232
39382
|
continue;
|
|
39383
|
+
}
|
|
39233
39384
|
const arr = c.members;
|
|
39234
39385
|
const triggers = uniqueStrings(arr.flatMap((e) => e.triggers ?? []));
|
|
39235
39386
|
const required3 = uniqueStrings(arr.flatMap((e) => e.required_actions ?? []));
|
|
@@ -39255,6 +39406,11 @@ function clusterEntries(entries) {
|
|
|
39255
39406
|
result.sort((a, b) => b.entries.length - a.entries.length || b.avgConfidence - a.avgConfidence || a.slug.localeCompare(b.slug));
|
|
39256
39407
|
return result;
|
|
39257
39408
|
}
|
|
39409
|
+
function isSkillSingletonEligible(entry) {
|
|
39410
|
+
if (!entry)
|
|
39411
|
+
return false;
|
|
39412
|
+
return isHighPriorityDirective(entry) || hasStrongSkillOutcomeRecord(entry.retrieval_outcomes);
|
|
39413
|
+
}
|
|
39258
39414
|
function uniqueStrings(arr) {
|
|
39259
39415
|
return [...new Set(arr.filter((s) => typeof s === "string" && s.length > 0))];
|
|
39260
39416
|
}
|
|
@@ -39355,12 +39511,12 @@ function escapeMarkdown(s) {
|
|
|
39355
39511
|
async function atomicWrite(p, content) {
|
|
39356
39512
|
await mkdir6(path17.dirname(p), { recursive: true });
|
|
39357
39513
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
39358
|
-
await
|
|
39514
|
+
await writeFile4(tmp, content, "utf-8");
|
|
39359
39515
|
await rename3(tmp, p);
|
|
39360
39516
|
}
|
|
39361
39517
|
async function generateSkills(req) {
|
|
39362
|
-
const minConfidence = req.minConfidence ??
|
|
39363
|
-
const minConfirmations = req.minConfirmations ??
|
|
39518
|
+
const minConfidence = req.minConfidence ?? DEFAULT_SKILL_MIN_CONFIDENCE;
|
|
39519
|
+
const minConfirmations = req.minConfirmations ?? DEFAULT_SKILL_MIN_CONFIRMATIONS;
|
|
39364
39520
|
const candidates = await selectCandidateEntries(req.directory, {
|
|
39365
39521
|
minConfidence,
|
|
39366
39522
|
minConfirmations
|
|
@@ -39755,7 +39911,7 @@ async function retireSkill(directory, slug, reason) {
|
|
|
39755
39911
|
reason: reason ?? "manual_retire"
|
|
39756
39912
|
});
|
|
39757
39913
|
await mkdir6(markerDir, { recursive: true });
|
|
39758
|
-
await
|
|
39914
|
+
await writeFile4(markerPath, markerContent, "utf-8");
|
|
39759
39915
|
return {
|
|
39760
39916
|
retired: true,
|
|
39761
39917
|
path: skillPath,
|
|
@@ -39918,8 +40074,9 @@ async function regenerateSkill(directory, slug) {
|
|
|
39918
40074
|
entryCount: matchedEntries.length
|
|
39919
40075
|
};
|
|
39920
40076
|
}
|
|
39921
|
-
var SLUG_PATTERN, MIN_CLUSTER_SIZE = 2, JACCARD_THRESHOLD = 0.5, AUTO_APPLY_BATCH_LIMIT = 5, _internals15;
|
|
40077
|
+
var SLUG_PATTERN, DEFAULT_SKILL_MIN_CONFIDENCE = 0.7, DEFAULT_SKILL_MIN_CONFIRMATIONS = 2, STRONG_SKILL_OUTCOME_COUNT = 3, MIN_CLUSTER_SIZE = 2, JACCARD_THRESHOLD = 0.5, AUTO_APPLY_BATCH_LIMIT = 5, _internals15;
|
|
39922
40078
|
var init_skill_generator = __esm(() => {
|
|
40079
|
+
init_knowledge_events();
|
|
39923
40080
|
init_knowledge_store();
|
|
39924
40081
|
init_knowledge_validator();
|
|
39925
40082
|
init_logger();
|
|
@@ -39929,6 +40086,7 @@ var init_skill_generator = __esm(() => {
|
|
|
39929
40086
|
sanitizeSlug,
|
|
39930
40087
|
isValidSlug,
|
|
39931
40088
|
selectCandidateEntries,
|
|
40089
|
+
isSkillMaturityEligible,
|
|
39932
40090
|
clusterEntries,
|
|
39933
40091
|
jaccardSimilarity,
|
|
39934
40092
|
renderSkillMarkdown,
|
|
@@ -39947,7 +40105,7 @@ var init_skill_generator = __esm(() => {
|
|
|
39947
40105
|
|
|
39948
40106
|
// src/services/skill-improver-quota.ts
|
|
39949
40107
|
import { existsSync as existsSync12 } from "fs";
|
|
39950
|
-
import { mkdir as mkdir7, readFile as readFile6, rename as rename4, writeFile as
|
|
40108
|
+
import { mkdir as mkdir7, readFile as readFile6, rename as rename4, writeFile as writeFile5 } from "fs/promises";
|
|
39951
40109
|
import * as path18 from "path";
|
|
39952
40110
|
async function acquireLock(dir) {
|
|
39953
40111
|
const acquire = import_proper_lockfile6.default.lock(dir, LOCK_RETRY_OPTS);
|
|
@@ -39965,8 +40123,9 @@ async function acquireLock(dir) {
|
|
|
39965
40123
|
clearTimeout(timer);
|
|
39966
40124
|
}
|
|
39967
40125
|
}
|
|
39968
|
-
function resolveQuotaPath(directory) {
|
|
39969
|
-
|
|
40126
|
+
function resolveQuotaPath(directory, scope = "skill-improver") {
|
|
40127
|
+
const fileName = scope === "knowledge-enrichment" ? "knowledge-enrichment-quota.json" : "skill-improver-quota.json";
|
|
40128
|
+
return path18.join(directory, ".swarm", fileName);
|
|
39970
40129
|
}
|
|
39971
40130
|
function todayKey(window, now = new Date) {
|
|
39972
40131
|
if (window === "utc") {
|
|
@@ -39994,11 +40153,11 @@ async function readState(filePath) {
|
|
|
39994
40153
|
async function writeState(filePath, state) {
|
|
39995
40154
|
await mkdir7(path18.dirname(filePath), { recursive: true });
|
|
39996
40155
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
39997
|
-
await
|
|
40156
|
+
await writeFile5(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
39998
40157
|
await rename4(tmp, filePath);
|
|
39999
40158
|
}
|
|
40000
40159
|
async function getQuotaState(directory, opts) {
|
|
40001
|
-
const filePath = resolveQuotaPath(directory);
|
|
40160
|
+
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
40002
40161
|
const today = todayKey(opts.window, opts.now);
|
|
40003
40162
|
const existing = await readState(filePath);
|
|
40004
40163
|
if (!existing || existing.date !== today || existing.window !== opts.window) {
|
|
@@ -40014,7 +40173,7 @@ async function getQuotaState(directory, opts) {
|
|
|
40014
40173
|
return { ...existing, max_calls: opts.maxCalls };
|
|
40015
40174
|
}
|
|
40016
40175
|
async function reserveQuota(directory, opts) {
|
|
40017
|
-
const filePath = resolveQuotaPath(directory);
|
|
40176
|
+
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
40018
40177
|
await mkdir7(path18.dirname(filePath), { recursive: true });
|
|
40019
40178
|
let release = null;
|
|
40020
40179
|
try {
|
|
@@ -40044,7 +40203,7 @@ async function reserveQuota(directory, opts) {
|
|
|
40044
40203
|
}
|
|
40045
40204
|
}
|
|
40046
40205
|
async function releaseQuota(directory, opts) {
|
|
40047
|
-
const filePath = resolveQuotaPath(directory);
|
|
40206
|
+
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
40048
40207
|
await mkdir7(path18.dirname(filePath), { recursive: true });
|
|
40049
40208
|
let release = null;
|
|
40050
40209
|
try {
|
|
@@ -40096,6 +40255,89 @@ function resolveLogPath(directory) {
|
|
|
40096
40255
|
function normalizeComplianceVerdict(verdict) {
|
|
40097
40256
|
return verdict === "violation" ? "violated" : verdict;
|
|
40098
40257
|
}
|
|
40258
|
+
function normalizeSkillUsageEntry(raw) {
|
|
40259
|
+
const entry = raw;
|
|
40260
|
+
return {
|
|
40261
|
+
...entry,
|
|
40262
|
+
complianceVerdict: normalizeComplianceVerdict(entry.complianceVerdict)
|
|
40263
|
+
};
|
|
40264
|
+
}
|
|
40265
|
+
function legacySkillUsageId(entry) {
|
|
40266
|
+
const stable = JSON.stringify({
|
|
40267
|
+
skillPath: entry.skillPath,
|
|
40268
|
+
agentName: entry.agentName,
|
|
40269
|
+
taskID: entry.taskID,
|
|
40270
|
+
timestamp: entry.timestamp,
|
|
40271
|
+
complianceVerdict: entry.complianceVerdict,
|
|
40272
|
+
sessionID: entry.sessionID,
|
|
40273
|
+
skillVersion: entry.skillVersion
|
|
40274
|
+
});
|
|
40275
|
+
return `legacy:${crypto3.createHash("sha256").update(stable).digest("hex")}`;
|
|
40276
|
+
}
|
|
40277
|
+
function parseSkillUsageEntry(raw) {
|
|
40278
|
+
const entry = raw;
|
|
40279
|
+
if (entry.type === "feedback_applied")
|
|
40280
|
+
return null;
|
|
40281
|
+
if (typeof entry.skillPath !== "string" || typeof entry.agentName !== "string" || typeof entry.taskID !== "string" || typeof entry.timestamp !== "string" || typeof entry.complianceVerdict !== "string" || typeof entry.sessionID !== "string") {
|
|
40282
|
+
return null;
|
|
40283
|
+
}
|
|
40284
|
+
return normalizeSkillUsageEntry({
|
|
40285
|
+
...entry,
|
|
40286
|
+
id: typeof entry.id === "string" ? entry.id : legacySkillUsageId(entry)
|
|
40287
|
+
});
|
|
40288
|
+
}
|
|
40289
|
+
function parseFeedbackMarker(raw) {
|
|
40290
|
+
const marker = raw;
|
|
40291
|
+
if (marker.type !== "feedback_applied")
|
|
40292
|
+
return null;
|
|
40293
|
+
if (typeof marker.timestamp !== "string")
|
|
40294
|
+
return null;
|
|
40295
|
+
if (!Array.isArray(marker.processedEntryIds))
|
|
40296
|
+
return null;
|
|
40297
|
+
const processedEntryIds = marker.processedEntryIds.filter((id) => typeof id === "string" && id.length > 0);
|
|
40298
|
+
return {
|
|
40299
|
+
type: "feedback_applied",
|
|
40300
|
+
timestamp: marker.timestamp,
|
|
40301
|
+
processedEntryIds
|
|
40302
|
+
};
|
|
40303
|
+
}
|
|
40304
|
+
function readFeedbackAppliedEntryIds(directory) {
|
|
40305
|
+
const resolved = resolveLogPath(directory);
|
|
40306
|
+
const processed = new Set;
|
|
40307
|
+
if (!_internals16.existsSync(resolved))
|
|
40308
|
+
return processed;
|
|
40309
|
+
const raw = _internals16.readFileSync(resolved, "utf-8");
|
|
40310
|
+
for (const line of raw.split(`
|
|
40311
|
+
`)) {
|
|
40312
|
+
const trimmed = line.trim();
|
|
40313
|
+
if (!trimmed)
|
|
40314
|
+
continue;
|
|
40315
|
+
try {
|
|
40316
|
+
const marker = parseFeedbackMarker(JSON.parse(trimmed));
|
|
40317
|
+
if (!marker)
|
|
40318
|
+
continue;
|
|
40319
|
+
for (const id of marker.processedEntryIds)
|
|
40320
|
+
processed.add(id);
|
|
40321
|
+
} catch {}
|
|
40322
|
+
}
|
|
40323
|
+
return processed;
|
|
40324
|
+
}
|
|
40325
|
+
function appendFeedbackAppliedMarker(directory, processedEntryIds) {
|
|
40326
|
+
if (processedEntryIds.length === 0)
|
|
40327
|
+
return;
|
|
40328
|
+
const resolved = resolveLogPath(directory);
|
|
40329
|
+
const dir = path19.dirname(resolved);
|
|
40330
|
+
if (!_internals16.existsSync(dir)) {
|
|
40331
|
+
_internals16.mkdirSync(dir, { recursive: true });
|
|
40332
|
+
}
|
|
40333
|
+
const marker = {
|
|
40334
|
+
type: "feedback_applied",
|
|
40335
|
+
timestamp: new Date().toISOString(),
|
|
40336
|
+
processedEntryIds: [...new Set(processedEntryIds)]
|
|
40337
|
+
};
|
|
40338
|
+
_internals16.appendFileSync(resolved, `${JSON.stringify(marker)}
|
|
40339
|
+
`, "utf-8");
|
|
40340
|
+
}
|
|
40099
40341
|
function appendSkillUsageEntry(directory, entry) {
|
|
40100
40342
|
const {
|
|
40101
40343
|
skillPath,
|
|
@@ -40139,7 +40381,7 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
40139
40381
|
agentName,
|
|
40140
40382
|
taskID,
|
|
40141
40383
|
timestamp,
|
|
40142
|
-
complianceVerdict,
|
|
40384
|
+
complianceVerdict: normalizeComplianceVerdict(complianceVerdict),
|
|
40143
40385
|
sessionID,
|
|
40144
40386
|
...reviewerNotes !== undefined && { reviewerNotes },
|
|
40145
40387
|
...skillVersion !== undefined && { skillVersion }
|
|
@@ -40147,8 +40389,8 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
40147
40389
|
_internals16.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
|
|
40148
40390
|
`, "utf-8");
|
|
40149
40391
|
try {
|
|
40150
|
-
const
|
|
40151
|
-
if (
|
|
40392
|
+
const stat3 = _internals16.statSync(resolved);
|
|
40393
|
+
if (stat3.size > SKILL_USAGE_LOG_ROTATE_BYTES) {
|
|
40152
40394
|
_internals16.pruneSkillUsageLog(directory, SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL);
|
|
40153
40395
|
}
|
|
40154
40396
|
} catch {}
|
|
@@ -40166,9 +40408,9 @@ function readSkillUsageEntries(directory, options) {
|
|
|
40166
40408
|
if (!trimmed)
|
|
40167
40409
|
continue;
|
|
40168
40410
|
try {
|
|
40169
|
-
const entry = JSON.parse(trimmed);
|
|
40170
|
-
|
|
40171
|
-
|
|
40411
|
+
const entry = parseSkillUsageEntry(JSON.parse(trimmed));
|
|
40412
|
+
if (entry)
|
|
40413
|
+
entries.push(entry);
|
|
40172
40414
|
} catch {}
|
|
40173
40415
|
}
|
|
40174
40416
|
if (!options)
|
|
@@ -40202,11 +40444,11 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
|
|
|
40202
40444
|
try {
|
|
40203
40445
|
const normalizedMaxBytes = Number.isFinite(maxBytes) ? maxBytes : TAIL_BYTES_DEFAULT;
|
|
40204
40446
|
const boundedMaxBytes = Math.min(Math.max(1, normalizedMaxBytes), MAX_TAIL_BYTES);
|
|
40205
|
-
const
|
|
40206
|
-
const start = Math.max(0,
|
|
40447
|
+
const stat3 = _internals16.statSync(logPath);
|
|
40448
|
+
const start = Math.max(0, stat3.size - boundedMaxBytes);
|
|
40207
40449
|
const fd = _internals16.openSync(logPath, "r");
|
|
40208
40450
|
try {
|
|
40209
|
-
const readLen =
|
|
40451
|
+
const readLen = stat3.size - start;
|
|
40210
40452
|
if (readLen === 0)
|
|
40211
40453
|
return [];
|
|
40212
40454
|
const buf = Buffer.alloc(readLen);
|
|
@@ -40226,8 +40468,9 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
|
|
|
40226
40468
|
if (!line.trim())
|
|
40227
40469
|
continue;
|
|
40228
40470
|
try {
|
|
40229
|
-
const entry = JSON.parse(line);
|
|
40230
|
-
|
|
40471
|
+
const entry = parseSkillUsageEntry(JSON.parse(line));
|
|
40472
|
+
if (!entry)
|
|
40473
|
+
continue;
|
|
40231
40474
|
if (filters.sessionID !== undefined && entry.sessionID !== filters.sessionID) {
|
|
40232
40475
|
continue;
|
|
40233
40476
|
}
|
|
@@ -40262,8 +40505,9 @@ function computeComplianceByVersion(entries, skillPath) {
|
|
|
40262
40505
|
stats.total += 1;
|
|
40263
40506
|
if (e.complianceVerdict === "compliant")
|
|
40264
40507
|
stats.compliant += 1;
|
|
40265
|
-
if (e.complianceVerdict === "violated")
|
|
40508
|
+
if (normalizeComplianceVerdict(e.complianceVerdict) === "violated") {
|
|
40266
40509
|
stats.violation += 1;
|
|
40510
|
+
}
|
|
40267
40511
|
}
|
|
40268
40512
|
for (const stats of map3.values()) {
|
|
40269
40513
|
stats.rate = stats.total === 0 ? 0 : stats.compliant / stats.total;
|
|
@@ -40374,6 +40618,7 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
40374
40618
|
let bumps = 0;
|
|
40375
40619
|
try {
|
|
40376
40620
|
const allEntries = readSkillUsageEntries(directory);
|
|
40621
|
+
const alreadyProcessed = readFeedbackAppliedEntryIds(directory);
|
|
40377
40622
|
const actionable = allEntries.filter((e) => {
|
|
40378
40623
|
if (e.complianceVerdict !== "compliant" && e.complianceVerdict !== "violated") {
|
|
40379
40624
|
return false;
|
|
@@ -40381,6 +40626,9 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
40381
40626
|
if (options?.sinceTimestamp && e.timestamp <= options.sinceTimestamp) {
|
|
40382
40627
|
return false;
|
|
40383
40628
|
}
|
|
40629
|
+
if (alreadyProcessed.has(e.id)) {
|
|
40630
|
+
return false;
|
|
40631
|
+
}
|
|
40384
40632
|
return true;
|
|
40385
40633
|
});
|
|
40386
40634
|
if (actionable.length === 0) {
|
|
@@ -40395,6 +40643,7 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
40395
40643
|
groups.set(entry.skillPath, [entry]);
|
|
40396
40644
|
}
|
|
40397
40645
|
const allDeltas = [];
|
|
40646
|
+
const processedEntryIds = [];
|
|
40398
40647
|
for (const [skillPath, entries] of Array.from(groups)) {
|
|
40399
40648
|
let compliantCount = 0;
|
|
40400
40649
|
let violationCount = 0;
|
|
@@ -40413,6 +40662,7 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
40413
40662
|
for (const id of sourceIds) {
|
|
40414
40663
|
allDeltas.push({ id, delta });
|
|
40415
40664
|
}
|
|
40665
|
+
processedEntryIds.push(...entries.map((entry) => entry.id));
|
|
40416
40666
|
processed++;
|
|
40417
40667
|
bumps += sourceIds.length;
|
|
40418
40668
|
}
|
|
@@ -40426,6 +40676,7 @@ async function applySkillUsageFeedback(directory, options) {
|
|
|
40426
40676
|
}));
|
|
40427
40677
|
if (clampedDeltas.length > 0) {
|
|
40428
40678
|
await bumpKnowledgeConfidenceBatch(directory, clampedDeltas);
|
|
40679
|
+
appendFeedbackAppliedMarker(directory, processedEntryIds);
|
|
40429
40680
|
}
|
|
40430
40681
|
} catch (err) {
|
|
40431
40682
|
console.warn("[skill-usage-log] applySkillUsageFeedback failed (fail-open):", err instanceof Error ? err.message : String(err));
|
|
@@ -40452,7 +40703,10 @@ var init_skill_usage_log = __esm(() => {
|
|
|
40452
40703
|
resolveSourceKnowledgeIds,
|
|
40453
40704
|
applySkillUsageFeedback,
|
|
40454
40705
|
parseGeneratedFromKnowledge,
|
|
40455
|
-
computeComplianceByVersion
|
|
40706
|
+
computeComplianceByVersion,
|
|
40707
|
+
normalizeComplianceVerdict,
|
|
40708
|
+
readFeedbackAppliedEntryIds,
|
|
40709
|
+
appendFeedbackAppliedMarker
|
|
40456
40710
|
};
|
|
40457
40711
|
TAIL_BYTES_DEFAULT = 64 * 1024;
|
|
40458
40712
|
MAX_TAIL_BYTES = TAIL_BYTES_DEFAULT;
|
|
@@ -40502,6 +40756,9 @@ function isAlreadyInHive(entry, hiveEntries, threshold) {
|
|
|
40502
40756
|
return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
|
|
40503
40757
|
}
|
|
40504
40758
|
function isHiveEligible(entry, autoPromoteDays) {
|
|
40759
|
+
if (!isActiveForHivePromotion(entry)) {
|
|
40760
|
+
return false;
|
|
40761
|
+
}
|
|
40505
40762
|
const phaseNumbers = new Set;
|
|
40506
40763
|
for (const record3 of entry.confirmed_by ?? []) {
|
|
40507
40764
|
if (record3 && typeof record3.phase_number === "number") {
|
|
@@ -40522,6 +40779,9 @@ function isHiveEligible(entry, autoPromoteDays) {
|
|
|
40522
40779
|
}
|
|
40523
40780
|
return false;
|
|
40524
40781
|
}
|
|
40782
|
+
function isActiveForHivePromotion(entry) {
|
|
40783
|
+
return !["archived", "quarantined", "quarantined_unactionable"].includes(entry.status);
|
|
40784
|
+
}
|
|
40525
40785
|
function countDistinctProjects(confirmedBy) {
|
|
40526
40786
|
const projectNames = new Set;
|
|
40527
40787
|
for (const record3 of confirmedBy) {
|
|
@@ -40604,7 +40864,7 @@ async function checkHivePromotions(swarmEntries, config3) {
|
|
|
40604
40864
|
}
|
|
40605
40865
|
let hiveModified = false;
|
|
40606
40866
|
for (const hiveEntry of hiveEntries) {
|
|
40607
|
-
const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries, config3.dedup_threshold);
|
|
40867
|
+
const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries.filter(isActiveForHivePromotion), config3.dedup_threshold);
|
|
40608
40868
|
if (!nearDuplicate) {
|
|
40609
40869
|
continue;
|
|
40610
40870
|
}
|
|
@@ -40734,9 +40994,9 @@ import {
|
|
|
40734
40994
|
mkdir as mkdir8,
|
|
40735
40995
|
readFile as readFile7,
|
|
40736
40996
|
rename as rename5,
|
|
40737
|
-
stat as
|
|
40997
|
+
stat as stat3,
|
|
40738
40998
|
unlink as unlink2,
|
|
40739
|
-
writeFile as
|
|
40999
|
+
writeFile as writeFile6
|
|
40740
41000
|
} from "fs/promises";
|
|
40741
41001
|
import * as path21 from "path";
|
|
40742
41002
|
function emptySynonymMap() {
|
|
@@ -40877,7 +41137,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
|
40877
41137
|
}
|
|
40878
41138
|
try {
|
|
40879
41139
|
const ceiling = Math.max(MIN_READ_CEILING_BYTES, Math.floor(maxPairs) * APPROX_BYTES_PER_PAIR);
|
|
40880
|
-
const st = await
|
|
41140
|
+
const st = await stat3(filePath);
|
|
40881
41141
|
if (st.size > ceiling)
|
|
40882
41142
|
return emptySynonymMap();
|
|
40883
41143
|
const raw = await readFile7(filePath, "utf-8");
|
|
@@ -40890,7 +41150,7 @@ async function writeSynonymMapAtomic(filePath, map3) {
|
|
|
40890
41150
|
await mkdir8(path21.dirname(filePath), { recursive: true });
|
|
40891
41151
|
const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
40892
41152
|
try {
|
|
40893
|
-
await
|
|
41153
|
+
await writeFile6(tmp, JSON.stringify(map3, null, 2), "utf-8");
|
|
40894
41154
|
await rename5(tmp, filePath);
|
|
40895
41155
|
} finally {
|
|
40896
41156
|
try {
|
|
@@ -41099,12 +41359,12 @@ function extractKeywords(text) {
|
|
|
41099
41359
|
const words = text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= MIN_KEYWORD_LENGTH);
|
|
41100
41360
|
return new Set(words);
|
|
41101
41361
|
}
|
|
41102
|
-
function computeContextMatchScore(taskDescription, skillPath) {
|
|
41362
|
+
function computeContextMatchScore(taskDescription, skillPath, metadata) {
|
|
41103
41363
|
const taskKeywords = extractKeywords(taskDescription);
|
|
41104
41364
|
if (taskKeywords.size === 0)
|
|
41105
41365
|
return 0;
|
|
41106
41366
|
const skillName = extractSkillName(skillPath);
|
|
41107
|
-
const skillText = `${skillPath} ${skillName}`;
|
|
41367
|
+
const skillText = `${skillPath} ${skillName} ${metadata?.name ?? ""} ${metadata?.description ?? ""}`;
|
|
41108
41368
|
const skillKeywords = extractKeywords(skillText);
|
|
41109
41369
|
let matchCount = 0;
|
|
41110
41370
|
for (const kw of taskKeywords) {
|
|
@@ -41115,7 +41375,7 @@ function computeContextMatchScore(taskDescription, skillPath) {
|
|
|
41115
41375
|
return matchCount / taskKeywords.size;
|
|
41116
41376
|
}
|
|
41117
41377
|
function computeSkillRelevanceScore(skillPath, taskDescription, usageHistory, metadata) {
|
|
41118
|
-
const contextScore = computeContextMatchScore(taskDescription, skillPath) * CONTEXT_WEIGHT;
|
|
41378
|
+
const contextScore = computeContextMatchScore(taskDescription, skillPath, metadata) * CONTEXT_WEIGHT;
|
|
41119
41379
|
if (usageHistory.length === 0)
|
|
41120
41380
|
return Math.min(1, contextScore);
|
|
41121
41381
|
const usageCount = usageHistory.length;
|
|
@@ -41190,8 +41450,8 @@ function formatSkillIndexWithContext(skills, directory) {
|
|
|
41190
41450
|
const usageLogPath = path22.join(directory, ".swarm", "skill-usage.jsonl");
|
|
41191
41451
|
let hasHistory = false;
|
|
41192
41452
|
try {
|
|
41193
|
-
const
|
|
41194
|
-
hasHistory =
|
|
41453
|
+
const stat4 = fs10.statSync(usageLogPath);
|
|
41454
|
+
hasHistory = stat4.size > 0;
|
|
41195
41455
|
} catch {}
|
|
41196
41456
|
if (!hasHistory) {
|
|
41197
41457
|
return skills.map((sp) => {
|
|
@@ -41712,24 +41972,32 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
|
|
|
41712
41972
|
if (!text)
|
|
41713
41973
|
continue;
|
|
41714
41974
|
const skillPaths = [];
|
|
41975
|
+
let explicitReviewerTaskID;
|
|
41715
41976
|
for (const line of text.split(`
|
|
41716
41977
|
`)) {
|
|
41717
|
-
const
|
|
41978
|
+
const trimmed = line.trim();
|
|
41979
|
+
const taskMatch = trimmed.match(REVIEWER_TASK_PATTERN);
|
|
41980
|
+
if (taskMatch) {
|
|
41981
|
+
explicitReviewerTaskID = taskMatch[1];
|
|
41982
|
+
}
|
|
41983
|
+
const coderMatch = trimmed.match(CODER_SKILLS_PATTERN);
|
|
41718
41984
|
if (coderMatch) {
|
|
41719
41985
|
const parsed = _internals18.parseSkillPaths(coderMatch[1]);
|
|
41720
41986
|
skillPaths.push(...parsed);
|
|
41721
41987
|
}
|
|
41722
41988
|
}
|
|
41723
|
-
let resolvedTaskID = "unknown";
|
|
41989
|
+
let resolvedTaskID = explicitReviewerTaskID ?? "unknown";
|
|
41724
41990
|
if (existingEntries.length > 0) {
|
|
41725
|
-
|
|
41726
|
-
|
|
41727
|
-
|
|
41728
|
-
|
|
41729
|
-
|
|
41730
|
-
|
|
41731
|
-
|
|
41732
|
-
|
|
41991
|
+
if (!explicitReviewerTaskID) {
|
|
41992
|
+
const latestDelegation = [...existingEntries].reverse().find((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__");
|
|
41993
|
+
if (latestDelegation) {
|
|
41994
|
+
resolvedTaskID = latestDelegation.taskID;
|
|
41995
|
+
}
|
|
41996
|
+
}
|
|
41997
|
+
if (skillPaths.length === 0 && resolvedTaskID !== "unknown") {
|
|
41998
|
+
const delegatedPaths = existingEntries.filter((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__" && e.taskID === resolvedTaskID).map((e) => e.skillPath);
|
|
41999
|
+
if (delegatedPaths.length > 0) {
|
|
42000
|
+
skillPaths.push(...new Set(delegatedPaths));
|
|
41733
42001
|
}
|
|
41734
42002
|
}
|
|
41735
42003
|
}
|
|
@@ -41819,7 +42087,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
|
|
|
41819
42087
|
break;
|
|
41820
42088
|
}
|
|
41821
42089
|
}
|
|
41822
|
-
var SKILL_CAPABLE_AGENTS, SKILL_SEARCH_ROOTS, MAX_SCORING_SESSION_ENTRIES = 500, _internals18, COMPLIANCE_PATTERN, CODER_SKILLS_PATTERN;
|
|
42090
|
+
var SKILL_CAPABLE_AGENTS, SKILL_SEARCH_ROOTS, MAX_SCORING_SESSION_ENTRIES = 500, _internals18, COMPLIANCE_PATTERN, CODER_SKILLS_PATTERN, REVIEWER_TASK_PATTERN;
|
|
41823
42091
|
var init_skill_propagation_gate = __esm(() => {
|
|
41824
42092
|
init_schema();
|
|
41825
42093
|
init_logger();
|
|
@@ -41865,6 +42133,7 @@ var init_skill_propagation_gate = __esm(() => {
|
|
|
41865
42133
|
};
|
|
41866
42134
|
COMPLIANCE_PATTERN = /SKILL_COMPLIANCE\s*:\s*(COMPLIANT|PARTIAL|VIOLATED)(?:\s*(?:\u2014|-)\s*(.*))?\s*$/i;
|
|
41867
42135
|
CODER_SKILLS_PATTERN = /SKILLS_USED_BY_CODER\s*:\s*(.+)/i;
|
|
42136
|
+
REVIEWER_TASK_PATTERN = /TASK\s*:\s*(\S+)/i;
|
|
41868
42137
|
_internals18.skillPropagationGateBefore = skillPropagationGateBefore;
|
|
41869
42138
|
_internals18.skillPropagationTransformScan = skillPropagationTransformScan;
|
|
41870
42139
|
_internals18.writeWarnEvent = writeWarnEvent;
|
|
@@ -41879,7 +42148,7 @@ var init_skill_propagation_gate = __esm(() => {
|
|
|
41879
42148
|
|
|
41880
42149
|
// src/hooks/micro-reflector.ts
|
|
41881
42150
|
import { existsSync as existsSync15 } from "fs";
|
|
41882
|
-
import { readFile as readFile8, writeFile as
|
|
42151
|
+
import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
|
|
41883
42152
|
import * as path24 from "path";
|
|
41884
42153
|
function resolveInsightCandidatesPath(directory) {
|
|
41885
42154
|
return validateSwarmPath(directory, "insight-candidates.jsonl");
|
|
@@ -41926,7 +42195,7 @@ var init_micro_reflector = __esm(() => {
|
|
|
41926
42195
|
|
|
41927
42196
|
// src/hooks/knowledge-curator.ts
|
|
41928
42197
|
import { existsSync as existsSync16 } from "fs";
|
|
41929
|
-
import { appendFile as appendFile6, mkdir as mkdir9, readFile as readFile9, writeFile as
|
|
42198
|
+
import { appendFile as appendFile6, mkdir as mkdir9, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
|
|
41930
42199
|
import * as path25 from "path";
|
|
41931
42200
|
function pruneSeenRetroSections() {
|
|
41932
42201
|
const cutoff = Date.now() - 86400000;
|
|
@@ -42167,7 +42436,8 @@ async function enrichLessonToV3(params) {
|
|
|
42167
42436
|
const reservation = await reserveQuota(params.directory, {
|
|
42168
42437
|
nCalls: 1,
|
|
42169
42438
|
maxCalls: quota.maxCalls,
|
|
42170
|
-
window: quota.window
|
|
42439
|
+
window: quota.window,
|
|
42440
|
+
scope: "knowledge-enrichment"
|
|
42171
42441
|
});
|
|
42172
42442
|
if (!reservation.allowed)
|
|
42173
42443
|
return null;
|
|
@@ -42221,7 +42491,7 @@ async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BAT
|
|
|
42221
42491
|
const body = data.length === 0 ? "" : `${data.map((c) => JSON.stringify(c)).join(`
|
|
42222
42492
|
`)}
|
|
42223
42493
|
`;
|
|
42224
|
-
await
|
|
42494
|
+
await writeFile8(p, body, "utf-8");
|
|
42225
42495
|
}, (all) => {
|
|
42226
42496
|
if (all.length === 0)
|
|
42227
42497
|
return null;
|
|
@@ -42512,7 +42782,7 @@ async function runAutoPromotion(directory, config3) {
|
|
|
42512
42782
|
await rewriteKnowledge(knowledgePath, entries);
|
|
42513
42783
|
}
|
|
42514
42784
|
}
|
|
42515
|
-
function createKnowledgeCuratorHook(directory, config3) {
|
|
42785
|
+
function createKnowledgeCuratorHook(directory, config3, options = {}) {
|
|
42516
42786
|
const handler = async (input, _output) => {
|
|
42517
42787
|
pruneSeenRetroSections();
|
|
42518
42788
|
if (!config3.enabled)
|
|
@@ -42557,7 +42827,10 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
42557
42827
|
recordSeenRetroSection(evidenceKey, evidenceHash, Date.now());
|
|
42558
42828
|
const projectName2 = evidenceData.project_name ?? "unknown";
|
|
42559
42829
|
const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
|
|
42560
|
-
await _internals19.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3
|
|
42830
|
+
await _internals19.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3, {
|
|
42831
|
+
llmDelegate: options.llmDelegateFactory?.(sessionID),
|
|
42832
|
+
enrichmentQuota: options.enrichmentQuota
|
|
42833
|
+
});
|
|
42561
42834
|
return;
|
|
42562
42835
|
}
|
|
42563
42836
|
const planContent = await readSwarmFileAsync(directory, "plan.md");
|
|
@@ -42579,7 +42852,10 @@ function createKnowledgeCuratorHook(directory, config3) {
|
|
|
42579
42852
|
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
42580
42853
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
42581
42854
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
42582
|
-
await _internals19.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3
|
|
42855
|
+
await _internals19.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3, {
|
|
42856
|
+
llmDelegate: options.llmDelegateFactory?.(sessionID),
|
|
42857
|
+
enrichmentQuota: options.enrichmentQuota
|
|
42858
|
+
});
|
|
42583
42859
|
};
|
|
42584
42860
|
return safeHook(handler);
|
|
42585
42861
|
}
|
|
@@ -42738,7 +43014,7 @@ var init_skill_improver_llm_factory = __esm(() => {
|
|
|
42738
43014
|
});
|
|
42739
43015
|
|
|
42740
43016
|
// src/services/trajectory-cluster.ts
|
|
42741
|
-
import { mkdir as mkdir10, writeFile as
|
|
43017
|
+
import { mkdir as mkdir10, writeFile as writeFile9 } from "fs/promises";
|
|
42742
43018
|
import * as path26 from "path";
|
|
42743
43019
|
function failureKind(e) {
|
|
42744
43020
|
const tool3 = (e.tool ?? "").toLowerCase();
|
|
@@ -42873,7 +43149,7 @@ async function writeMotifProposals(directory, opts = {}) {
|
|
|
42873
43149
|
for (const motif of motifs.slice(0, max)) {
|
|
42874
43150
|
const slug = `motif-${slugify2(motif.signature)}`;
|
|
42875
43151
|
const filePath = path26.join(proposalsDir, `${slug}.md`);
|
|
42876
|
-
await
|
|
43152
|
+
await writeFile9(filePath, buildMotifProposal(motif), "utf-8");
|
|
42877
43153
|
result.proposalsWritten.push(filePath);
|
|
42878
43154
|
}
|
|
42879
43155
|
return result;
|
|
@@ -43017,7 +43293,7 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
|
|
|
43017
43293
|
for (const motif of motifs.slice(0, max)) {
|
|
43018
43294
|
const slug = workflowSlug(motif.signature);
|
|
43019
43295
|
const filePath = path26.join(proposalsDir, `${slug}.md`);
|
|
43020
|
-
await
|
|
43296
|
+
await writeFile9(filePath, buildWorkflowProposal(motif), "utf-8");
|
|
43021
43297
|
result.proposalsWritten.push(filePath);
|
|
43022
43298
|
}
|
|
43023
43299
|
return result;
|
|
@@ -43148,7 +43424,7 @@ var init_unactionable_hardening = __esm(() => {
|
|
|
43148
43424
|
|
|
43149
43425
|
// src/services/skill-improver.ts
|
|
43150
43426
|
import { existsSync as existsSync18 } from "fs";
|
|
43151
|
-
import { mkdir as mkdir11, readFile as readFile10, rename as rename6, writeFile as
|
|
43427
|
+
import { mkdir as mkdir11, readFile as readFile10, rename as rename6, writeFile as writeFile10 } from "fs/promises";
|
|
43152
43428
|
import * as path27 from "path";
|
|
43153
43429
|
function timestampSlug(d) {
|
|
43154
43430
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
@@ -43156,7 +43432,7 @@ function timestampSlug(d) {
|
|
|
43156
43432
|
async function atomicWrite2(p, content) {
|
|
43157
43433
|
await mkdir11(path27.dirname(p), { recursive: true });
|
|
43158
43434
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
43159
|
-
await
|
|
43435
|
+
await writeFile10(tmp, content, "utf-8");
|
|
43160
43436
|
await rename6(tmp, p);
|
|
43161
43437
|
}
|
|
43162
43438
|
async function gatherInventory(directory) {
|
|
@@ -43210,7 +43486,10 @@ async function gatherInventory(directory) {
|
|
|
43210
43486
|
});
|
|
43211
43487
|
}
|
|
43212
43488
|
}
|
|
43213
|
-
const matureCandidates =
|
|
43489
|
+
const matureCandidates = await selectCandidateEntries(directory, {
|
|
43490
|
+
minConfidence: DEFAULT_SKILL_MIN_CONFIDENCE,
|
|
43491
|
+
minConfirmations: DEFAULT_SKILL_MIN_CONFIRMATIONS
|
|
43492
|
+
});
|
|
43214
43493
|
return {
|
|
43215
43494
|
knowledge: { swarm: swarm.length, hive: hive.length, archived },
|
|
43216
43495
|
skills: {
|
|
@@ -43476,8 +43755,8 @@ async function runSkillImprover(req) {
|
|
|
43476
43755
|
const gen = await generateSkills({
|
|
43477
43756
|
directory: req.directory,
|
|
43478
43757
|
mode: "draft",
|
|
43479
|
-
minConfidence:
|
|
43480
|
-
minConfirmations:
|
|
43758
|
+
minConfidence: DEFAULT_SKILL_MIN_CONFIDENCE,
|
|
43759
|
+
minConfirmations: DEFAULT_SKILL_MIN_CONFIRMATIONS
|
|
43481
43760
|
});
|
|
43482
43761
|
draftSkillsWritten = gen.written.map((w) => ({
|
|
43483
43762
|
slug: w.slug,
|
|
@@ -43513,7 +43792,7 @@ async function runSkillImprover(req) {
|
|
|
43513
43792
|
unactionableHardening = await hardenUnactionableEntries({
|
|
43514
43793
|
directory: req.directory,
|
|
43515
43794
|
llmDelegate: delegate,
|
|
43516
|
-
quota:
|
|
43795
|
+
quota: req.enrichmentQuota
|
|
43517
43796
|
});
|
|
43518
43797
|
}
|
|
43519
43798
|
const motifResult = await writeMotifProposals(req.directory);
|
|
@@ -44339,8 +44618,8 @@ async function copyDirRecursive(src, dest) {
|
|
|
44339
44618
|
const srcEntry = path29.join(src, entry);
|
|
44340
44619
|
const destEntry = path29.join(dest, entry);
|
|
44341
44620
|
try {
|
|
44342
|
-
const
|
|
44343
|
-
if (
|
|
44621
|
+
const stat4 = await fs12.stat(srcEntry);
|
|
44622
|
+
if (stat4.isDirectory()) {
|
|
44344
44623
|
const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
|
|
44345
44624
|
count += subCount;
|
|
44346
44625
|
} else {
|
|
@@ -44376,8 +44655,8 @@ function guaranteeAllPlansComplete(planData) {
|
|
|
44376
44655
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
44377
44656
|
const swarmDir = path29.join(directory, ".swarm");
|
|
44378
44657
|
try {
|
|
44379
|
-
const
|
|
44380
|
-
if (
|
|
44658
|
+
const stat4 = fsSync2.lstatSync(swarmDir);
|
|
44659
|
+
if (stat4.isSymbolicLink()) {
|
|
44381
44660
|
return `\u274C Refused: .swarm/ is a symlink or junction. Refusing to operate on a redirected directory for safety.`;
|
|
44382
44661
|
}
|
|
44383
44662
|
} catch (err) {
|
|
@@ -44531,12 +44810,11 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
44531
44810
|
let curationSucceeded = false;
|
|
44532
44811
|
let curationResult;
|
|
44533
44812
|
try {
|
|
44534
|
-
const skillImproverCfg = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
|
|
44535
44813
|
curationResult = await curateAndStoreSwarm(allLessons, projectName, { phase_number: 0 }, directory, config3, {
|
|
44536
44814
|
llmDelegate: createCuratorLLMDelegate(directory, "phase", options.sessionID),
|
|
44537
44815
|
enrichmentQuota: {
|
|
44538
|
-
maxCalls:
|
|
44539
|
-
window:
|
|
44816
|
+
maxCalls: config3.enrichment.max_calls_per_day,
|
|
44817
|
+
window: config3.enrichment.quota_window
|
|
44540
44818
|
}
|
|
44541
44819
|
});
|
|
44542
44820
|
curationSucceeded = true;
|
|
@@ -44601,7 +44879,11 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
44601
44879
|
config: skillImproverConfig,
|
|
44602
44880
|
targets: ["skills", "knowledge"],
|
|
44603
44881
|
mode: "proposal",
|
|
44604
|
-
sessionId: options.sessionID
|
|
44882
|
+
sessionId: options.sessionID,
|
|
44883
|
+
enrichmentQuota: {
|
|
44884
|
+
maxCalls: config3.enrichment.max_calls_per_day,
|
|
44885
|
+
window: config3.enrichment.quota_window
|
|
44886
|
+
}
|
|
44605
44887
|
}, options.skillReviewTimeoutMs ?? CLOSE_SKILL_REVIEW_TIMEOUT_MS);
|
|
44606
44888
|
if (skillReviewResult.ran) {
|
|
44607
44889
|
const proposal = skillReviewResult.proposalPath ? ` Proposal: ${skillReviewResult.proposalPath}.` : "";
|
|
@@ -45359,7 +45641,7 @@ var init_curate = __esm(() => {
|
|
|
45359
45641
|
// src/tools/co-change-analyzer.ts
|
|
45360
45642
|
import * as child_process3 from "child_process";
|
|
45361
45643
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
45362
|
-
import { readdir, readFile as readFile11, stat as
|
|
45644
|
+
import { readdir, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
45363
45645
|
import * as path31 from "path";
|
|
45364
45646
|
import { promisify } from "util";
|
|
45365
45647
|
function getExecFileAsync() {
|
|
@@ -45510,7 +45792,7 @@ async function getStaticEdges(directory) {
|
|
|
45510
45792
|
for (const ext of extensions) {
|
|
45511
45793
|
const testPath = resolvedPath + ext;
|
|
45512
45794
|
try {
|
|
45513
|
-
const testStat = await
|
|
45795
|
+
const testStat = await stat4(testPath);
|
|
45514
45796
|
if (testStat.isFile()) {
|
|
45515
45797
|
targetFile = testPath;
|
|
45516
45798
|
break;
|
|
@@ -51774,7 +52056,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
|
51774
52056
|
// src/hooks/knowledge-migrator.ts
|
|
51775
52057
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
51776
52058
|
import { existsSync as existsSync26, readFileSync as readFileSync16 } from "fs";
|
|
51777
|
-
import { mkdir as mkdir12, readFile as readFile13, writeFile as
|
|
52059
|
+
import { mkdir as mkdir12, readFile as readFile13, writeFile as writeFile11 } from "fs/promises";
|
|
51778
52060
|
import * as os8 from "os";
|
|
51779
52061
|
import * as path39 from "path";
|
|
51780
52062
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
@@ -52123,7 +52405,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
52123
52405
|
migration_tool: "knowledge-migrator.ts"
|
|
52124
52406
|
};
|
|
52125
52407
|
await mkdir12(path39.dirname(sentinelPath), { recursive: true });
|
|
52126
|
-
await
|
|
52408
|
+
await writeFile11(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
52127
52409
|
}
|
|
52128
52410
|
function resolveLegacyHiveKnowledgePath() {
|
|
52129
52411
|
const platform = process.platform;
|
|
@@ -52540,7 +52822,7 @@ var init_redaction = __esm(() => {
|
|
|
52540
52822
|
});
|
|
52541
52823
|
|
|
52542
52824
|
// src/memory/schema.ts
|
|
52543
|
-
import { createHash as
|
|
52825
|
+
import { createHash as createHash7 } from "crypto";
|
|
52544
52826
|
function normalizeMemoryText(text) {
|
|
52545
52827
|
return text.replace(/\s+/g, " ").trim();
|
|
52546
52828
|
}
|
|
@@ -52564,7 +52846,7 @@ function stableScopeKey(scope) {
|
|
|
52564
52846
|
}
|
|
52565
52847
|
function computeMemoryContentHash(recordLike) {
|
|
52566
52848
|
const normalized = normalizeMemoryText(recordLike.text).toLowerCase();
|
|
52567
|
-
return
|
|
52849
|
+
return createHash7("sha256").update(`${stableScopeKey(recordLike.scope)}
|
|
52568
52850
|
${recordLike.kind}
|
|
52569
52851
|
${normalized}`).digest("hex");
|
|
52570
52852
|
}
|
|
@@ -53316,7 +53598,7 @@ import {
|
|
|
53316
53598
|
mkdir as mkdir13,
|
|
53317
53599
|
readFile as readFile14,
|
|
53318
53600
|
rename as rename7,
|
|
53319
|
-
writeFile as
|
|
53601
|
+
writeFile as writeFile12
|
|
53320
53602
|
} from "fs/promises";
|
|
53321
53603
|
import * as path40 from "path";
|
|
53322
53604
|
|
|
@@ -53727,7 +54009,7 @@ async function writeJsonlAtomic(filePath, values) {
|
|
|
53727
54009
|
const content = values.map((value) => JSON.stringify(value)).join(`
|
|
53728
54010
|
`) + (values.length > 0 ? `
|
|
53729
54011
|
` : "");
|
|
53730
|
-
await
|
|
54012
|
+
await writeFile12(tmp, content, "utf-8");
|
|
53731
54013
|
await rename7(tmp, filePath);
|
|
53732
54014
|
}
|
|
53733
54015
|
var init_local_jsonl_provider = __esm(() => {
|
|
@@ -53748,7 +54030,7 @@ var init_prompt_block = __esm(() => {
|
|
|
53748
54030
|
|
|
53749
54031
|
// src/memory/jsonl-migration.ts
|
|
53750
54032
|
import { existsSync as existsSync28 } from "fs";
|
|
53751
|
-
import { copyFile, mkdir as mkdir14, readFile as readFile15, stat as
|
|
54033
|
+
import { copyFile, mkdir as mkdir14, readFile as readFile15, stat as stat5, writeFile as writeFile13 } from "fs/promises";
|
|
53752
54034
|
import * as path41 from "path";
|
|
53753
54035
|
function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
|
|
53754
54036
|
const resolved = resolveConfig(config3);
|
|
@@ -53796,14 +54078,14 @@ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
|
|
|
53796
54078
|
await mkdir14(exportDir, { recursive: true });
|
|
53797
54079
|
const memoriesPath = path41.join(exportDir, "memories.jsonl");
|
|
53798
54080
|
const proposalsPath = path41.join(exportDir, "proposals.jsonl");
|
|
53799
|
-
await
|
|
53800
|
-
await
|
|
54081
|
+
await writeFile13(memoriesPath, toJsonl(memories), "utf-8");
|
|
54082
|
+
await writeFile13(proposalsPath, toJsonl(proposals), "utf-8");
|
|
53801
54083
|
return { directory: exportDir, memoriesPath, proposalsPath };
|
|
53802
54084
|
}
|
|
53803
54085
|
async function writeMigrationReport(rootDirectory, report, config3 = {}) {
|
|
53804
54086
|
const reportPath = path41.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
|
|
53805
54087
|
await mkdir14(path41.dirname(reportPath), { recursive: true });
|
|
53806
|
-
await
|
|
54088
|
+
await writeFile13(reportPath, `${JSON.stringify(report, null, 2)}
|
|
53807
54089
|
`, "utf-8");
|
|
53808
54090
|
return reportPath;
|
|
53809
54091
|
}
|
|
@@ -53824,7 +54106,7 @@ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
|
|
|
53824
54106
|
const filePath = path41.join(storageDir, file3);
|
|
53825
54107
|
let sizeBytes = 0;
|
|
53826
54108
|
if (existsSync28(filePath)) {
|
|
53827
|
-
sizeBytes = (await
|
|
54109
|
+
sizeBytes = (await stat5(filePath)).size;
|
|
53828
54110
|
}
|
|
53829
54111
|
statuses.push({
|
|
53830
54112
|
file: file3,
|
|
@@ -57559,8 +57841,8 @@ var init_secretscan = __esm(() => {
|
|
|
57559
57841
|
break;
|
|
57560
57842
|
const fileFindings = scanFileForSecrets(filePath);
|
|
57561
57843
|
try {
|
|
57562
|
-
const
|
|
57563
|
-
if (
|
|
57844
|
+
const stat6 = fs19.statSync(filePath);
|
|
57845
|
+
if (stat6.size > MAX_FILE_SIZE_BYTES) {
|
|
57564
57846
|
skippedFiles++;
|
|
57565
57847
|
continue;
|
|
57566
57848
|
}
|
|
@@ -58370,8 +58652,8 @@ function sharedTrailingSegments(a, b) {
|
|
|
58370
58652
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
58371
58653
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
58372
58654
|
try {
|
|
58373
|
-
const
|
|
58374
|
-
if (
|
|
58655
|
+
const stat6 = fs23.statSync(sourcePath);
|
|
58656
|
+
if (stat6.mtimeMs > generatedAtMs) {
|
|
58375
58657
|
return true;
|
|
58376
58658
|
}
|
|
58377
58659
|
} catch {
|
|
@@ -59672,8 +59954,8 @@ function manifestHash(dir) {
|
|
|
59672
59954
|
if (!entries.has(name))
|
|
59673
59955
|
continue;
|
|
59674
59956
|
try {
|
|
59675
|
-
const
|
|
59676
|
-
parts.push(`${name}:${
|
|
59957
|
+
const stat6 = fs28.statSync(path56.join(dir, name));
|
|
59958
|
+
parts.push(`${name}:${stat6.size}:${stat6.mtimeMs}:${stat6.ino}`);
|
|
59677
59959
|
} catch {}
|
|
59678
59960
|
}
|
|
59679
59961
|
return parts.join("|");
|