tribunal-kit 4.6.1 → 5.7.0
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/README.md +15 -1
- package/bin/mcp-server.js +89 -19
- package/bin/wrapper.js +5 -4
- package/dist/cli.js +234 -0
- package/dist/commands/case.js +48 -0
- package/dist/commands/context.js +66 -0
- package/dist/commands/graph.js +38 -0
- package/dist/commands/hook.js +28 -0
- package/dist/commands/init.js +297 -0
- package/dist/commands/learn.js +60 -0
- package/dist/commands/marathon.js +45 -0
- package/dist/commands/mutate.js +30 -0
- package/dist/commands/status.js +35 -0
- package/dist/commands/sync.js +25 -0
- package/dist/commands/uninstall.js +42 -0
- package/dist/commands/update.js +37 -0
- package/dist/mcp/server.js +142 -0
- package/dist/types.js +8 -0
- package/dist/utils/fs.js +96 -0
- package/dist/utils/hasher.js +142 -0
- package/dist/utils/helpers.js +68 -0
- package/dist/utils/logger.js +54 -0
- package/dist/utils/version.js +150 -0
- package/package.json +2 -1
- package/scripts/benchmark.js +160 -0
|
@@ -0,0 +1,297 @@
|
|
|
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.cmdInit = cmdInit;
|
|
7
|
+
exports.generateIDEBridges = generateIDEBridges;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const logger_1 = require("../utils/logger");
|
|
11
|
+
const fs_2 = require("../utils/fs");
|
|
12
|
+
const helpers_1 = require("../utils/helpers");
|
|
13
|
+
const hasher_1 = require("../utils/hasher");
|
|
14
|
+
// Core agents to install in --minimal mode
|
|
15
|
+
const CORE_AGENTS = new Set([
|
|
16
|
+
'backend-specialist.md',
|
|
17
|
+
'frontend-specialist.md',
|
|
18
|
+
'database-architect.md',
|
|
19
|
+
'debugger.md',
|
|
20
|
+
'security-auditor.md',
|
|
21
|
+
'logic-reviewer.md',
|
|
22
|
+
'dependency-reviewer.md',
|
|
23
|
+
'type-safety-reviewer.md',
|
|
24
|
+
'performance-reviewer.md',
|
|
25
|
+
'orchestrator.md',
|
|
26
|
+
'explorer-agent.md',
|
|
27
|
+
'project-planner.md',
|
|
28
|
+
'test-engineer.md',
|
|
29
|
+
]);
|
|
30
|
+
// Core skills to install in --minimal mode
|
|
31
|
+
const CORE_SKILLS = new Set([
|
|
32
|
+
'clean-code', 'architecture', 'testing-patterns', 'systematic-debugging',
|
|
33
|
+
'frontend-design', 'database-design', 'api-patterns', 'nodejs-best-practices',
|
|
34
|
+
'vulnerability-scanner', 'typescript-advanced', 'python-pro', 'nextjs-react-expert',
|
|
35
|
+
'react-specialist', 'performance-profiling', 'lint-and-validate',
|
|
36
|
+
]);
|
|
37
|
+
async function cmdInit(flags, quiet = false) {
|
|
38
|
+
const agentSrc = (0, helpers_1.getKitAgent)();
|
|
39
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
40
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
41
|
+
const dryRun = flags.dryRun || false;
|
|
42
|
+
const pkgStr = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../package.json'), 'utf8');
|
|
43
|
+
const pkg = JSON.parse(pkgStr);
|
|
44
|
+
// ── Self-install guard ──────────────────────────────────
|
|
45
|
+
if ((0, fs_2.isSelfInstall)(targetDir, pkg.name, path_1.default.resolve(__dirname, '../..'))) {
|
|
46
|
+
(0, logger_1.err)('Cannot run init/update inside the tribunal-kit package itself.');
|
|
47
|
+
(0, logger_1.err)(`Target: ${targetDir}`);
|
|
48
|
+
(0, logger_1.err)(`Package: ${path_1.default.resolve(__dirname, '../..')}`);
|
|
49
|
+
console.log();
|
|
50
|
+
(0, logger_1.dim)('This command is designed to install .agent/ into OTHER projects.');
|
|
51
|
+
(0, logger_1.dim)('Run it from the root of the project you want to set up:');
|
|
52
|
+
(0, logger_1.dim)(' cd /path/to/your-project');
|
|
53
|
+
(0, logger_1.dim)(' npx tribunal-kit init');
|
|
54
|
+
console.log();
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
// ────────────────────────────────────────────────────────
|
|
58
|
+
let diff = null;
|
|
59
|
+
let incremental = false;
|
|
60
|
+
|
|
61
|
+
if (!dryRun && fs_1.default.existsSync(agentDest) && flags.force) {
|
|
62
|
+
const oldManifest = (0, hasher_1.readManifest)(agentDest);
|
|
63
|
+
if (oldManifest) {
|
|
64
|
+
const newManifest = await (0, hasher_1.generateManifest)(agentSrc);
|
|
65
|
+
diff = (0, hasher_1.diffManifests)(oldManifest, newManifest);
|
|
66
|
+
incremental = true;
|
|
67
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '✦')} Performing incremental update (${diff.added.length} added, ${diff.changed.length} changed, ${diff.removed.length} removed)`);
|
|
68
|
+
|
|
69
|
+
// Backup ONLY changed or removed files
|
|
70
|
+
const toBackup = [...diff.changed, ...diff.removed];
|
|
71
|
+
if (toBackup.length > 0) {
|
|
72
|
+
const backupDir = path_1.default.join(agentDest, '.backups', `backup-${Date.now()}`);
|
|
73
|
+
fs_1.default.mkdirSync(backupDir, { recursive: true });
|
|
74
|
+
let backedUpCount = 0;
|
|
75
|
+
for (const file of toBackup) {
|
|
76
|
+
const srcPath = path_1.default.join(agentDest, file);
|
|
77
|
+
const destPath = path_1.default.join(backupDir, file);
|
|
78
|
+
if (fs_1.default.existsSync(srcPath)) {
|
|
79
|
+
fs_1.default.mkdirSync(path_1.default.dirname(destPath), { recursive: true });
|
|
80
|
+
fs_1.default.copyFileSync(srcPath, destPath);
|
|
81
|
+
backedUpCount++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', `✦ Backed up ${backedUpCount} modified/removed files to .backups/`)}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Remove removed files
|
|
88
|
+
for (const file of diff.removed) {
|
|
89
|
+
const target = path_1.default.join(agentDest, file);
|
|
90
|
+
if (fs_1.default.existsSync(target)) {
|
|
91
|
+
fs_1.default.rmSync(target);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
// Legacy full backup
|
|
96
|
+
const backupDir = path_1.default.join(agentDest, '.backups', `backup-${Date.now()}`);
|
|
97
|
+
fs_1.default.mkdirSync(backupDir, { recursive: true });
|
|
98
|
+
const subdirs = ['agents', 'workflows', 'skills', 'scripts', '.shared', 'rules'];
|
|
99
|
+
for (const sub of subdirs) {
|
|
100
|
+
const subPath = path_1.default.join(agentDest, sub);
|
|
101
|
+
if (fs_1.default.existsSync(subPath)) {
|
|
102
|
+
await (0, fs_2.copyDir)(subPath, path_1.default.join(backupDir, sub), false);
|
|
103
|
+
await fs_1.default.promises.rm(subPath, { recursive: true, force: true });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '✦ Backed up existing configurations to .agent/.backups/')}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ────────────────────────────────────────────────────────
|
|
110
|
+
(0, helpers_1.banner)(quiet);
|
|
111
|
+
if (dryRun) {
|
|
112
|
+
(0, logger_1.log)((0, logger_1.colorize)('yellow', ' DRY RUN — no files will be written'));
|
|
113
|
+
console.log();
|
|
114
|
+
}
|
|
115
|
+
// Check target exists
|
|
116
|
+
if (!fs_1.default.existsSync(targetDir)) {
|
|
117
|
+
(0, logger_1.err)(`Target directory not found: ${targetDir}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
// Check if .agent already exists
|
|
121
|
+
if (fs_1.default.existsSync(agentDest) && !flags.force) {
|
|
122
|
+
(0, logger_1.warn)('.agent/ already exists in this project.');
|
|
123
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} To refresh or update it, run: ${(0, logger_1.colorize)('white', 'tribunal-kit init --force')}`);
|
|
124
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} Or check status with: ${(0, logger_1.colorize)('cyan', 'tribunal-kit status')}`);
|
|
125
|
+
console.log();
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
// Ensure history dirs exist (Case Law + Skill Evolution)
|
|
129
|
+
if (!dryRun) {
|
|
130
|
+
const caseDir = path_1.default.join(agentDest, 'history', 'case-law', 'cases');
|
|
131
|
+
const evoDir = path_1.default.join(agentDest, 'history', 'skill-evolution');
|
|
132
|
+
fs_1.default.mkdirSync(caseDir, { recursive: true });
|
|
133
|
+
fs_1.default.mkdirSync(evoDir, { recursive: true });
|
|
134
|
+
const gkCase = path_1.default.join(caseDir, '.gitkeep');
|
|
135
|
+
const gkEvo = path_1.default.join(evoDir, '.gitkeep');
|
|
136
|
+
if (!fs_1.default.existsSync(gkCase))
|
|
137
|
+
fs_1.default.writeFileSync(gkCase, '');
|
|
138
|
+
if (!fs_1.default.existsSync(gkEvo))
|
|
139
|
+
fs_1.default.writeFileSync(gkEvo, '');
|
|
140
|
+
}
|
|
141
|
+
// Count what we're installing
|
|
142
|
+
const isMinimal = flags.minimal || false;
|
|
143
|
+
if (isMinimal) {
|
|
144
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', '⚡')} ${(0, logger_1.bold)('Minimal mode')} — installing core agents and skills only`);
|
|
145
|
+
console.log();
|
|
146
|
+
}
|
|
147
|
+
const totalFiles = await (0, fs_2.countDir)(agentSrc);
|
|
148
|
+
(0, logger_1.dbg)(`Source: ${agentSrc}`);
|
|
149
|
+
(0, logger_1.dbg)(`Target: ${agentDest}`);
|
|
150
|
+
(0, logger_1.dbg)(`Total source files: ${totalFiles}`);
|
|
151
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} Scanning ${(0, logger_1.c)('white', String(totalFiles))} files ${(0, logger_1.c)('gray', '→')} ${(0, logger_1.c)('gray', agentDest)}`);
|
|
152
|
+
try {
|
|
153
|
+
// Build filter for --minimal mode
|
|
154
|
+
let filterFunc = isMinimal ? (name, parentDir, isDir) => {
|
|
155
|
+
if (isDir) return true; // always traverse directories
|
|
156
|
+
const parentName = path_1.default.basename(parentDir);
|
|
157
|
+
if (parentName === 'agents')
|
|
158
|
+
return CORE_AGENTS.has(name);
|
|
159
|
+
if (parentName === 'skills')
|
|
160
|
+
return CORE_SKILLS.has(name);
|
|
161
|
+
return true; // everything else passes
|
|
162
|
+
} : null;
|
|
163
|
+
|
|
164
|
+
if (incremental && diff) {
|
|
165
|
+
const addedSet = new Set(diff.added);
|
|
166
|
+
const changedSet = new Set(diff.changed);
|
|
167
|
+
const baseFilter = filterFunc;
|
|
168
|
+
filterFunc = (name, parentDir, isDir) => {
|
|
169
|
+
if (isDir) return true;
|
|
170
|
+
if (baseFilter && !baseFilter(name, parentDir, isDir)) return false;
|
|
171
|
+
|
|
172
|
+
const relativePath = path_1.default.relative(agentSrc, path_1.default.join(parentDir, name)).replace(/\\/g, '/');
|
|
173
|
+
return addedSet.has(relativePath) || changedSet.has(relativePath);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const copied = await (0, fs_2.copyDir)(agentSrc, agentDest, dryRun, filterFunc);
|
|
178
|
+
// Generate and save hash manifest for incremental future updates
|
|
179
|
+
if (!dryRun) {
|
|
180
|
+
try {
|
|
181
|
+
const manifest = await (0, hasher_1.generateManifest)(agentSrc);
|
|
182
|
+
(0, hasher_1.writeManifest)(agentDest, manifest);
|
|
183
|
+
(0, logger_1.dbg)(` Manifest saved: ${Object.keys(manifest).length} files hashed`);
|
|
184
|
+
} catch (e) {
|
|
185
|
+
(0, logger_1.dbg)(` Manifest generation skipped: ${e.message}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
console.log();
|
|
189
|
+
if (dryRun) {
|
|
190
|
+
(0, logger_1.ok)(`${(0, logger_1.bold)('DRY RUN')} complete — would install ${(0, logger_1.c)('cyan', String(copied))} files`);
|
|
191
|
+
(0, logger_1.dim)(`Target: ${agentDest}`);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// ── Success card — W=62, rows padded by plain-text length ──
|
|
195
|
+
const W = 62;
|
|
196
|
+
const agentsCount = fs_1.default.readdirSync(path_1.default.join(agentDest, 'agents')).length;
|
|
197
|
+
const workflowsCount = fs_1.default.readdirSync(path_1.default.join(agentDest, 'workflows')).length;
|
|
198
|
+
const skillsCount = fs_1.default.readdirSync(path_1.default.join(agentDest, 'skills')).length;
|
|
199
|
+
const scriptsCount = fs_1.default.readdirSync(path_1.default.join(agentDest, 'scripts')).length;
|
|
200
|
+
// Stat rows: compute trailing spaces from plain text so right ║ aligns
|
|
201
|
+
const statRow = (icon, label, val, col) => {
|
|
202
|
+
const plain = ` ${icon} ${label.padEnd(10)}${String(val).padStart(3)} installed`;
|
|
203
|
+
const trail = ' '.repeat(Math.max(0, W - plain.length));
|
|
204
|
+
return ` ${(0, logger_1.c)('cyan', '║')} ${icon} ${(0, logger_1.c)('white', label.padEnd(10))}${(0, logger_1.c)(col, String(val).padStart(3))} ${(0, logger_1.c)('gray', 'installed')}${trail}${(0, logger_1.c)('cyan', '║')}`;
|
|
205
|
+
};
|
|
206
|
+
// Plain-text rows (header / blank)
|
|
207
|
+
const plainRow = (text, wrapFn) => {
|
|
208
|
+
const trail = ' '.repeat(Math.max(0, W - text.length));
|
|
209
|
+
return ` ${(0, logger_1.c)('cyan', '║')}${wrapFn(text)}${trail}${(0, logger_1.c)('cyan', '║')}`;
|
|
210
|
+
};
|
|
211
|
+
// Next-step rows: fixed cmd column + description
|
|
212
|
+
const stepRow = (cmd, desc) => {
|
|
213
|
+
const plain = ` ${cmd.padEnd(16)}${desc}`;
|
|
214
|
+
const trail = ' '.repeat(Math.max(0, W - plain.length));
|
|
215
|
+
return ` ${(0, logger_1.c)('cyan', '║')} ${(0, logger_1.c)('white', cmd.padEnd(16))}${(0, logger_1.c)('gray', desc)}${trail}${(0, logger_1.c)('cyan', '║')}`;
|
|
216
|
+
};
|
|
217
|
+
console.log(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)((0, logger_1.c)('green', 'Installation complete'))} ${(0, logger_1.c)('gray', '—')} ${(0, logger_1.c)('white', String(copied))} files`);
|
|
218
|
+
console.log(` ${(0, logger_1.c)('gray', ' ╰─')} ${(0, logger_1.c)('gray', agentDest)}`);
|
|
219
|
+
console.log();
|
|
220
|
+
console.log(` ${(0, logger_1.c)('cyan', '╔' + '═'.repeat(W) + '╗')}`);
|
|
221
|
+
console.log(plainRow(` What's inside:`, s => (0, logger_1.bold)((0, logger_1.c)('white', s))));
|
|
222
|
+
console.log(` ${(0, logger_1.c)('cyan', '╠' + '═'.repeat(W) + '╣')}`);
|
|
223
|
+
console.log(statRow('🤖', 'Agents', agentsCount, 'magenta'));
|
|
224
|
+
console.log(statRow('⚡', 'Workflows', workflowsCount, 'yellow'));
|
|
225
|
+
console.log(statRow('🧠', 'Skills', skillsCount, 'blue'));
|
|
226
|
+
console.log(statRow('🔧', 'Scripts', scriptsCount, 'green'));
|
|
227
|
+
console.log(` ${(0, logger_1.c)('cyan', '╠' + '═'.repeat(W) + '╣')}`);
|
|
228
|
+
console.log(plainRow('', () => ''));
|
|
229
|
+
console.log(plainRow(` Next steps:`, s => (0, logger_1.c)('gray', s)));
|
|
230
|
+
console.log(stepRow('/generate', 'Generate code with anti-hallucination'));
|
|
231
|
+
console.log(stepRow('/review', 'Audit existing code for issues'));
|
|
232
|
+
console.log(stepRow('/tribunal-full', 'Run all 16 reviewers in parallel'));
|
|
233
|
+
console.log(plainRow('', () => ''));
|
|
234
|
+
console.log(` ${(0, logger_1.c)('cyan', '╚' + '═'.repeat(W) + '╝')}`);
|
|
235
|
+
console.log();
|
|
236
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '✦ Generating IDE bridge files...')}`);
|
|
237
|
+
await generateIDEBridges(targetDir, agentDest, dryRun);
|
|
238
|
+
}
|
|
239
|
+
console.log();
|
|
240
|
+
}
|
|
241
|
+
catch (e) {
|
|
242
|
+
if (e instanceof Error) {
|
|
243
|
+
(0, logger_1.err)(`Failed to install: ${e.message}`);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
(0, logger_1.err)(`Failed to install: ${String(e)}`);
|
|
247
|
+
}
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async function generateIDEBridges(targetDir, agentDest, dryRun = false) {
|
|
252
|
+
const rulesFile = path_1.default.join(agentDest, 'rules', 'GEMINI.md');
|
|
253
|
+
let rulesContent = '';
|
|
254
|
+
try {
|
|
255
|
+
rulesContent = await fs_1.default.promises.readFile(rulesFile, 'utf8');
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
// rules file doesn't exist
|
|
259
|
+
}
|
|
260
|
+
// Helper: write a bridge file only if it doesn't already exist
|
|
261
|
+
const writeBridge = async (filePath, content, label) => {
|
|
262
|
+
if (dryRun) {
|
|
263
|
+
(0, logger_1.dbg)(` would create: ${filePath}`);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const dir = path_1.default.dirname(filePath);
|
|
267
|
+
try {
|
|
268
|
+
await fs_1.default.promises.mkdir(dir, { recursive: true });
|
|
269
|
+
await fs_1.default.promises.stat(filePath);
|
|
270
|
+
(0, logger_1.dbg)(` skip (exists): ${path_1.default.basename(filePath)}`);
|
|
271
|
+
}
|
|
272
|
+
catch (statErr) {
|
|
273
|
+
if (statErr instanceof Error && statErr.code === 'ENOENT') {
|
|
274
|
+
await fs_1.default.promises.writeFile(filePath, content, 'utf8');
|
|
275
|
+
(0, logger_1.ok)(`${label} → ${(0, logger_1.c)('gray', path_1.default.relative(targetDir, filePath))}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
// ── 1. Cursor (.cursorrules) ──────────────────────────
|
|
280
|
+
const cursorRules = `# Tribunal Kit — Cursor Bridge
|
|
281
|
+
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
282
|
+
# Source: .agent/rules/GEMINI.md
|
|
283
|
+
|
|
284
|
+
${rulesContent}
|
|
285
|
+
`;
|
|
286
|
+
// Fire ALL bridge writes concurrently via Promise.all
|
|
287
|
+
const bridges = [
|
|
288
|
+
{ path: path_1.default.join(targetDir, '.cursorrules'), content: cursorRules, label: 'Cursor' },
|
|
289
|
+
{ path: path_1.default.join(targetDir, '.windsurfrules'), content: windsurfRules, label: 'Windsurf' },
|
|
290
|
+
{ path: path_1.default.join(targetDir, '.gemini', 'settings.json'), content: geminiSettings, label: 'Gemini/Antigravity' },
|
|
291
|
+
{ path: path_1.default.join(targetDir, '.gemini', 'GEMINI.md'), content: geminiRulesBridge, label: 'Gemini rules' },
|
|
292
|
+
{ path: path_1.default.join(targetDir, '.github', 'copilot-instructions.md'), content: copilotInstructions, label: 'GitHub Copilot' },
|
|
293
|
+
{ path: path_1.default.join(targetDir, '.claude', 'CLAUDE.md'), content: claudeRules, label: 'Claude' },
|
|
294
|
+
];
|
|
295
|
+
await Promise.all(bridges.map(b => writeBridge(b.path, b.content, b.label)));
|
|
296
|
+
console.log();
|
|
297
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
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.cmdLearn = cmdLearn;
|
|
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
|
+
async function cmdLearn(flags, quiet = false) {
|
|
12
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
13
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
14
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
15
|
+
(0, logger_1.err)('.agent/ not found. Run: npx tribunal-kit init');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
(0, helpers_1.banner)(quiet);
|
|
19
|
+
const W = 62;
|
|
20
|
+
const title = ' Tribunal Learn — Supreme Court Mode';
|
|
21
|
+
const trail = ' '.repeat(Math.max(0, W - title.length));
|
|
22
|
+
console.log(` ${(0, logger_1.c)('cyan', '\u2554' + '\u2550'.repeat(W) + '\u2557')}`);
|
|
23
|
+
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')}`);
|
|
24
|
+
console.log(` ${(0, logger_1.c)('cyan', '\u255a' + '\u2550'.repeat(W) + '\u255d')}`);
|
|
25
|
+
console.log();
|
|
26
|
+
const dryRun = flags.dryRun ? '--dry-run' : '';
|
|
27
|
+
const useHead = flags.head ? '--head' : '';
|
|
28
|
+
// Phase 1: Skill Evolution
|
|
29
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u229b')} ${(0, logger_1.bold)('Phase 1')} \u2014 Skill Evolution Forge (auto-generating project idioms)`);
|
|
30
|
+
const evoScript = path_1.default.join(agentDest, 'scripts', 'skill_evolution.js');
|
|
31
|
+
if (!fs_1.default.existsSync(evoScript)) {
|
|
32
|
+
(0, logger_1.warn)('skill_evolution.js not found \u2014 run: npx tribunal-kit update');
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
try {
|
|
36
|
+
const cmd = `node "${evoScript}" digest ${dryRun} ${useHead}`.trim();
|
|
37
|
+
await (0, helpers_1.runShellAsync)(cmd, { stdio: 'inherit', cwd: targetDir });
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
if (e instanceof Error) {
|
|
41
|
+
(0, logger_1.warn)(`Skill Evolution error: ${e.message}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
(0, logger_1.warn)(`Skill Evolution error: ${String(e)}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
console.log();
|
|
49
|
+
// Phase 2: Case Law prompt
|
|
50
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u229b')} ${(0, logger_1.bold)('Phase 2')} \u2014 Case Law Engine (building precedence record)`);
|
|
51
|
+
console.log();
|
|
52
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '\u25b8')} Record a new rejection precedent:`);
|
|
53
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('white', 'npx tribunal-kit case add')}`);
|
|
54
|
+
console.log();
|
|
55
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '\u25b8')} Search existing case law:`);
|
|
56
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('white', 'npx tribunal-kit case search "your query"')}`);
|
|
57
|
+
console.log();
|
|
58
|
+
(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
|
+
console.log();
|
|
60
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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.cmdMarathon = cmdMarathon;
|
|
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
|
+
async function cmdMarathon(flags, processArgs, quiet = false) {
|
|
12
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
13
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
14
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
15
|
+
(0, logger_1.err)('.agent/ not found. Run: npx tribunal-kit init');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const args = processArgs.slice(3);
|
|
19
|
+
const argsStr = args.join(' ');
|
|
20
|
+
if (args.length === 0 || args[0] === 'help' || args[0] === '--help' || args[0] === '-h') {
|
|
21
|
+
(0, helpers_1.banner)(quiet);
|
|
22
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '╔' + '═'.repeat(60) + '╗')}`);
|
|
23
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '║')}\x1b[1m\x1b[97m Marathon — Long-Running Agent Harness \x1b[0m${(0, logger_1.c)('cyan', '║')}`);
|
|
24
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '╚' + '═'.repeat(60) + '╝')}`);
|
|
25
|
+
console.log();
|
|
26
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'init'.padEnd(16))} ${(0, logger_1.c)('gray', 'Start a new marathon (init "spec")')}`);
|
|
27
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'status'.padEnd(16))} ${(0, logger_1.c)('gray', 'Show progress dashboard')}`);
|
|
28
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'next'.padEnd(16))} ${(0, logger_1.c)('gray', 'Show next unfinished feature')}`);
|
|
29
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'mark'.padEnd(16))} ${(0, logger_1.c)('gray', 'Mark feature pass/fail (mark <id> pass)')}`);
|
|
30
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'log'.padEnd(16))} ${(0, logger_1.c)('gray', 'Add a progress note')}`);
|
|
31
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'session-start'.padEnd(16))} ${(0, logger_1.c)('gray', 'Begin a new work session')}`);
|
|
32
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'session-end'.padEnd(16))} ${(0, logger_1.c)('gray', 'End session with summary')}`);
|
|
33
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'add-feature'.padEnd(16))} ${(0, logger_1.c)('gray', 'Add feature: "category" "desc" "step1" ...')}`);
|
|
34
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'reset'.padEnd(16))} ${(0, logger_1.c)('gray', 'Archive and start fresh')}`);
|
|
35
|
+
console.log();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const marathonScript = path_1.default.join(agentDest, 'scripts', 'marathon_harness.js');
|
|
39
|
+
try {
|
|
40
|
+
await (0, helpers_1.runShellAsync)(`node "${marathonScript}" ${argsStr}`, { stdio: 'inherit', cwd: targetDir });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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.cmdMutate = cmdMutate;
|
|
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
|
+
async function cmdMutate(flags, processArgs) {
|
|
12
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
13
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
14
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
15
|
+
(0, logger_1.err)('.agent/ not found. Run: npx tribunal-kit init');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const args = processArgs.slice(3);
|
|
19
|
+
if (args.length < 2) {
|
|
20
|
+
(0, logger_1.err)('Usage: npx tribunal-kit mutate <target_file> <test_command>');
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const mutateScript = path_1.default.join(agentDest, 'scripts', 'mutation_runner.js');
|
|
24
|
+
try {
|
|
25
|
+
await (0, helpers_1.runShellAsync)(`node "${mutateScript}" ${args.join(' ')}`, { stdio: 'inherit', cwd: targetDir });
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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.cmdStatus = cmdStatus;
|
|
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
|
+
function cmdStatus(flags, quiet = false) {
|
|
12
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
13
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
14
|
+
(0, helpers_1.banner)(quiet);
|
|
15
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
16
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('red', '✖')} ${(0, logger_1.bold)('Not installed')} in this project`);
|
|
17
|
+
console.log();
|
|
18
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', 'Run:')} ${(0, logger_1.c)('cyan', 'npx tribunal-kit init')}`);
|
|
19
|
+
console.log();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)((0, logger_1.c)('green', 'Installed'))} ${(0, logger_1.c)('gray', '→')} ${(0, logger_1.c)('gray', agentDest)}`);
|
|
23
|
+
console.log();
|
|
24
|
+
const icons = { agents: '🤖', workflows: '⚡', skills: '🧠', scripts: '🔧' };
|
|
25
|
+
const colors = { agents: 'magenta', workflows: 'yellow', skills: 'blue', scripts: 'green' };
|
|
26
|
+
const subdirs = ['agents', 'workflows', 'skills', 'scripts'];
|
|
27
|
+
for (const sub of subdirs) {
|
|
28
|
+
const subPath = path_1.default.join(agentDest, sub);
|
|
29
|
+
if (fs_1.default.existsSync(subPath)) {
|
|
30
|
+
const count = fs_1.default.readdirSync(subPath).filter(f => !fs_1.default.statSync(path_1.default.join(subPath, f)).isDirectory()).length;
|
|
31
|
+
(0, logger_1.log)(` ${icons[sub]} ${(0, logger_1.c)(colors[sub], sub.padEnd(12))}${(0, logger_1.c)('white', String(count).padStart(3))} files`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
console.log();
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
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.cmdSync = cmdSync;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("../utils/logger");
|
|
10
|
+
const init_1 = require("./init");
|
|
11
|
+
async function cmdSync() {
|
|
12
|
+
console.log(`\n╭─ ${(0, logger_1.c)('bold', 'Tribunal IDE Sync')} ──────────────────`);
|
|
13
|
+
console.log('│');
|
|
14
|
+
console.log(`│ ${(0, logger_1.c)('gray', '✦ Regenerating IDE bridge files...')}`);
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
const agentDest = path_1.default.join(cwd, '.agent');
|
|
17
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
18
|
+
console.error(`│ ${(0, logger_1.c)('red', '✖ Error: .agent/ directory not found.')}`);
|
|
19
|
+
console.error(`│ ${(0, logger_1.c)('gray', 'Run `tk init` first.')}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
await (0, init_1.generateIDEBridges)(cwd, agentDest, false);
|
|
23
|
+
console.log(`│ ${(0, logger_1.c)('green', '✔ Sync complete.')}`);
|
|
24
|
+
console.log('╰────────────────────────────────────────\n');
|
|
25
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.cmdUninstall = cmdUninstall;
|
|
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
|
+
function cmdUninstall(flags, quiet = false) {
|
|
12
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
13
|
+
const agentDest = path_1.default.join(targetDir, '.agent');
|
|
14
|
+
(0, helpers_1.banner)(quiet);
|
|
15
|
+
if (!fs_1.default.existsSync(agentDest)) {
|
|
16
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('yellow', '⚠')} ${(0, logger_1.bold)('.agent/')} is not installed in this project.`);
|
|
17
|
+
console.log();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (flags.dryRun) {
|
|
21
|
+
(0, logger_1.log)((0, logger_1.colorize)('yellow', ' DRY RUN — would remove:'));
|
|
22
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', ' ╰─')} ${agentDest}`);
|
|
23
|
+
console.log();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
fs_1.default.rmSync(agentDest, { recursive: true, force: true });
|
|
28
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('green', '✔')} ${(0, logger_1.bold)('.agent/')} has been removed from this project.`);
|
|
29
|
+
console.log();
|
|
30
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '▸')} To reinstall: ${(0, logger_1.c)('cyan', 'npx tribunal-kit init')}`);
|
|
31
|
+
console.log();
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
if (e instanceof Error) {
|
|
35
|
+
(0, logger_1.err)(`Failed to remove .agent/: ${e.message}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
(0, logger_1.err)(`Failed to remove .agent/: ${String(e)}`);
|
|
39
|
+
}
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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.cmdUpdate = cmdUpdate;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const logger_1 = require("../utils/logger");
|
|
10
|
+
const fs_2 = require("../utils/fs");
|
|
11
|
+
const init_1 = require("./init");
|
|
12
|
+
async function cmdUpdate(flags) {
|
|
13
|
+
const pkgStr = fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../package.json'), 'utf8');
|
|
14
|
+
const pkg = JSON.parse(pkgStr);
|
|
15
|
+
// ── Self-install guard (early, before banner) ───────────
|
|
16
|
+
const targetDir = flags.path ? path_1.default.resolve(flags.path) : process.cwd();
|
|
17
|
+
if ((0, fs_2.isSelfInstall)(targetDir, pkg.name, path_1.default.resolve(__dirname, '../..'))) {
|
|
18
|
+
(0, logger_1.err)('Cannot run update inside the tribunal-kit package itself.');
|
|
19
|
+
(0, logger_1.err)(`Target: ${targetDir}`);
|
|
20
|
+
console.log();
|
|
21
|
+
(0, logger_1.dim)('This command is designed to update .agent/ in OTHER projects.');
|
|
22
|
+
(0, logger_1.dim)('Run it from the root of the project you want to update:');
|
|
23
|
+
(0, logger_1.dim)(' cd /path/to/your-project');
|
|
24
|
+
(0, logger_1.dim)(' npx tribunal-kit update');
|
|
25
|
+
console.log();
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
// ────────────────────────────────────────────────────────
|
|
29
|
+
const isQuiet = flags.quiet || false;
|
|
30
|
+
// Update = init with --force
|
|
31
|
+
flags.force = true;
|
|
32
|
+
if (!isQuiet) {
|
|
33
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '↻')} ${(0, logger_1.bold)('Updating')} ${(0, logger_1.c)('white', '.agent/')} to latest version...`);
|
|
34
|
+
console.log();
|
|
35
|
+
}
|
|
36
|
+
await (0, init_1.cmdInit)(flags, isQuiet);
|
|
37
|
+
}
|