tribunal-kit 5.7.0 → 5.8.1
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/.agent/ARCHITECTURE.md +6 -7
- package/.agent/agents/frontend-reviewer.md +13 -0
- package/.agent/agents/frontend-specialist.md +14 -0
- package/.agent/agents/logic-reviewer.md +11 -0
- package/.agent/agents/orchestrator.md +15 -0
- package/.agent/agents/project-planner.md +5 -0
- package/.agent/agents/security-auditor.md +13 -0
- package/.agent/agents/ui-ux-auditor.md +7 -31
- package/.agent/history/memory/.memory.idx +1693 -0
- package/.agent/history/memory/MEMORY.md +123 -0
- package/.agent/routing_index.json +694 -714
- package/.agent/rules/GEMINI.md +88 -13
- package/.agent/scripts/_colors.js +131 -89
- package/.agent/scripts/_utils.js +163 -128
- package/.agent/scripts/auto_preview.js +207 -197
- package/.agent/scripts/bundle_analyzer.js +227 -192
- package/.agent/scripts/case_law_manager.js +991 -689
- package/.agent/scripts/checklist.js +233 -190
- package/.agent/scripts/context_broker.js +930 -605
- package/.agent/scripts/dependency_analyzer.js +275 -184
- package/.agent/scripts/graph_builder.js +412 -341
- package/.agent/scripts/graph_visualizer.js +392 -390
- package/.agent/scripts/graph_zoom.js +198 -156
- package/.agent/scripts/inner_loop_validator.js +523 -445
- package/.agent/scripts/lint_runner.js +199 -157
- package/.agent/scripts/marathon_harness.js +819 -661
- package/.agent/scripts/minify_context.js +115 -100
- package/.agent/scripts/mutation_runner.js +321 -280
- package/.agent/scripts/prompt_compiler.js +62 -42
- package/.agent/scripts/schema_validator.js +373 -280
- package/.agent/scripts/security_scan.js +333 -190
- package/.agent/scripts/session_manager.js +306 -270
- package/.agent/scripts/skill_evolution.js +810 -637
- package/.agent/scripts/skill_integrator.js +327 -307
- package/.agent/scripts/strengthen_skills.js +203 -193
- package/.agent/scripts/swarm_dispatcher.js +558 -457
- package/.agent/scripts/test_runner.js +178 -152
- package/.agent/scripts/verify_all.js +200 -168
- package/.agent/skills/fabel-protocol/SKILL.md +271 -0
- package/.agent/skills/thinking-protocol/SKILL.md +27 -0
- package/.agent/workflows/generate.md +2 -1
- package/.agent/workflows/tribunal-full.md +4 -3
- package/.agent/workflows/tribunal-speed.md +1 -1
- package/README.md +184 -58
- package/bin/mcp-server.js +496 -173
- package/bin/tribunal-kit.js +1245 -987
- package/bin/wrapper.js +108 -74
- package/dist/cli.js +44 -0
- package/dist/commands/align.js +201 -0
- package/dist/commands/case.js +23 -0
- package/dist/commands/compile.js +84 -0
- package/dist/commands/init.js +42 -0
- package/dist/commands/learn.js +57 -0
- package/dist/commands/memory.js +456 -0
- package/package.json +22 -10
- package/scripts/benchmark.js +162 -125
- package/scripts/changelog.js +196 -168
- package/scripts/sync-version.js +94 -81
- package/scripts/validate-payload.js +85 -78
package/dist/commands/init.js
CHANGED
|
@@ -281,6 +281,47 @@ async function generateIDEBridges(targetDir, agentDest, dryRun = false) {
|
|
|
281
281
|
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
282
282
|
# Source: .agent/rules/GEMINI.md
|
|
283
283
|
|
|
284
|
+
${rulesContent}
|
|
285
|
+
`;
|
|
286
|
+
// ── 2. Windsurf (.windsurfrules) ─────────────────────
|
|
287
|
+
const windsurfRules = `# Tribunal Kit — Windsurf Bridge
|
|
288
|
+
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
289
|
+
# Source: .agent/rules/GEMINI.md
|
|
290
|
+
|
|
291
|
+
${rulesContent}
|
|
292
|
+
`;
|
|
293
|
+
// ── 3. Gemini / Antigravity (.gemini/settings.json) ──
|
|
294
|
+
const geminiSettings = JSON.stringify({
|
|
295
|
+
"rules": [
|
|
296
|
+
{ "path": "../.agent/rules/GEMINI.md", "trigger": "always_on" }
|
|
297
|
+
],
|
|
298
|
+
"agents": { "directory": "../.agent/agents" },
|
|
299
|
+
"skills": { "directory": "../.agent/skills" },
|
|
300
|
+
"workflows": { "directory": "../.agent/workflows" }
|
|
301
|
+
}, null, 2) + '\n';
|
|
302
|
+
// ── Also create .gemini/GEMINI.md as a direct rules file ──
|
|
303
|
+
const geminiRulesBridge = `---
|
|
304
|
+
trigger: always_on
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
# Tribunal Kit — Gemini Bridge
|
|
308
|
+
# Auto-generated by tribunal-kit init.
|
|
309
|
+
# Full rules: .agent/rules/GEMINI.md
|
|
310
|
+
|
|
311
|
+
${rulesContent}
|
|
312
|
+
`;
|
|
313
|
+
// ── 4. GitHub Copilot (.github/copilot-instructions.md) ──
|
|
314
|
+
const copilotInstructions = `# Tribunal Kit — Copilot Bridge
|
|
315
|
+
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
316
|
+
# Source: .agent/rules/GEMINI.md
|
|
317
|
+
|
|
318
|
+
${rulesContent}
|
|
319
|
+
`;
|
|
320
|
+
// ── 5. Claude (.claude/CLAUDE.md) ─────────────────────
|
|
321
|
+
const claudeRules = `# Tribunal Kit — Claude Bridge
|
|
322
|
+
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
323
|
+
# Source: .agent/rules/GEMINI.md
|
|
324
|
+
|
|
284
325
|
${rulesContent}
|
|
285
326
|
`;
|
|
286
327
|
// Fire ALL bridge writes concurrently via Promise.all
|
|
@@ -295,3 +336,4 @@ ${rulesContent}
|
|
|
295
336
|
await Promise.all(bridges.map(b => writeBridge(b.path, b.content, b.label)));
|
|
296
337
|
console.log();
|
|
297
338
|
}
|
|
339
|
+
|
package/dist/commands/learn.js
CHANGED
|
@@ -55,6 +55,63 @@ async function cmdLearn(flags, quiet = false) {
|
|
|
55
55
|
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '\u25b8')} Search existing case law:`);
|
|
56
56
|
(0, logger_1.log)(` ${(0, logger_1.c)('white', 'npx tribunal-kit case search "your query"')}`);
|
|
57
57
|
console.log();
|
|
58
|
+
// Phase 3: Memory Distillation
|
|
59
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u229b')} ${(0, logger_1.bold)('Phase 3')} \u2014 Memory Distillation (storing project knowledge)`);
|
|
60
|
+
try {
|
|
61
|
+
const { _memoryStore } = require('./memory');
|
|
62
|
+
// Auto-extract SEMANTIC memories from project-idioms if it exists
|
|
63
|
+
const idiomsPath = path_1.default.join(agentDest, 'skills', 'project-idioms', 'SKILL.md');
|
|
64
|
+
let memoriesStored = 0;
|
|
65
|
+
if (fs_1.default.existsSync(idiomsPath)) {
|
|
66
|
+
const idiomsContent = fs_1.default.readFileSync(idiomsPath, 'utf8');
|
|
67
|
+
// Extract lines that look like project rules (lines starting with - or * that contain actionable content)
|
|
68
|
+
const ruleLines = idiomsContent.split('\n')
|
|
69
|
+
.filter(line => /^[\s]*[-*]\s+/.test(line) && line.trim().length > 20)
|
|
70
|
+
.map(line => line.replace(/^[\s]*[-*]\s+/, '').trim())
|
|
71
|
+
.slice(0, 10); // Cap at 10 to prevent bloat
|
|
72
|
+
|
|
73
|
+
for (const rule of ruleLines) {
|
|
74
|
+
try {
|
|
75
|
+
_memoryStore(agentDest, 'semantic', rule, ['project-idiom', 'auto-learned'], null);
|
|
76
|
+
memoriesStored++;
|
|
77
|
+
} catch {
|
|
78
|
+
// Skip duplicates or capacity errors silently
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Auto-extract PROCEDURAL memories from package.json scripts
|
|
83
|
+
const pkgPath = path_1.default.join(targetDir, 'package.json');
|
|
84
|
+
if (fs_1.default.existsSync(pkgPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
|
|
87
|
+
if (pkg.scripts) {
|
|
88
|
+
const importantScripts = ['build', 'test', 'dev', 'start', 'deploy', 'lint'];
|
|
89
|
+
for (const key of importantScripts) {
|
|
90
|
+
if (pkg.scripts[key]) {
|
|
91
|
+
try {
|
|
92
|
+
_memoryStore(agentDest, 'procedural',
|
|
93
|
+
`Run \`${pkg.scripts[key]}\` to ${key} the project`,
|
|
94
|
+
['build-script', key, 'auto-learned'], null);
|
|
95
|
+
memoriesStored++;
|
|
96
|
+
} catch {
|
|
97
|
+
// Skip
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
// Unreadable package.json
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (memoriesStored > 0) {
|
|
107
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '\u2714')} ${memoriesStored} memories auto-stored (semantic + procedural)`);
|
|
108
|
+
} else {
|
|
109
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '\u25b8')} No new memories to distill (run again after committing changes)`);
|
|
110
|
+
}
|
|
111
|
+
} catch (e) {
|
|
112
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', '\u26a0')} Memory distillation skipped: ${e.message || String(e)}`);
|
|
113
|
+
}
|
|
114
|
+
console.log();
|
|
58
115
|
(0, logger_1.log)(` ${(0, logger_1.c)('green', '\u2714')} ${(0, logger_1.bold)('Learn cycle complete.')} Your Tribunal grows smarter with every commit.`);
|
|
59
116
|
console.log();
|
|
60
117
|
}
|
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.cmdMemory = cmdMemory;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("../utils/logger");
|
|
10
|
+
const helpers_1 = require("../utils/helpers");
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Tribunal Memory Engine — Node.js CLI Handler
|
|
14
|
+
*
|
|
15
|
+
* Routes memory subcommands to the Rust binary when available,
|
|
16
|
+
* with a pure JS fallback for environments without native binaries.
|
|
17
|
+
*
|
|
18
|
+
* Commands:
|
|
19
|
+
* tk memory store --type semantic --content "..." --tags "db,orm"
|
|
20
|
+
* tk memory recall --query "database" --budget 2000
|
|
21
|
+
* tk memory gc
|
|
22
|
+
* tk memory stats
|
|
23
|
+
* tk memory export
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
// ── Memory Index I/O (JS fallback) ──────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
const MEMORY_DIR = 'history/memory';
|
|
29
|
+
const INDEX_FILE = '.memory.idx';
|
|
30
|
+
const PROJECTION_FILE = 'MEMORY.md';
|
|
31
|
+
const MAX_ENTRIES = 500;
|
|
32
|
+
const EPISODIC_TTL_DAYS = 30;
|
|
33
|
+
|
|
34
|
+
function getMemoryDir(agentDest) {
|
|
35
|
+
return path_1.default.join(agentDest, MEMORY_DIR);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function getIndexPath(agentDest) {
|
|
39
|
+
return path_1.default.join(getMemoryDir(agentDest), INDEX_FILE);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function getProjectionPath(agentDest) {
|
|
43
|
+
return path_1.default.join(getMemoryDir(agentDest), PROJECTION_FILE);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function loadIndex(agentDest) {
|
|
47
|
+
const indexPath = getIndexPath(agentDest);
|
|
48
|
+
if (!fs_1.default.existsSync(indexPath)) {
|
|
49
|
+
return { version: 1, entries: [], next_id: 1 };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const content = fs_1.default.readFileSync(indexPath, 'utf8');
|
|
53
|
+
return JSON.parse(content);
|
|
54
|
+
} catch {
|
|
55
|
+
return { version: 1, entries: [], next_id: 1 };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function saveIndex(agentDest, index) {
|
|
60
|
+
const memDir = getMemoryDir(agentDest);
|
|
61
|
+
fs_1.default.mkdirSync(memDir, { recursive: true });
|
|
62
|
+
const indexPath = getIndexPath(agentDest);
|
|
63
|
+
// Atomic write: write temp, rename
|
|
64
|
+
const tmpPath = indexPath + '.tmp';
|
|
65
|
+
fs_1.default.writeFileSync(tmpPath, JSON.stringify(index, null, 2), 'utf8');
|
|
66
|
+
fs_1.default.renameSync(tmpPath, indexPath);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function estimateTokens(text) {
|
|
70
|
+
return Math.ceil(text.length / 4);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function nowEpochStr() {
|
|
74
|
+
return `${Math.floor(Date.now() / 1000)}Z`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function daysSince(ts) {
|
|
78
|
+
const created = parseInt(ts.replace('Z', ''), 10) || 0;
|
|
79
|
+
const now = Math.floor(Date.now() / 1000);
|
|
80
|
+
return Math.floor((now - created) / 86400);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── Scoring Engine ──────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
const TYPE_PRIORITY = { semantic: 1.0, procedural: 0.9, episodic: 0.7, working: 0.5 };
|
|
86
|
+
|
|
87
|
+
function computeScore(entry, query) {
|
|
88
|
+
const queryLower = query.toLowerCase();
|
|
89
|
+
const contentLower = entry.content.toLowerCase();
|
|
90
|
+
|
|
91
|
+
let relevance = 0;
|
|
92
|
+
if (contentLower.includes(queryLower)) {
|
|
93
|
+
relevance = 1.0;
|
|
94
|
+
} else if (entry.tags.some(t => t.toLowerCase().includes(queryLower))) {
|
|
95
|
+
relevance = 0.8;
|
|
96
|
+
} else if (queryLower.split(/\s+/).some(word => contentLower.includes(word))) {
|
|
97
|
+
relevance = 0.3;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (relevance === 0) return 0;
|
|
101
|
+
|
|
102
|
+
const priority = TYPE_PRIORITY[entry.memory_type] || 0.5;
|
|
103
|
+
let recency = 0;
|
|
104
|
+
if (entry.memory_type === 'episodic') {
|
|
105
|
+
const age = daysSince(entry.created_at);
|
|
106
|
+
recency = Math.exp(-age / 30);
|
|
107
|
+
}
|
|
108
|
+
const freqBoost = Math.max(0, Math.log(entry.access_count || 1)) * 0.05;
|
|
109
|
+
|
|
110
|
+
return (relevance * priority) + recency + freqBoost;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── Store ───────────────────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
function memoryStore(agentDest, type, content, tags, sessionId) {
|
|
116
|
+
const VALID_TYPES = ['episodic', 'semantic', 'procedural', 'working'];
|
|
117
|
+
if (!VALID_TYPES.includes(type)) {
|
|
118
|
+
throw new Error(`Invalid memory type: "${type}". Must be one of: ${VALID_TYPES.join(', ')}`);
|
|
119
|
+
}
|
|
120
|
+
if (!content || content.trim().length === 0) {
|
|
121
|
+
throw new Error('Memory content cannot be empty');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const index = loadIndex(agentDest);
|
|
125
|
+
|
|
126
|
+
// Enforce cap — auto-GC if needed
|
|
127
|
+
if (index.entries.length >= MAX_ENTRIES) {
|
|
128
|
+
index.entries = index.entries.filter(e => e.memory_type !== 'working');
|
|
129
|
+
if (index.entries.length >= MAX_ENTRIES) {
|
|
130
|
+
index.entries = index.entries.filter(e => {
|
|
131
|
+
if (e.memory_type === 'episodic') {
|
|
132
|
+
return daysSince(e.created_at) < EPISODIC_TTL_DAYS;
|
|
133
|
+
}
|
|
134
|
+
return true;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (index.entries.length >= MAX_ENTRIES) {
|
|
138
|
+
throw new Error(`Memory at capacity (${MAX_ENTRIES}). Run: tk memory gc`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const now = nowEpochStr();
|
|
143
|
+
const id = index.next_id || (index.entries.length > 0 ? Math.max(...index.entries.map(e => e.id)) + 1 : 1);
|
|
144
|
+
const entry = {
|
|
145
|
+
id,
|
|
146
|
+
memory_type: type,
|
|
147
|
+
content: content.trim(),
|
|
148
|
+
tags: tags.filter(t => t.length > 0),
|
|
149
|
+
created_at: now,
|
|
150
|
+
last_accessed: now,
|
|
151
|
+
access_count: 0,
|
|
152
|
+
token_estimate: estimateTokens(content),
|
|
153
|
+
source: type === 'working' ? 'session' : 'manual',
|
|
154
|
+
session_id: sessionId || null,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
index.entries.push(entry);
|
|
158
|
+
index.next_id = id + 1;
|
|
159
|
+
saveIndex(agentDest, index);
|
|
160
|
+
generateProjection(agentDest, index);
|
|
161
|
+
|
|
162
|
+
return { id, token_estimate: entry.token_estimate };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ── Recall ──────────────────────────────────────────────────────────────────
|
|
166
|
+
|
|
167
|
+
function memoryRecall(agentDest, query, budget = 2000) {
|
|
168
|
+
const index = loadIndex(agentDest);
|
|
169
|
+
|
|
170
|
+
const scored = index.entries
|
|
171
|
+
.map(entry => ({ entry, score: computeScore(entry, query) }))
|
|
172
|
+
.filter(s => s.score > 0)
|
|
173
|
+
.sort((a, b) => b.score - a.score);
|
|
174
|
+
|
|
175
|
+
let totalTokens = 0;
|
|
176
|
+
const results = [];
|
|
177
|
+
|
|
178
|
+
for (const { entry, score } of scored) {
|
|
179
|
+
if (totalTokens + entry.token_estimate > budget) break;
|
|
180
|
+
totalTokens += entry.token_estimate;
|
|
181
|
+
entry.last_accessed = nowEpochStr();
|
|
182
|
+
entry.access_count = (entry.access_count || 0) + 1;
|
|
183
|
+
results.push({ ...entry, score });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Save updated access counts
|
|
187
|
+
saveIndex(agentDest, index);
|
|
188
|
+
|
|
189
|
+
return { results, tokens_used: totalTokens, budget };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ── Garbage Collect ─────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
function memoryGc(agentDest) {
|
|
195
|
+
const index = loadIndex(agentDest);
|
|
196
|
+
const before = index.entries.length;
|
|
197
|
+
|
|
198
|
+
let workingRemoved = 0;
|
|
199
|
+
let episodicRemoved = 0;
|
|
200
|
+
|
|
201
|
+
index.entries = index.entries.filter(e => {
|
|
202
|
+
if (e.memory_type === 'working') { workingRemoved++; return false; }
|
|
203
|
+
if (e.memory_type === 'episodic' && daysSince(e.created_at) >= EPISODIC_TTL_DAYS) {
|
|
204
|
+
episodicRemoved++; return false;
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
saveIndex(agentDest, index);
|
|
210
|
+
generateProjection(agentDest, index);
|
|
211
|
+
|
|
212
|
+
return { working_removed: workingRemoved, episodic_removed: episodicRemoved, before, after: index.entries.length };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ── Stats ───────────────────────────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
function memoryStats(agentDest) {
|
|
218
|
+
const index = loadIndex(agentDest);
|
|
219
|
+
const total = index.entries.length;
|
|
220
|
+
const semantic = index.entries.filter(e => e.memory_type === 'semantic').length;
|
|
221
|
+
const procedural = index.entries.filter(e => e.memory_type === 'procedural').length;
|
|
222
|
+
const episodic = index.entries.filter(e => e.memory_type === 'episodic').length;
|
|
223
|
+
const working = index.entries.filter(e => e.memory_type === 'working').length;
|
|
224
|
+
const totalTokens = index.entries.reduce((sum, e) => sum + (e.token_estimate || 0), 0);
|
|
225
|
+
return { total, semantic, procedural, episodic, working, total_tokens: totalTokens, capacity: MAX_ENTRIES };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Projection Generator ───────────────────────────────────────────────────
|
|
229
|
+
|
|
230
|
+
function generateProjection(agentDest, index) {
|
|
231
|
+
if (!index) index = loadIndex(agentDest);
|
|
232
|
+
|
|
233
|
+
let md = '# 🧠 Tribunal Memory Index\n';
|
|
234
|
+
md += '> Auto-generated by `tribunal-kit memory export`. Do not edit manually.\n';
|
|
235
|
+
|
|
236
|
+
const sem = index.entries.filter(e => e.memory_type === 'semantic');
|
|
237
|
+
const proc = index.entries.filter(e => e.memory_type === 'procedural');
|
|
238
|
+
const ep = index.entries.filter(e => e.memory_type === 'episodic');
|
|
239
|
+
const work = index.entries.filter(e => e.memory_type === 'working');
|
|
240
|
+
|
|
241
|
+
md += `> Entries: ${index.entries.length} | Semantic: ${sem.length} | Procedural: ${proc.length} | Episodic: ${ep.length} | Working: ${work.length}\n\n`;
|
|
242
|
+
|
|
243
|
+
if (sem.length > 0) {
|
|
244
|
+
md += '## SEMANTIC (Permanent Facts)\n';
|
|
245
|
+
md += '| ID | Content | Tags | Source | Created |\n';
|
|
246
|
+
md += '|----|---------|------|--------|---------|\n';
|
|
247
|
+
for (const e of sem) {
|
|
248
|
+
md += `| ${e.id} | ${e.content.replace(/\|/g, '\\|')} | ${e.tags.join(', ')} | ${e.source} | ${e.created_at} |\n`;
|
|
249
|
+
}
|
|
250
|
+
md += '\n';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (proc.length > 0) {
|
|
254
|
+
md += '## PROCEDURAL (How-To Recipes)\n';
|
|
255
|
+
md += '| ID | Content | Tags | Source | Created |\n';
|
|
256
|
+
md += '|----|---------|------|--------|---------|\n';
|
|
257
|
+
for (const e of proc) {
|
|
258
|
+
md += `| ${e.id} | ${e.content.replace(/\|/g, '\\|')} | ${e.tags.join(', ')} | ${e.source} | ${e.created_at} |\n`;
|
|
259
|
+
}
|
|
260
|
+
md += '\n';
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (ep.length > 0) {
|
|
264
|
+
md += '## EPISODIC (Session History — auto-decays after 30 days)\n';
|
|
265
|
+
md += '| ID | Content | Tags | Source | Created | Days Remaining |\n';
|
|
266
|
+
md += '|----|---------|------|--------|---------|----------------|\n';
|
|
267
|
+
for (const e of ep) {
|
|
268
|
+
const remaining = Math.max(0, EPISODIC_TTL_DAYS - daysSince(e.created_at));
|
|
269
|
+
md += `| ${e.id} | ${e.content.replace(/\|/g, '\\|')} | ${e.tags.join(', ')} | ${e.source} | ${e.created_at} | ${remaining} |\n`;
|
|
270
|
+
}
|
|
271
|
+
md += '\n';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (work.length > 0) {
|
|
275
|
+
md += '## WORKING (Current Session — cleared on GC)\n';
|
|
276
|
+
md += '| ID | Content | Tags | Session |\n';
|
|
277
|
+
md += '|----|---------|------|---------|\n';
|
|
278
|
+
for (const e of work) {
|
|
279
|
+
md += `| ${e.id} | ${e.content.replace(/\|/g, '\\|')} | ${e.tags.join(', ')} | ${e.session_id || '—'} |\n`;
|
|
280
|
+
}
|
|
281
|
+
md += '\n';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (index.entries.length === 0) {
|
|
285
|
+
md += '*No memories recorded yet. Run `tk memory store` to add your first memory.*\n';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const projPath = getProjectionPath(agentDest);
|
|
289
|
+
fs_1.default.mkdirSync(path_1.default.dirname(projPath), { recursive: true });
|
|
290
|
+
fs_1.default.writeFileSync(projPath, md, 'utf8');
|
|
291
|
+
|
|
292
|
+
return projPath;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ── CLI Router ──────────────────────────────────────────────────────────────
|
|
296
|
+
|
|
297
|
+
async function cmdMemory(flags, processArgs, quiet = false) {
|
|
298
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
299
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
300
|
+
|
|
301
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
302
|
+
(0, logger_1.err)('.agent/ not found. Run: npx tribunal-kit init');
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const args = processArgs.slice(3);
|
|
307
|
+
const subcommand = args[0];
|
|
308
|
+
|
|
309
|
+
if (!subcommand || subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
|
|
310
|
+
(0, helpers_1.banner)(quiet);
|
|
311
|
+
const W = 62;
|
|
312
|
+
const title = ' Tribunal Memory — 4-Type Taxonomy Engine';
|
|
313
|
+
const trail = ' '.repeat(Math.max(0, W - title.length));
|
|
314
|
+
console.log(` ${(0, logger_1.c)('cyan', '\u2554' + '\u2550'.repeat(W) + '\u2557')}`);
|
|
315
|
+
console.log(` ${(0, logger_1.c)('cyan', '\u2551')}${(0, logger_1.bold)((0, logger_1.c)('white', title))}${trail}${(0, logger_1.c)('cyan', '\u2551')}`);
|
|
316
|
+
console.log(` ${(0, logger_1.c)('cyan', '\u255a' + '\u2550'.repeat(W) + '\u255d')}`);
|
|
317
|
+
console.log();
|
|
318
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'store'.padEnd(10))} ${(0, logger_1.c)('gray', 'Store a new memory entry')}`);
|
|
319
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'recall'.padEnd(10))} ${(0, logger_1.c)('gray', 'Budget-constrained memory recall')}`);
|
|
320
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'gc'.padEnd(10))} ${(0, logger_1.c)('gray', 'Garbage collect expired/working memories')}`);
|
|
321
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'stats'.padEnd(10))} ${(0, logger_1.c)('gray', 'Show memory index statistics')}`);
|
|
322
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'export'.padEnd(10))} ${(0, logger_1.c)('gray', 'Export MEMORY.md projection')}`);
|
|
323
|
+
console.log();
|
|
324
|
+
(0, logger_1.log)((0, logger_1.bold)(' Memory Types'));
|
|
325
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
326
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', 'semantic'.padEnd(14))} ${(0, logger_1.c)('gray', 'Permanent project facts & rules')}`);
|
|
327
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', 'procedural'.padEnd(14))} ${(0, logger_1.c)('gray', 'How-to recipes & build steps')}`);
|
|
328
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', 'episodic'.padEnd(14))} ${(0, logger_1.c)('gray', 'Session events (30-day TTL)')}`);
|
|
329
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', 'working'.padEnd(14))} ${(0, logger_1.c)('gray', 'Scratch memory (cleared on GC)')}`);
|
|
330
|
+
console.log();
|
|
331
|
+
(0, logger_1.log)((0, logger_1.bold)(' Examples'));
|
|
332
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
333
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', 'tk memory store --type semantic --content "Uses PostgreSQL" --tags db,orm')}`);
|
|
334
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', 'tk memory recall --query "database" --budget 2000')}`);
|
|
335
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', 'tk memory gc')}`);
|
|
336
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', 'tk memory stats')}`);
|
|
337
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', 'tk memory export')}`);
|
|
338
|
+
console.log();
|
|
339
|
+
process.exit(0);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Parse flags from remaining args
|
|
343
|
+
function getFlag(name) {
|
|
344
|
+
const idx = args.indexOf(`--${name}`);
|
|
345
|
+
if (idx === -1) return null;
|
|
346
|
+
return args[idx + 1] || null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
switch (subcommand) {
|
|
351
|
+
case 'store': {
|
|
352
|
+
const type = getFlag('type');
|
|
353
|
+
const content = getFlag('content');
|
|
354
|
+
const tagsRaw = getFlag('tags') || '';
|
|
355
|
+
const sessionId = getFlag('session-id');
|
|
356
|
+
if (!type || !content) {
|
|
357
|
+
(0, logger_1.err)('Usage: tk memory store --type <type> --content "<text>" [--tags tag1,tag2]');
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
const tags = tagsRaw.split(',').map(t => t.trim()).filter(t => t.length > 0);
|
|
361
|
+
const result = memoryStore(agentDest, type, content, tags, sessionId);
|
|
362
|
+
if (!quiet) {
|
|
363
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)('Memory stored')} #${result.id} (${type})`);
|
|
364
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} ${(0, logger_1.c)('gray', content)}`);
|
|
365
|
+
if (tags.length > 0) {
|
|
366
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Tags: ${(0, logger_1.c)('gray', tags.join(', '))}`);
|
|
367
|
+
}
|
|
368
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} ~${result.token_estimate} tokens`);
|
|
369
|
+
}
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
case 'recall': {
|
|
374
|
+
const query = getFlag('query');
|
|
375
|
+
const budgetStr = getFlag('budget');
|
|
376
|
+
const budget = budgetStr ? parseInt(budgetStr, 10) : 2000;
|
|
377
|
+
if (!query) {
|
|
378
|
+
(0, logger_1.err)('Usage: tk memory recall --query "<search>" [--budget 2000]');
|
|
379
|
+
process.exit(1);
|
|
380
|
+
}
|
|
381
|
+
const { results, tokens_used } = memoryRecall(agentDest, query, budget);
|
|
382
|
+
if (!quiet) {
|
|
383
|
+
if (results.length === 0) {
|
|
384
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', '⚠')} No memories match query: "${query}"`);
|
|
385
|
+
} else {
|
|
386
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${results.length} memories recalled (budget: ${budget} tokens)`);
|
|
387
|
+
for (const entry of results) {
|
|
388
|
+
const typeLabel = entry.memory_type.toUpperCase();
|
|
389
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} [${(0, logger_1.c)('cyan', typeLabel)}] #${entry.id}: ${entry.content} ${(0, logger_1.c)('gray', `(score: ${entry.score.toFixed(2)}, ~${entry.token_estimate}tok)`)}`);
|
|
390
|
+
}
|
|
391
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Total: ~${tokens_used} tokens used of ${budget} budget`);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Machine output for agent consumption
|
|
395
|
+
console.log(JSON.stringify({
|
|
396
|
+
action: 'recall', query, budget, tokens_used,
|
|
397
|
+
count: results.length,
|
|
398
|
+
entries: results.map(e => ({
|
|
399
|
+
id: e.id, memory_type: e.memory_type, content: e.content,
|
|
400
|
+
tags: e.tags, score: e.score, token_estimate: e.token_estimate,
|
|
401
|
+
})),
|
|
402
|
+
}));
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
case 'gc': {
|
|
407
|
+
const result = memoryGc(agentDest);
|
|
408
|
+
if (!quiet) {
|
|
409
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)('Garbage collection complete')}`);
|
|
410
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Working removed: ${result.working_removed}`);
|
|
411
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Episodic expired: ${result.episodic_removed}`);
|
|
412
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Entries: ${result.before} → ${result.after}`);
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
case 'stats': {
|
|
418
|
+
const stats = memoryStats(agentDest);
|
|
419
|
+
if (!quiet) {
|
|
420
|
+
(0, logger_1.log)(`\n 🧠 ${(0, logger_1.bold)('Tribunal Memory Index')}`);
|
|
421
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Total entries: ${stats.total}`);
|
|
422
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Semantic: ${stats.semantic} (permanent)`);
|
|
423
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Procedural: ${stats.procedural} (permanent)`);
|
|
424
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Episodic: ${stats.episodic} (30-day TTL)`);
|
|
425
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Working: ${stats.working} (session-scoped)`);
|
|
426
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Token budget: ~${stats.total_tokens} tokens indexed`);
|
|
427
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▶')} Capacity: ${stats.total}/${stats.capacity}\n`);
|
|
428
|
+
}
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
case 'export': {
|
|
433
|
+
const projPath = generateProjection(agentDest);
|
|
434
|
+
if (!quiet) {
|
|
435
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)('MEMORY.md exported')} → ${projPath}`);
|
|
436
|
+
}
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
default:
|
|
441
|
+
(0, logger_1.err)(`Unknown memory subcommand: "${subcommand}"`);
|
|
442
|
+
(0, logger_1.log)(' Run: tk memory --help');
|
|
443
|
+
process.exit(1);
|
|
444
|
+
}
|
|
445
|
+
} catch (e) {
|
|
446
|
+
(0, logger_1.err)(e.message || String(e));
|
|
447
|
+
process.exit(1);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Export internal functions for MCP server and learn/case integration
|
|
452
|
+
exports._memoryStore = memoryStore;
|
|
453
|
+
exports._memoryRecall = memoryRecall;
|
|
454
|
+
exports._memoryGc = memoryGc;
|
|
455
|
+
exports._memoryStats = memoryStats;
|
|
456
|
+
exports._generateProjection = generateProjection;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tribunal-kit",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"description": "Anti-Hallucination AI Agent Kit — 43 specialist agents,
|
|
3
|
+
"version": "5.8.1",
|
|
4
|
+
"description": "Anti-Hallucination AI Agent Kit for IDEs (Cursor, VSCode, Windsurf) — 43 specialist agents, 34 workflows, 20 parallel Tribunal code reviewers, Model Context Protocol (MCP) server, and long-running autonomous agent harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
7
7
|
"ai-agent",
|
|
@@ -33,7 +33,17 @@
|
|
|
33
33
|
"ai-coding",
|
|
34
34
|
"autonomous-agents",
|
|
35
35
|
"coding-assistant",
|
|
36
|
-
"automation"
|
|
36
|
+
"automation",
|
|
37
|
+
"model-context-protocol-server",
|
|
38
|
+
"mcp-server",
|
|
39
|
+
"claude-code",
|
|
40
|
+
"aider",
|
|
41
|
+
"cursor-rules-generator",
|
|
42
|
+
"agentic-ai",
|
|
43
|
+
"ai-code-reviewer",
|
|
44
|
+
"hallucination-mitigation",
|
|
45
|
+
"autonomous-workflows",
|
|
46
|
+
"code-correctness"
|
|
37
47
|
],
|
|
38
48
|
"homepage": "https://github.com/Harmitx7/tribunal-kit",
|
|
39
49
|
"repository": {
|
|
@@ -67,20 +77,22 @@
|
|
|
67
77
|
"changelog:preview": "node scripts/changelog.js --preview",
|
|
68
78
|
"sync": "node scripts/sync-version.js",
|
|
69
79
|
"validate-payload": "node scripts/validate-payload.js",
|
|
80
|
+
"benchmark": "node scripts/benchmark.js",
|
|
81
|
+
"benchmark:rust": "cargo build --release && node scripts/benchmark.js",
|
|
70
82
|
"build": "echo 'No build step required for this project'"
|
|
71
83
|
},
|
|
72
84
|
"devDependencies": {
|
|
73
85
|
"eslint": "^9.1.1",
|
|
74
|
-
"jest": "^
|
|
86
|
+
"jest": "^30.4.2",
|
|
75
87
|
"typescript": "^5.4.5"
|
|
76
88
|
},
|
|
77
89
|
"optionalDependencies": {
|
|
78
|
-
"@tribunal-kit/core-darwin-arm64": "^
|
|
79
|
-
"@tribunal-kit/core-darwin-x64": "^
|
|
80
|
-
"@tribunal-kit/core-linux-arm64": "^
|
|
81
|
-
"@tribunal-kit/core-linux-x64": "^
|
|
82
|
-
"@tribunal-kit/core-win32-arm64": "^
|
|
83
|
-
"@tribunal-kit/core-win32-x64": "^
|
|
90
|
+
"@tribunal-kit/core-darwin-arm64": "^5.8.1",
|
|
91
|
+
"@tribunal-kit/core-darwin-x64": "^5.8.1",
|
|
92
|
+
"@tribunal-kit/core-linux-arm64": "^5.8.1",
|
|
93
|
+
"@tribunal-kit/core-linux-x64": "^5.8.1",
|
|
94
|
+
"@tribunal-kit/core-win32-arm64": "^5.8.1",
|
|
95
|
+
"@tribunal-kit/core-win32-x64": "^5.8.1"
|
|
84
96
|
},
|
|
85
97
|
"jest": {
|
|
86
98
|
"testMatch": [
|