gossipcat 0.6.8 → 0.6.9
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-mcp/mcp-server.js +164 -13
- package/package.json +1 -1
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -24760,7 +24760,7 @@ This section will be used for cross-review with peer agents.
|
|
|
24760
24760
|
|
|
24761
24761
|
${OUTPUT_DELIVERY_PROTOCOL}` });
|
|
24762
24762
|
} else {
|
|
24763
|
-
const hasAnyMeaningfulPart = !!(parts.identity || parts.instructions || parts.memory || parts.memoryDir || parts.lens || parts.skills || parts.context || parts.sessionContext || parts.chainContext || parts.specReviewContext || parts.projectStructure || parts.task || parts.consensusFindings && parts.consensusFindings.length > 0);
|
|
24763
|
+
const hasAnyMeaningfulPart = !!(parts.identity || parts.instructions || parts.memory || parts.memoryDir || parts.lens || parts.skills || parts.context || parts.sessionContext || parts.chainContext || parts.specReviewContext || parts.projectStructure || parts.task || parts.consensusFindings && parts.consensusFindings.length > 0 || parts.agentCorrections && parts.agentCorrections.length > 0);
|
|
24764
24764
|
if (hasAnyMeaningfulPart) {
|
|
24765
24765
|
suffix.push({ priority: 0, text: `
|
|
24766
24766
|
|
|
@@ -24786,13 +24786,18 @@ ${parts.lens}
|
|
|
24786
24786
|
${parts.specReviewContext}
|
|
24787
24787
|
--- END SPEC REVIEW ---` });
|
|
24788
24788
|
}
|
|
24789
|
-
if (parts.memory || parts.consensusFindings && parts.consensusFindings.length > 0) {
|
|
24789
|
+
if (parts.memory || parts.consensusFindings && parts.consensusFindings.length > 0 || parts.agentCorrections && parts.agentCorrections.length > 0) {
|
|
24790
24790
|
const memParts = [];
|
|
24791
24791
|
if (parts.memory) memParts.push(parts.memory);
|
|
24792
24792
|
if (parts.consensusFindings && parts.consensusFindings.length > 0) {
|
|
24793
24793
|
const findingsBlock = "### Recent Consensus Findings\n" + parts.consensusFindings.map((f, i) => `${i + 1}. ${f}`).join("\n");
|
|
24794
24794
|
memParts.push(findingsBlock);
|
|
24795
24795
|
}
|
|
24796
|
+
if (parts.agentCorrections && parts.agentCorrections.length > 0) {
|
|
24797
|
+
memParts.push(
|
|
24798
|
+
"### Your Prior Corrections\n" + parts.agentCorrections.map((f, i) => `${i + 1}. ${f}`).join("\n")
|
|
24799
|
+
);
|
|
24800
|
+
}
|
|
24796
24801
|
suffix.push({ priority: 3, text: `
|
|
24797
24802
|
|
|
24798
24803
|
--- MEMORY ---
|
|
@@ -24911,7 +24916,7 @@ var init_prompt_assembler = __esm({
|
|
|
24911
24916
|
});
|
|
24912
24917
|
|
|
24913
24918
|
// packages/orchestrator/src/agent-memory.ts
|
|
24914
|
-
var import_fs20, import_path21, FINDINGS_MAX_RESULTS, FINDINGS_MAX_CHARS, FINDINGS_STALE_DAYS, FINDINGS_MIN_SCORE, AgentMemoryReader;
|
|
24919
|
+
var import_fs20, import_path21, FINDINGS_MAX_RESULTS, FINDINGS_MAX_CHARS, FINDINGS_STALE_DAYS, FINDINGS_MIN_SCORE, CORRECTIONS_MAX_RESULTS, AgentMemoryReader;
|
|
24915
24920
|
var init_agent_memory = __esm({
|
|
24916
24921
|
"packages/orchestrator/src/agent-memory.ts"() {
|
|
24917
24922
|
"use strict";
|
|
@@ -24921,6 +24926,7 @@ var init_agent_memory = __esm({
|
|
|
24921
24926
|
FINDINGS_MAX_CHARS = 150;
|
|
24922
24927
|
FINDINGS_STALE_DAYS = 30;
|
|
24923
24928
|
FINDINGS_MIN_SCORE = 1;
|
|
24929
|
+
CORRECTIONS_MAX_RESULTS = 2;
|
|
24924
24930
|
AgentMemoryReader = class {
|
|
24925
24931
|
constructor(projectRoot) {
|
|
24926
24932
|
this.projectRoot = projectRoot;
|
|
@@ -25021,6 +25027,46 @@ ${content}
|
|
|
25021
25027
|
}
|
|
25022
25028
|
return scored.sort((a, b) => b.score - a.score).slice(0, FINDINGS_MAX_RESULTS).map((s) => s.text);
|
|
25023
25029
|
}
|
|
25030
|
+
/**
|
|
25031
|
+
* Pre-fetch this agent's own prior lesson cards relevant to the task (issue #642 B-delta).
|
|
25032
|
+
* Selects by `lesson-*.md` filename (not frontmatter `type`, which parsers don't read),
|
|
25033
|
+
* ranks by body keyword overlap, drops cards older than FINDINGS_STALE_DAYS, and strips
|
|
25034
|
+
* prompt-injection delimiters before returning. Returns top CORRECTIONS_MAX_RESULTS snippets.
|
|
25035
|
+
*/
|
|
25036
|
+
prefetchAgentCorrectionsText(agentId, taskText) {
|
|
25037
|
+
if (!agentId || /[/\\.\0]/.test(agentId)) return [];
|
|
25038
|
+
const knowledgeDir = (0, import_path21.join)(this.projectRoot, ".gossip", "agents", agentId, "memory", "knowledge");
|
|
25039
|
+
if (!(0, import_fs20.existsSync)(knowledgeDir)) return [];
|
|
25040
|
+
let files;
|
|
25041
|
+
try {
|
|
25042
|
+
files = (0, import_fs20.readdirSync)(knowledgeDir).filter((f) => f.startsWith("lesson-") && f.endsWith(".md"));
|
|
25043
|
+
} catch {
|
|
25044
|
+
return [];
|
|
25045
|
+
}
|
|
25046
|
+
if (files.length === 0) return [];
|
|
25047
|
+
const keywords = this.extractKeywords(taskText);
|
|
25048
|
+
if (keywords.length === 0) return [];
|
|
25049
|
+
const cutoffMs = Date.now() - FINDINGS_STALE_DAYS * 864e5;
|
|
25050
|
+
const scored = [];
|
|
25051
|
+
for (const file2 of files) {
|
|
25052
|
+
const filePath = (0, import_path21.join)(knowledgeDir, file2);
|
|
25053
|
+
let content;
|
|
25054
|
+
try {
|
|
25055
|
+
const mtime = (0, import_fs20.statSync)(filePath).mtimeMs;
|
|
25056
|
+
if (mtime < cutoffMs) continue;
|
|
25057
|
+
content = (0, import_fs20.readFileSync)(filePath, "utf-8");
|
|
25058
|
+
} catch {
|
|
25059
|
+
continue;
|
|
25060
|
+
}
|
|
25061
|
+
const body = content.replace(/^---\n[\s\S]*?\n---\n*/, "").replace(/<\/?(?:agent-memory|system|instructions)>/gi, "").replace(/\s+/g, " ").trim();
|
|
25062
|
+
if (!body) continue;
|
|
25063
|
+
const score = this.scoreKeywords(keywords, body);
|
|
25064
|
+
if (score >= FINDINGS_MIN_SCORE) {
|
|
25065
|
+
scored.push({ text: body.slice(0, FINDINGS_MAX_CHARS).trim(), score });
|
|
25066
|
+
}
|
|
25067
|
+
}
|
|
25068
|
+
return scored.sort((a, b) => b.score - a.score).slice(0, CORRECTIONS_MAX_RESULTS).map((s) => s.text);
|
|
25069
|
+
}
|
|
25024
25070
|
/** Simple word-boundary keyword overlap scoring (no LLM). */
|
|
25025
25071
|
extractKeywords(taskText) {
|
|
25026
25072
|
const words = taskText.toLowerCase().split(/[\s,/.;:!?()\[\]{}*_~`"'<>|]+/);
|
|
@@ -25505,7 +25551,21 @@ function validateAgentId(agentId) {
|
|
|
25505
25551
|
function sanitizeTaskId(taskId) {
|
|
25506
25552
|
return taskId.replace(/[/\\:*?"<>|\0]/g, "_");
|
|
25507
25553
|
}
|
|
25508
|
-
|
|
25554
|
+
function writeLessonCardsForSignals(projectRoot, signals) {
|
|
25555
|
+
if (!Array.isArray(signals) || signals.length === 0) return;
|
|
25556
|
+
const writer = new MemoryWriter(projectRoot);
|
|
25557
|
+
for (const s of signals) {
|
|
25558
|
+
if (!s || !s.finding_id || !TERMINAL_LESSON_SIGNALS.has(s.signal)) continue;
|
|
25559
|
+
writer.writeLessonCard(s.agent_id, {
|
|
25560
|
+
signal: s.signal,
|
|
25561
|
+
findingId: s.finding_id,
|
|
25562
|
+
finding: s.finding ?? "",
|
|
25563
|
+
lesson: s.lesson,
|
|
25564
|
+
taskTokens: s.finding
|
|
25565
|
+
});
|
|
25566
|
+
}
|
|
25567
|
+
}
|
|
25568
|
+
var import_fs23, import_path24, import_crypto11, TERMINAL_LESSON_SIGNALS, LESSON_CARDS_MAX_PER_AGENT, LESSON_RESERVED_AGENT_IDS, MemoryWriter;
|
|
25509
25569
|
var init_memory_writer = __esm({
|
|
25510
25570
|
"packages/orchestrator/src/memory-writer.ts"() {
|
|
25511
25571
|
"use strict";
|
|
@@ -25516,6 +25576,13 @@ var init_memory_writer = __esm({
|
|
|
25516
25576
|
init_project_structure();
|
|
25517
25577
|
init_log();
|
|
25518
25578
|
init_completion_signals();
|
|
25579
|
+
TERMINAL_LESSON_SIGNALS = /* @__PURE__ */ new Set([
|
|
25580
|
+
"hallucination_caught",
|
|
25581
|
+
"impl_test_fail",
|
|
25582
|
+
"impl_peer_rejected"
|
|
25583
|
+
]);
|
|
25584
|
+
LESSON_CARDS_MAX_PER_AGENT = 200;
|
|
25585
|
+
LESSON_RESERVED_AGENT_IDS = /* @__PURE__ */ new Set(["_project", "_system", "_utility"]);
|
|
25519
25586
|
MemoryWriter = class {
|
|
25520
25587
|
constructor(projectRoot) {
|
|
25521
25588
|
this.projectRoot = projectRoot;
|
|
@@ -26088,7 +26155,7 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
26088
26155
|
/** Shared warmth-aware pruning — evicts lowest-warmth files, respects pinned */
|
|
26089
26156
|
pruneKnowledgeDir(knowledgeDir, maxFiles) {
|
|
26090
26157
|
try {
|
|
26091
|
-
const existing = (0, import_fs23.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md") && !f.endsWith("-session.md")).sort();
|
|
26158
|
+
const existing = (0, import_fs23.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md") && !f.endsWith("-session.md") && !f.startsWith("lesson-")).sort();
|
|
26092
26159
|
if (existing.length >= maxFiles) {
|
|
26093
26160
|
const scored = existing.map((f) => {
|
|
26094
26161
|
const content = (0, import_fs23.readFileSync)((0, import_path24.join)(knowledgeDir, f), "utf-8");
|
|
@@ -26392,6 +26459,76 @@ ${result}`;
|
|
|
26392
26459
|
this.pruneKnowledgeDir(knowledgeDir, 25);
|
|
26393
26460
|
(0, import_fs23.writeFileSync)((0, import_path24.join)(knowledgeDir, filename), content);
|
|
26394
26461
|
}
|
|
26462
|
+
/**
|
|
26463
|
+
* Write a recallable "lesson card" for a terminal correction signal (issue #642 A).
|
|
26464
|
+
* Best-effort: any failure is swallowed — this MUST NOT fail signal recording.
|
|
26465
|
+
* Idempotent: keyed by finding_id via sanitizeTaskId, no timestamp in the filename.
|
|
26466
|
+
*/
|
|
26467
|
+
writeLessonCard(agentId, card) {
|
|
26468
|
+
try {
|
|
26469
|
+
if (LESSON_RESERVED_AGENT_IDS.has(agentId)) return;
|
|
26470
|
+
validateAgentId(agentId);
|
|
26471
|
+
const slug = sanitizeTaskId(card.findingId).slice(0, 96);
|
|
26472
|
+
if (!slug) return;
|
|
26473
|
+
const memDir = this.ensureDirs(agentId);
|
|
26474
|
+
const knowledgeDir = (0, import_path24.join)(memDir, "knowledge");
|
|
26475
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
26476
|
+
const generated = (/* @__PURE__ */ new Date()).toISOString();
|
|
26477
|
+
const shortId = slug.slice(0, 24);
|
|
26478
|
+
const finding = truncateAtWord(sanitizeYamlValue(card.finding ?? ""), 400);
|
|
26479
|
+
const lessonBody = card.lesson ? truncateAtWord(sanitizeYamlValue(card.lesson), 400) : "(no root-cause supplied)";
|
|
26480
|
+
const desc = sanitizeYamlValue(card.lesson || card.finding || "lesson").slice(0, 80);
|
|
26481
|
+
const taskTokens = (card.taskTokens ?? card.finding ?? "").replace(/[\n\r]/g, " ").slice(0, 300);
|
|
26482
|
+
const content = [
|
|
26483
|
+
"---",
|
|
26484
|
+
`name: lesson-${sanitizeYamlValue(card.signal)}-${shortId}`,
|
|
26485
|
+
`description: ${desc}`,
|
|
26486
|
+
"type: lesson",
|
|
26487
|
+
`agent: ${sanitizeYamlValue(agentId)}`,
|
|
26488
|
+
`signal: ${sanitizeYamlValue(card.signal)}`,
|
|
26489
|
+
`finding_id: ${sanitizeYamlValue(card.findingId)}`,
|
|
26490
|
+
"importance: 0.7",
|
|
26491
|
+
`lastAccessed: ${today}`,
|
|
26492
|
+
"accessCount: 0",
|
|
26493
|
+
`generated: ${generated}`,
|
|
26494
|
+
"---",
|
|
26495
|
+
"",
|
|
26496
|
+
`**Why it failed:** ${lessonBody}`,
|
|
26497
|
+
"",
|
|
26498
|
+
`**What happened:** ${finding}`,
|
|
26499
|
+
"",
|
|
26500
|
+
`**Task context:** ${taskTokens}`
|
|
26501
|
+
].join("\n");
|
|
26502
|
+
const cardPath = (0, import_path24.join)(knowledgeDir, `lesson-${slug}.md`);
|
|
26503
|
+
if (!(0, import_fs23.existsSync)(cardPath)) this.pruneLessonCards(knowledgeDir, LESSON_CARDS_MAX_PER_AGENT);
|
|
26504
|
+
(0, import_fs23.writeFileSync)(cardPath, content);
|
|
26505
|
+
} catch {
|
|
26506
|
+
}
|
|
26507
|
+
}
|
|
26508
|
+
/** Count-based prune of lesson-*.md only (leaves consensus/session knowledge untouched). */
|
|
26509
|
+
pruneLessonCards(knowledgeDir, maxFiles) {
|
|
26510
|
+
try {
|
|
26511
|
+
const cards = (0, import_fs23.readdirSync)(knowledgeDir).filter((f) => f.startsWith("lesson-") && f.endsWith(".md"));
|
|
26512
|
+
if (cards.length < maxFiles) return;
|
|
26513
|
+
const withMtime = cards.map((f) => {
|
|
26514
|
+
let mtime = 0;
|
|
26515
|
+
try {
|
|
26516
|
+
mtime = (0, import_fs23.statSync)((0, import_path24.join)(knowledgeDir, f)).mtimeMs;
|
|
26517
|
+
} catch {
|
|
26518
|
+
}
|
|
26519
|
+
return { f, mtime };
|
|
26520
|
+
});
|
|
26521
|
+
withMtime.sort((a, b) => a.mtime - b.mtime);
|
|
26522
|
+
const toEvict = withMtime.slice(0, cards.length - (maxFiles - 1));
|
|
26523
|
+
for (const item of toEvict) {
|
|
26524
|
+
try {
|
|
26525
|
+
(0, import_fs23.unlinkSync)((0, import_path24.join)(knowledgeDir, item.f));
|
|
26526
|
+
} catch {
|
|
26527
|
+
}
|
|
26528
|
+
}
|
|
26529
|
+
} catch {
|
|
26530
|
+
}
|
|
26531
|
+
}
|
|
26395
26532
|
/**
|
|
26396
26533
|
* Update task memory importance based on consensus signals.
|
|
26397
26534
|
* High-quality findings get boosted, hallucinations get reduced.
|
|
@@ -32298,6 +32435,10 @@ var init_dispatch_pipeline = __esm({
|
|
|
32298
32435
|
if (consensusFindings.length > 0) {
|
|
32299
32436
|
gossipLog(`\u{1F4CB} pre-fetched ${consensusFindings.length} consensus findings for ${agentId}`);
|
|
32300
32437
|
}
|
|
32438
|
+
const agentCorrections = this.memReader.prefetchAgentCorrectionsText(agentId, task);
|
|
32439
|
+
if (agentCorrections.length > 0) {
|
|
32440
|
+
gossipLog(`\u{1F9E0} pre-fetched ${agentCorrections.length} prior corrections for ${agentId}`);
|
|
32441
|
+
}
|
|
32301
32442
|
const effectiveSkills = resolveEffectiveSkills(agentId, agentSkills, this.skillIndex ?? void 0);
|
|
32302
32443
|
const skillWarnings = this.catalog ? this.catalog.checkCoverage(effectiveSkills, task) : [];
|
|
32303
32444
|
const sessionGossip = this.sessionContext.getSessionGossip();
|
|
@@ -32348,7 +32489,8 @@ var init_dispatch_pipeline = __esm({
|
|
|
32348
32489
|
consensusSummary: options?.consensus,
|
|
32349
32490
|
specReviewContext,
|
|
32350
32491
|
projectStructure: this.getProjectStructure(),
|
|
32351
|
-
consensusFindings: consensusFindings.length > 0 ? consensusFindings : void 0
|
|
32492
|
+
consensusFindings: consensusFindings.length > 0 ? consensusFindings : void 0,
|
|
32493
|
+
agentCorrections: agentCorrections.length > 0 ? agentCorrections : void 0
|
|
32352
32494
|
});
|
|
32353
32495
|
this.taskGraph.recordCreated(taskId, agentId, task, agentSkills);
|
|
32354
32496
|
const entry = {
|
|
@@ -40598,6 +40740,7 @@ __export(src_exports3, {
|
|
|
40598
40740
|
JACCARD_THRESHOLD: () => JACCARD_THRESHOLD,
|
|
40599
40741
|
KEY_REQUIRING_PROVIDERS: () => KEY_REQUIRING_PROVIDERS,
|
|
40600
40742
|
LEDGER_INDEX_FILENAME: () => LEDGER_INDEX_FILENAME,
|
|
40743
|
+
LESSON_CARDS_MAX_PER_AGENT: () => LESSON_CARDS_MAX_PER_AGENT,
|
|
40601
40744
|
LensGenerator: () => LensGenerator,
|
|
40602
40745
|
MAX_ASSEMBLED_PROMPT_CHARS: () => MAX_ASSEMBLED_PROMPT_CHARS,
|
|
40603
40746
|
MAX_CLAIMS_PER_BLOCK: () => MAX_CLAIMS_PER_BLOCK,
|
|
@@ -40641,6 +40784,7 @@ __export(src_exports3, {
|
|
|
40641
40784
|
SkillEngine: () => SkillEngine,
|
|
40642
40785
|
SkillGapTracker: () => SkillGapTracker,
|
|
40643
40786
|
SkillIndex: () => SkillIndex,
|
|
40787
|
+
TERMINAL_LESSON_SIGNALS: () => TERMINAL_LESSON_SIGNALS,
|
|
40644
40788
|
TIMEOUT_DAYS: () => TIMEOUT_DAYS,
|
|
40645
40789
|
TIMEOUT_MS: () => TIMEOUT_MS,
|
|
40646
40790
|
TOOL_SCHEMAS: () => TOOL_SCHEMAS2,
|
|
@@ -40808,6 +40952,7 @@ __export(src_exports3, {
|
|
|
40808
40952
|
verifyClaims: () => verifyClaims,
|
|
40809
40953
|
withResolverLock: () => withResolverLock,
|
|
40810
40954
|
writeLedgerIndex: () => writeLedgerIndex,
|
|
40955
|
+
writeLessonCardsForSignals: () => writeLessonCardsForSignals,
|
|
40811
40956
|
writeOrchestratorRoleMarker: () => writeOrchestratorRoleMarker
|
|
40812
40957
|
});
|
|
40813
40958
|
var init_src4 = __esm({
|
|
@@ -46531,11 +46676,11 @@ var init_routes = __esm({
|
|
|
46531
46676
|
}
|
|
46532
46677
|
if (!existsSync74(reportsDir)) return { reports: [], totalReports: 0, page, pageSize, retractedConsensusIds, roundRetractions };
|
|
46533
46678
|
try {
|
|
46534
|
-
const { statSync:
|
|
46679
|
+
const { statSync: statSync37 } = require("fs");
|
|
46535
46680
|
const allFiles = readdirSync22(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
|
|
46536
46681
|
try {
|
|
46537
|
-
const aTime =
|
|
46538
|
-
const bTime =
|
|
46682
|
+
const aTime = statSync37((0, import_path80.join)(reportsDir, a)).mtimeMs;
|
|
46683
|
+
const bTime = statSync37((0, import_path80.join)(reportsDir, b)).mtimeMs;
|
|
46539
46684
|
return bTime - aTime;
|
|
46540
46685
|
} catch {
|
|
46541
46686
|
return 0;
|
|
@@ -49403,7 +49548,7 @@ function appendRelayWarning(projectRoot, entry) {
|
|
|
49403
49548
|
}
|
|
49404
49549
|
function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
49405
49550
|
try {
|
|
49406
|
-
const { readdirSync: readdirSync22, statSync:
|
|
49551
|
+
const { readdirSync: readdirSync22, statSync: statSync37 } = require("fs");
|
|
49407
49552
|
const { join: join93 } = require("path");
|
|
49408
49553
|
const wtDir = join93(projectRoot, ".claude", "worktrees");
|
|
49409
49554
|
let entries;
|
|
@@ -49416,7 +49561,7 @@ function checkWorktreeEngaged(startedAt, projectRoot = process.cwd()) {
|
|
|
49416
49561
|
for (const entry of entries) {
|
|
49417
49562
|
if (!entry.startsWith("agent-")) continue;
|
|
49418
49563
|
try {
|
|
49419
|
-
const st =
|
|
49564
|
+
const st = statSync37(join93(wtDir, entry));
|
|
49420
49565
|
if (st.isDirectory() && st.mtimeMs >= startedAt - 2e3) return true;
|
|
49421
49566
|
} catch {
|
|
49422
49567
|
}
|
|
@@ -81759,7 +81904,7 @@ Ledger: ${ledgerPath2}`
|
|
|
81759
81904
|
} catch {
|
|
81760
81905
|
}
|
|
81761
81906
|
try {
|
|
81762
|
-
const { readdirSync: readdirSync22, statSync:
|
|
81907
|
+
const { readdirSync: readdirSync22, statSync: statSync37, readFileSync: readFileSync70 } = await import("fs");
|
|
81763
81908
|
const { readJsonlWithRotated: readJsonlRotated1506 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
81764
81909
|
const reportsDir = (0, import_path97.join)(process.cwd(), ".gossip", "consensus-reports");
|
|
81765
81910
|
const perfPath = (0, import_path97.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
@@ -81770,7 +81915,7 @@ Ledger: ${ledgerPath2}`
|
|
|
81770
81915
|
for (const fname of readdirSync22(reportsDir)) {
|
|
81771
81916
|
if (!fname.endsWith(".json")) continue;
|
|
81772
81917
|
const fpath = (0, import_path97.join)(reportsDir, fname);
|
|
81773
|
-
const st =
|
|
81918
|
+
const st = statSync37(fpath);
|
|
81774
81919
|
if (now - st.mtimeMs > WINDOW_MS3) continue;
|
|
81775
81920
|
try {
|
|
81776
81921
|
const report = JSON.parse(readFileSync70(fpath, "utf8"));
|
|
@@ -82595,6 +82740,7 @@ ${output}` }]
|
|
|
82595
82740
|
agent_id: external_exports.string().describe("Agent being evaluated"),
|
|
82596
82741
|
counterpart_id: external_exports.string().optional().describe("The other agent involved (e.g., who won the disagreement)"),
|
|
82597
82742
|
finding: external_exports.string().describe("Brief description of the finding"),
|
|
82743
|
+
lesson: external_exports.string().optional().describe("Root-cause narrative for a terminal correction signal \u2014 1-2 sentences on why it failed and the check that would have caught it. Written verbatim into the discovering agent's lesson card (issue #642 A)."),
|
|
82598
82744
|
finding_id: external_exports.string().optional().describe("Consensus finding ID \u2014 links this signal to a specific finding in a consensus report. Enables dashboard to resolve UNVERIFIED findings."),
|
|
82599
82745
|
severity: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("Finding severity for impact scoring. If omitted, defaults to medium."),
|
|
82600
82746
|
category: external_exports.string().optional().describe("Finding category for ATI competency profiles (e.g., concurrency, trust_boundaries, injection_vectors, resource_exhaustion, type_safety, error_handling, data_integrity, input_validation)"),
|
|
@@ -83083,6 +83229,11 @@ Uncategorized finding_ids: ${uncategorized.join(", ")}`;
|
|
|
83083
83229
|
if (dedupedConsensus.length > 0) emitRecordConsensusSignals(process.cwd(), dedupedConsensus);
|
|
83084
83230
|
if (dedupedImpl.length > 0) emitRecordImplSignals(process.cwd(), dedupedImpl);
|
|
83085
83231
|
}
|
|
83232
|
+
try {
|
|
83233
|
+
const { writeLessonCardsForSignals: writeLessonCardsForSignals2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
83234
|
+
writeLessonCardsForSignals2(process.cwd(), signals ?? []);
|
|
83235
|
+
} catch {
|
|
83236
|
+
}
|
|
83086
83237
|
const hallucinationSignals = deduped.filter(
|
|
83087
83238
|
(s) => s.type === "consensus" && s.signal === "hallucination_caught"
|
|
83088
83239
|
);
|
package/package.json
CHANGED