tribunal-kit 4.6.1 → 5.8.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/.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/security-auditor.md +13 -0
- package/.agent/agents/ui-ux-auditor.md +7 -31
- package/.agent/history/memory/.memory.idx +766 -0
- package/.agent/history/memory/MEMORY.md +62 -0
- package/.agent/routing_index.json +694 -714
- package/.agent/rules/GEMINI.md +58 -8
- 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 +235 -0
- package/.agent/skills/thinking-protocol/SKILL.md +27 -0
- package/.agent/workflows/generate.md +1 -1
- package/.agent/workflows/tribunal-speed.md +1 -1
- package/README.md +61 -47
- package/bin/mcp-server.js +476 -121
- package/bin/tribunal-kit.js +1245 -987
- package/bin/wrapper.js +104 -73
- package/dist/cli.js +265 -0
- package/dist/commands/case.js +71 -0
- package/dist/commands/compile.js +84 -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 +339 -0
- package/dist/commands/learn.js +117 -0
- package/dist/commands/marathon.js +45 -0
- package/dist/commands/memory.js +456 -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 +3 -2
- package/scripts/benchmark.js +197 -0
- package/scripts/changelog.js +196 -168
- package/scripts/sync-version.js +94 -81
- package/scripts/validate-payload.js +85 -78
package/bin/wrapper.js
CHANGED
|
@@ -1,107 +1,138 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Tribunal-Kit Core Wrapper
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* This script routes commands to the ultra-fast Rust binary if available and supported.
|
|
6
6
|
* For legacy commands (or if the binary isn't available/compiled yet), it gracefully
|
|
7
7
|
* falls back to the original JavaScript implementation.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const fs = require(
|
|
11
|
-
const path = require(
|
|
12
|
-
const { spawnSync } = require(
|
|
13
|
-
const os = require(
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
const path = require("path");
|
|
12
|
+
const { spawnSync } = require("child_process");
|
|
13
|
+
const os = require("os");
|
|
14
14
|
|
|
15
15
|
// Commands that have been fully ported to Rust so far
|
|
16
|
-
const RUST_COMMANDS = new Set([
|
|
16
|
+
const RUST_COMMANDS = new Set([
|
|
17
|
+
"init",
|
|
18
|
+
"validate",
|
|
19
|
+
"status",
|
|
20
|
+
"sync",
|
|
21
|
+
"hook",
|
|
22
|
+
"uninstall",
|
|
23
|
+
]);
|
|
17
24
|
|
|
18
25
|
// Determine the path to the compiled Rust binary
|
|
19
26
|
// In a full production release, this checks optionalDependencies in node_modules
|
|
20
27
|
// For development, it checks the local target/release folder
|
|
21
28
|
function getBinaryPath() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// First, try production resolution (from optionalDependencies)
|
|
28
|
-
const pkgName = `@tribunal-kit/core-${platform}-${arch}`;
|
|
29
|
-
try {
|
|
30
|
-
// Try to resolve the binary from the optional dependency package
|
|
31
|
-
const pkgPath = require.resolve(`${pkgName}/package.json`);
|
|
32
|
-
const binPath = path.resolve(path.dirname(pkgPath), `bin/tribunal-core${ext}`);
|
|
33
|
-
if (fs.existsSync(binPath)) {
|
|
34
|
-
return binPath;
|
|
35
|
-
}
|
|
36
|
-
} catch (e) {
|
|
37
|
-
// Package not found, ignore and fall back to local dev targets
|
|
38
|
-
}
|
|
29
|
+
const isWindows = os.platform() === "win32";
|
|
30
|
+
const ext = isWindows ? ".exe" : "";
|
|
31
|
+
const platform = os.platform();
|
|
32
|
+
const arch = os.arch();
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
// First, try production resolution (from optionalDependencies)
|
|
35
|
+
const pkgName = `@tribunal-kit/core-${platform}-${arch}`;
|
|
36
|
+
try {
|
|
37
|
+
// Try to resolve the binary from the optional dependency package
|
|
38
|
+
const pkgPath = require.resolve(`${pkgName}/package.json`);
|
|
39
|
+
const binPath = path.resolve(
|
|
40
|
+
path.dirname(pkgPath),
|
|
41
|
+
`bin/tribunal-core${ext}`,
|
|
42
|
+
);
|
|
43
|
+
if (fs.existsSync(binPath)) {
|
|
44
|
+
return binPath;
|
|
44
45
|
}
|
|
46
|
+
} catch {
|
|
47
|
+
// Package not found, ignore and fall back to local dev targets
|
|
48
|
+
}
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
// Second, try to find the binary compiled from crates/core/Cargo.toml (Local dev)
|
|
51
|
+
const devPath = path.resolve(
|
|
52
|
+
__dirname,
|
|
53
|
+
"..",
|
|
54
|
+
"target",
|
|
55
|
+
"release",
|
|
56
|
+
`tribunal-core${ext}`,
|
|
57
|
+
);
|
|
58
|
+
if (fs.existsSync(devPath)) {
|
|
59
|
+
return devPath;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Third, try target/debug (if they ran `cargo build` instead of `--release`)
|
|
63
|
+
const debugPath = path.resolve(
|
|
64
|
+
__dirname,
|
|
65
|
+
"..",
|
|
66
|
+
"target",
|
|
67
|
+
"debug",
|
|
68
|
+
`tribunal-core${ext}`,
|
|
69
|
+
);
|
|
70
|
+
if (fs.existsSync(debugPath)) {
|
|
71
|
+
return debugPath;
|
|
72
|
+
}
|
|
51
73
|
|
|
52
|
-
|
|
74
|
+
return null;
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
function runRustBinary(binPath, args) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
const stdio = [
|
|
79
|
+
"inherit",
|
|
80
|
+
process.stdout.isTTY ? "ignore" : "inherit",
|
|
81
|
+
"inherit",
|
|
82
|
+
];
|
|
83
|
+
const result = spawnSync(binPath, args, {
|
|
84
|
+
stdio: stdio,
|
|
85
|
+
env: process.env,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (result.error) {
|
|
89
|
+
console.error(
|
|
90
|
+
`\x1b[91m✖ Failed to execute Rust engine:\x1b[0m ${result.error.message}`,
|
|
91
|
+
);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
66
94
|
|
|
67
|
-
|
|
95
|
+
process.exit(result.status || 0);
|
|
68
96
|
}
|
|
69
97
|
|
|
70
98
|
function runLegacyFallback() {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
99
|
+
// Use the modular dist/ CLI with lazy-loaded commands for faster cold-start.
|
|
100
|
+
// Each command module is require()'d only when invoked (~70% fewer files loaded).
|
|
101
|
+
const { main } = require("../dist/cli.js");
|
|
102
|
+
main();
|
|
74
103
|
}
|
|
75
104
|
|
|
76
105
|
function main() {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
// Skip 'node' and 'wrapper.js'
|
|
107
|
+
const args = process.argv.slice(2);
|
|
108
|
+
|
|
109
|
+
// Extract the command (the first non-flag argument)
|
|
110
|
+
const command = args.find((a) => !a.startsWith("-"));
|
|
111
|
+
|
|
112
|
+
if (command && RUST_COMMANDS.has(command)) {
|
|
113
|
+
const binPath = getBinaryPath();
|
|
114
|
+
|
|
115
|
+
if (binPath) {
|
|
116
|
+
// For the init command, Rust needs to know where the .agent template folder is.
|
|
117
|
+
if (command === "init") {
|
|
118
|
+
const sourceDir = path.resolve(__dirname, "..", ".agent");
|
|
119
|
+
args.push("--source-dir", sourceDir);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Route to Rust engine
|
|
123
|
+
// console.log('\x1b[90m⚡ Executing via Rust Core Engine\x1b[0m');
|
|
124
|
+
runRustBinary(binPath, args);
|
|
125
|
+
return;
|
|
126
|
+
} else {
|
|
127
|
+
// Warn if Rust command was requested but binary is missing
|
|
128
|
+
console.warn(
|
|
129
|
+
"\x1b[93m⚠ Rust binary not found in target/. Falling back to JS engine.\x1b[0m",
|
|
130
|
+
);
|
|
101
131
|
}
|
|
132
|
+
}
|
|
102
133
|
|
|
103
|
-
|
|
104
|
-
|
|
134
|
+
// Fall back to JS logic for un-ported commands (e.g. `learn`, `case`, `marathon`)
|
|
135
|
+
runLegacyFallback();
|
|
105
136
|
}
|
|
106
137
|
|
|
107
138
|
main();
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* tribunal-kit CLI Core (TypeScript version)
|
|
5
|
+
*
|
|
6
|
+
* Commands are lazy-loaded: only the invoked command's module is require()'d.
|
|
7
|
+
* This means `tk status` loads ~4 files instead of ~17, cutting startup I/O by ~70%.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.main = main;
|
|
11
|
+
const logger_1 = require("./utils/logger");
|
|
12
|
+
const helpers_1 = require("./utils/helpers");
|
|
13
|
+
const PKG = require('../package.json');
|
|
14
|
+
const CURRENT_VERSION = PKG.version;
|
|
15
|
+
// ── Arg Parser ───────────────────────────────────────────
|
|
16
|
+
function parseArgs(argv) {
|
|
17
|
+
const args = { command: null, flags: {} };
|
|
18
|
+
const raw = argv.slice(2);
|
|
19
|
+
// First non-flag arg is the command
|
|
20
|
+
for (const arg of raw) {
|
|
21
|
+
if (!arg.startsWith('--') && !args.command) {
|
|
22
|
+
args.command = arg;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (arg === '--force') {
|
|
26
|
+
args.flags.force = true;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (arg === '--quiet') {
|
|
30
|
+
args.flags.quiet = true;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (arg === '--verbose') {
|
|
34
|
+
args.flags.verbose = true;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (arg === '--dry-run') {
|
|
38
|
+
args.flags.dryRun = true;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (arg === '--minimal') {
|
|
42
|
+
args.flags.minimal = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (arg === '--skip-update-check') {
|
|
46
|
+
args.flags.skipUpdateCheck = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (arg === '--head') {
|
|
50
|
+
args.flags.head = true;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (arg.startsWith('--path=')) {
|
|
54
|
+
args.flags.path = arg.split('=').slice(1).join('=');
|
|
55
|
+
}
|
|
56
|
+
if (arg === '--path') {
|
|
57
|
+
const idx = raw.indexOf('--path');
|
|
58
|
+
const nextVal = raw[idx + 1];
|
|
59
|
+
if (!nextVal || nextVal.startsWith('--')) {
|
|
60
|
+
console.error(` \x1b[91m✖ --path requires a directory argument\x1b[0m`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
args.flags.path = nextVal;
|
|
64
|
+
}
|
|
65
|
+
if (arg.startsWith('--target=')) {
|
|
66
|
+
args.flags.target = arg.split('=').slice(1).join('=');
|
|
67
|
+
}
|
|
68
|
+
if (arg === '--target') {
|
|
69
|
+
const idx = raw.indexOf('--target');
|
|
70
|
+
const nextVal = raw[idx + 1];
|
|
71
|
+
if (!nextVal || nextVal.startsWith('--')) {
|
|
72
|
+
console.error(` \x1b[91m✖ --target requires an argument\x1b[0m`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
args.flags.target = nextVal;
|
|
76
|
+
}
|
|
77
|
+
if (arg.startsWith('--branch=')) {
|
|
78
|
+
args.flags.branch = arg.split('=').slice(1).join('=');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return args;
|
|
82
|
+
}
|
|
83
|
+
function cmdHelp(quiet = false) {
|
|
84
|
+
(0, helpers_1.banner)(quiet);
|
|
85
|
+
const cmd = (name, desc) => ` ${(0, logger_1.c)('cyan', name.padEnd(10))} ${(0, logger_1.c)('gray', desc)}`;
|
|
86
|
+
const opt = (flag, desc) => ` ${(0, logger_1.c)('yellow', flag.padEnd(22))} ${(0, logger_1.c)('gray', desc)}`;
|
|
87
|
+
const ex = (s) => ` ${(0, logger_1.c)('gray', '▸')} ${(0, logger_1.c)('white', s)}`;
|
|
88
|
+
(0, logger_1.log)((0, logger_1.bold)(' Commands'));
|
|
89
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
90
|
+
(0, logger_1.log)(cmd('init', 'Install .agent/ into current project'));
|
|
91
|
+
(0, logger_1.log)(cmd('update', 'Re-install to get latest version'));
|
|
92
|
+
(0, logger_1.log)(cmd('status', 'Check if .agent/ is installed'));
|
|
93
|
+
(0, logger_1.log)(cmd('learn', 'Evolve project idioms based on git diffs'));
|
|
94
|
+
(0, logger_1.log)(cmd('case', 'Manage Case Law precedents (add, search, list, show, stats, overrule)'));
|
|
95
|
+
(0, logger_1.log)(cmd('graph', 'Build and visualize the architecture graph'));
|
|
96
|
+
(0, logger_1.log)(cmd('mutate', 'Run the Mutation Engine to test test-suite reliability'));
|
|
97
|
+
(0, logger_1.log)(cmd('context', 'Retrieve a highly-optimized Context Snapshot for a file'));
|
|
98
|
+
(0, logger_1.log)(cmd('sync', 'Synchronize IDE bridge files with current rules'));
|
|
99
|
+
(0, logger_1.log)(cmd('marathon', 'Long-running agent harness (init, status, next, mark)'));
|
|
100
|
+
(0, logger_1.log)(cmd('hook', 'Install pre-push git hook for auto-learning'));
|
|
101
|
+
(0, logger_1.log)(cmd('compile', 'Compile rules into a static instruction file for terminal agents'));
|
|
102
|
+
(0, logger_1.log)(cmd('memory', '4-Type Taxonomy Persistent Memory Engine (store, recall, gc, stats, export)'));
|
|
103
|
+
(0, logger_1.log)(cmd('uninstall', 'Remove .agent/ folder from project'));
|
|
104
|
+
console.log();
|
|
105
|
+
(0, logger_1.log)((0, logger_1.bold)(' Options'));
|
|
106
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
107
|
+
(0, logger_1.log)(opt('--force', 'Overwrite existing .agent/ folder'));
|
|
108
|
+
(0, logger_1.log)(opt('--path <dir>', 'Install in specific directory'));
|
|
109
|
+
(0, logger_1.log)(opt('--target <name>', 'Target terminal agent for compile (e.g. aider)'));
|
|
110
|
+
(0, logger_1.log)(opt('--quiet', 'Suppress all output'));
|
|
111
|
+
(0, logger_1.log)(opt('--verbose', 'Show detailed debug logging'));
|
|
112
|
+
(0, logger_1.log)(opt('--dry-run', 'Preview actions without executing'));
|
|
113
|
+
(0, logger_1.log)(opt('--minimal', 'Install core agents/skills only (~13 agents)'));
|
|
114
|
+
(0, logger_1.log)(opt('--skip-update-check', 'Skip auto-update version check'));
|
|
115
|
+
(0, logger_1.log)(opt('--head', '(learn) Diff against last commit instead of staged'));
|
|
116
|
+
console.log();
|
|
117
|
+
(0, logger_1.log)((0, logger_1.bold)(' Aliases'));
|
|
118
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
119
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'tk')} ${(0, logger_1.c)('gray', 'Shorthand for tribunal-kit (e.g., tk init, tk status)')}`);
|
|
120
|
+
console.log();
|
|
121
|
+
(0, logger_1.log)((0, logger_1.bold)(' Examples'));
|
|
122
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
123
|
+
(0, logger_1.log)(ex('npx tribunal-kit init'));
|
|
124
|
+
(0, logger_1.log)(ex('tk init --force'));
|
|
125
|
+
(0, logger_1.log)(ex('tk init --path ./my-app'));
|
|
126
|
+
(0, logger_1.log)(ex('npx tribunal-kit init --dry-run'));
|
|
127
|
+
(0, logger_1.log)(ex('tk update'));
|
|
128
|
+
(0, logger_1.log)(ex('tk status'));
|
|
129
|
+
(0, logger_1.log)(ex('tk learn'));
|
|
130
|
+
(0, logger_1.log)(ex('tk learn --dry-run'));
|
|
131
|
+
(0, logger_1.log)(ex('tk learn --head'));
|
|
132
|
+
(0, logger_1.log)(ex('tk case add'));
|
|
133
|
+
(0, logger_1.log)(ex('tk case search "useEffect"'));
|
|
134
|
+
(0, logger_1.log)(ex('tk case list'));
|
|
135
|
+
(0, logger_1.log)(ex('tk case show --id 1'));
|
|
136
|
+
(0, logger_1.log)(ex('tk case stats'));
|
|
137
|
+
(0, logger_1.log)(ex('tk case export'));
|
|
138
|
+
(0, logger_1.log)(ex('tk case overrule --id 1'));
|
|
139
|
+
(0, logger_1.log)(ex('tk graph'));
|
|
140
|
+
(0, logger_1.log)(ex('tk mutate src/utils.js "npm test"'));
|
|
141
|
+
(0, logger_1.log)(ex('tk marathon init "Build a todo app"'));
|
|
142
|
+
(0, logger_1.log)(ex('tk marathon status'));
|
|
143
|
+
(0, logger_1.log)(ex('tk marathon next'));
|
|
144
|
+
(0, logger_1.log)(ex('tk marathon mark 5 pass'));
|
|
145
|
+
(0, logger_1.log)(ex('tk hook'));
|
|
146
|
+
(0, logger_1.log)(ex('tk compile'));
|
|
147
|
+
(0, logger_1.log)(ex('tk memory store --type semantic --content "Uses PostgreSQL" --tags db,orm'));
|
|
148
|
+
(0, logger_1.log)(ex('tk memory recall --query "database" --budget 2000'));
|
|
149
|
+
(0, logger_1.log)(ex('tk memory gc'));
|
|
150
|
+
(0, logger_1.log)(ex('tk memory stats'));
|
|
151
|
+
(0, logger_1.log)(ex('tk memory export'));
|
|
152
|
+
(0, logger_1.log)(ex('tk uninstall'));
|
|
153
|
+
console.log();
|
|
154
|
+
}
|
|
155
|
+
// ── Lazy Loaders ─────────────────────────────────────────
|
|
156
|
+
// Each command module is require()'d only when invoked.
|
|
157
|
+
// Running `tk status` loads ~4 files instead of ~17.
|
|
158
|
+
function loadCmd(modulePath, exportName) {
|
|
159
|
+
return require(modulePath)[exportName];
|
|
160
|
+
}
|
|
161
|
+
async function runWithUpdateCheck(command, flags) {
|
|
162
|
+
const shouldSkip = flags.skipUpdateCheck || process.env.TK_SKIP_UPDATE_CHECK === '1';
|
|
163
|
+
if (!shouldSkip && (command === 'init' || command === 'update')) {
|
|
164
|
+
// version.ts is only loaded for init/update — not every command
|
|
165
|
+
const { autoUpdateCheck } = require('./utils/version');
|
|
166
|
+
const originalArgs = process.argv.slice(2);
|
|
167
|
+
const didReInvoke = await autoUpdateCheck(originalArgs, CURRENT_VERSION);
|
|
168
|
+
if (didReInvoke) {
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const quiet = flags.quiet || false;
|
|
173
|
+
switch (command) {
|
|
174
|
+
case 'init': {
|
|
175
|
+
const cmdInit = loadCmd('./commands/init', 'cmdInit');
|
|
176
|
+
await cmdInit(flags, quiet);
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case 'update': {
|
|
180
|
+
const cmdUpdate = loadCmd('./commands/update', 'cmdUpdate');
|
|
181
|
+
await cmdUpdate(flags);
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
case 'status': {
|
|
185
|
+
const cmdStatus = loadCmd('./commands/status', 'cmdStatus');
|
|
186
|
+
cmdStatus(flags, quiet);
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
case 'learn': {
|
|
190
|
+
const cmdLearn = loadCmd('./commands/learn', 'cmdLearn');
|
|
191
|
+
await cmdLearn(flags, quiet);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case 'case': {
|
|
195
|
+
const cmdCase = loadCmd('./commands/case', 'cmdCase');
|
|
196
|
+
await cmdCase(flags, process.argv, quiet);
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
case 'hook': {
|
|
200
|
+
const cmdHook = loadCmd('./commands/hook', 'cmdHook');
|
|
201
|
+
cmdHook(flags);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case 'graph': {
|
|
205
|
+
const cmdGraph = loadCmd('./commands/graph', 'cmdGraph');
|
|
206
|
+
await cmdGraph(flags, quiet);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 'mutate': {
|
|
210
|
+
const cmdMutate = loadCmd('./commands/mutate', 'cmdMutate');
|
|
211
|
+
await cmdMutate(flags, process.argv);
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
case 'context': {
|
|
215
|
+
const cmdContext = loadCmd('./commands/context', 'cmdContext');
|
|
216
|
+
cmdContext(flags, process.argv);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 'sync': {
|
|
220
|
+
const cmdSync = loadCmd('./commands/sync', 'cmdSync');
|
|
221
|
+
await cmdSync();
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case 'marathon': {
|
|
225
|
+
const cmdMarathon = loadCmd('./commands/marathon', 'cmdMarathon');
|
|
226
|
+
await cmdMarathon(flags, process.argv, quiet);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case 'compile': {
|
|
230
|
+
const cmdCompile = loadCmd('./commands/compile', 'cmdCompile');
|
|
231
|
+
await cmdCompile(flags, quiet);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case 'uninstall': {
|
|
235
|
+
const cmdUninstall = loadCmd('./commands/uninstall', 'cmdUninstall');
|
|
236
|
+
cmdUninstall(flags, quiet);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case 'memory': {
|
|
240
|
+
const cmdMemory = loadCmd('./commands/memory', 'cmdMemory');
|
|
241
|
+
await cmdMemory(flags, process.argv, quiet);
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
case 'help':
|
|
245
|
+
case '--help':
|
|
246
|
+
case '-h':
|
|
247
|
+
case null:
|
|
248
|
+
cmdHelp(quiet);
|
|
249
|
+
break;
|
|
250
|
+
default:
|
|
251
|
+
(0, logger_1.err)(`Unknown command: "${command}"`);
|
|
252
|
+
console.log();
|
|
253
|
+
(0, logger_1.dim)('Run tribunal-kit --help for usage');
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// ── Main ──────────────────────────────────────────────────
|
|
258
|
+
async function main() {
|
|
259
|
+
const { command, flags } = parseArgs(process.argv);
|
|
260
|
+
(0, logger_1.setLogLevels)(flags.quiet || false, flags.verbose || false);
|
|
261
|
+
await runWithUpdateCheck(command, flags);
|
|
262
|
+
}
|
|
263
|
+
if (require.main === module) {
|
|
264
|
+
main();
|
|
265
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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.cmdCase = cmdCase;
|
|
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 cmdCase(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).join(' ');
|
|
19
|
+
if (!args || args === 'help' || args === '--help' || args === '-h') {
|
|
20
|
+
(0, helpers_1.banner)(quiet);
|
|
21
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u2554' + '\u2550'.repeat(60) + '\u2557')}`);
|
|
22
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u2551')}${(0, logger_1.bold)((0, logger_1.c)('white', ' Tribunal Case Law Engine \u2014 Supreme Court '))}${(0, logger_1.c)('cyan', '\u2551')}`);
|
|
23
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u255a' + '\u2550'.repeat(60) + '\u255d')}`);
|
|
24
|
+
console.log();
|
|
25
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'add'.padEnd(10))} ${(0, logger_1.c)('gray', 'Record a new Case Law rejection pattern')}`);
|
|
26
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'search'.padEnd(10))} ${(0, logger_1.c)('gray', 'Search existing cases (e.g., search "query")')}`);
|
|
27
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'list'.padEnd(10))} ${(0, logger_1.c)('gray', 'List all recorded case law')}`);
|
|
28
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'show'.padEnd(10))} ${(0, logger_1.c)('gray', 'Show full diff for a case (e.g., show --id 1)')}`);
|
|
29
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'stats'.padEnd(10))} ${(0, logger_1.c)('gray', 'Show case law stats by domain/verdict')}`);
|
|
30
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'export'.padEnd(10))} ${(0, logger_1.c)('gray', 'Export all cases to Markdown')}`);
|
|
31
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', 'overrule'.padEnd(10))} ${(0, logger_1.c)('gray', 'Overrule a past precedent (e.g., overrule --id 1)')}`);
|
|
32
|
+
console.log();
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
const caseLawScript = path_1.default.join(agentDest, 'scripts', 'case_law_manager.js');
|
|
36
|
+
// Make shorthand aliases
|
|
37
|
+
let pyArgs = args;
|
|
38
|
+
if (pyArgs.startsWith('add'))
|
|
39
|
+
pyArgs = pyArgs.replace(/^add/, 'add-case');
|
|
40
|
+
if (pyArgs.startsWith('search'))
|
|
41
|
+
pyArgs = pyArgs.replace(/^search/, 'search-cases');
|
|
42
|
+
try {
|
|
43
|
+
await (0, helpers_1.runShellAsync)(`node "${caseLawScript}" ${pyArgs}`, { stdio: 'inherit', cwd: targetDir });
|
|
44
|
+
// Memory Bridge: When a case is added, auto-store a SEMANTIC memory
|
|
45
|
+
if (args.startsWith('add')) {
|
|
46
|
+
try {
|
|
47
|
+
const { _memoryStore } = require('./memory');
|
|
48
|
+
// Extract a summary from the add-case args (best effort)
|
|
49
|
+
const contentMatch = args.match(/--violation\s+"([^"]+)"/i) || args.match(/--violation\s+(\S+)/i);
|
|
50
|
+
const domainMatch = args.match(/--domain\s+"([^"]+)"/i) || args.match(/--domain\s+(\S+)/i);
|
|
51
|
+
const violation = contentMatch ? contentMatch[1] : 'Unknown violation';
|
|
52
|
+
const domain = domainMatch ? domainMatch[1] : 'general';
|
|
53
|
+
_memoryStore(
|
|
54
|
+
agentDest,
|
|
55
|
+
'semantic',
|
|
56
|
+
`CASE LAW REJECTION: ${violation} (domain: ${domain})`,
|
|
57
|
+
['case-law', domain, 'rejection'],
|
|
58
|
+
null
|
|
59
|
+
);
|
|
60
|
+
if (!quiet) {
|
|
61
|
+
(0, logger_1.log)(` ${(0, logger_1.c)('cyan', '\u25b8')} Memory bridge: case law rejection stored to memory index`);
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
// Non-critical — case law was still saved, memory bridge is a bonus
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
process.exit(1); // Script already prints errors
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cmdCompile = cmdCompile;
|
|
4
|
+
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const { log, err, ok, c, bold, dbg } = require("../utils/logger");
|
|
8
|
+
|
|
9
|
+
async function cmdCompile(flags, quiet) {
|
|
10
|
+
const cwd = process.cwd();
|
|
11
|
+
const agentDir = path.join(cwd, ".agent");
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(agentDir)) {
|
|
14
|
+
err("Tribunal Kit is not installed in this directory (.agent folder missing). Run 'tk init' first.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
log(bold("Compiling Tribunal Kit rules..."));
|
|
19
|
+
|
|
20
|
+
let compiledContext = "# Tribunal Kit Context\n\n";
|
|
21
|
+
compiledContext += "The following are rules, agents, and skills from the Tribunal Kit.\n\n";
|
|
22
|
+
|
|
23
|
+
// 1. Read GEMINI.md
|
|
24
|
+
const geminiPath = path.join(agentDir, "rules", "GEMINI.md");
|
|
25
|
+
if (fs.existsSync(geminiPath)) {
|
|
26
|
+
compiledContext += "## Global Rules (GEMINI.md)\n\n";
|
|
27
|
+
compiledContext += fs.readFileSync(geminiPath, "utf-8") + "\n\n";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Read Agents
|
|
31
|
+
const agentsDir = path.join(agentDir, "agents");
|
|
32
|
+
if (fs.existsSync(agentsDir)) {
|
|
33
|
+
compiledContext += "## Agents\n\n";
|
|
34
|
+
const agents = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
35
|
+
for (const file of agents) {
|
|
36
|
+
const content = fs.readFileSync(path.join(agentsDir, file), "utf-8");
|
|
37
|
+
compiledContext += `### Agent: ${file}\n\n`;
|
|
38
|
+
compiledContext += content + "\n\n";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 3. Read Skills
|
|
43
|
+
const skillsDir = path.join(agentDir, "skills");
|
|
44
|
+
if (fs.existsSync(skillsDir)) {
|
|
45
|
+
compiledContext += "## Skills\n\n";
|
|
46
|
+
const skills = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
47
|
+
for (const dirent of skills) {
|
|
48
|
+
if (dirent.isDirectory()) {
|
|
49
|
+
const skillPath = path.join(skillsDir, dirent.name, "SKILL.md");
|
|
50
|
+
if (fs.existsSync(skillPath)) {
|
|
51
|
+
const content = fs.readFileSync(skillPath, "utf-8");
|
|
52
|
+
compiledContext += `### Skill: ${dirent.name}\n\n`;
|
|
53
|
+
compiledContext += content + "\n\n";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 4. Read Workflows
|
|
60
|
+
const workflowsDir = path.join(agentDir, "workflows");
|
|
61
|
+
if (fs.existsSync(workflowsDir)) {
|
|
62
|
+
compiledContext += "## Workflows\n\n";
|
|
63
|
+
const workflows = fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md'));
|
|
64
|
+
for (const file of workflows) {
|
|
65
|
+
const content = fs.readFileSync(path.join(workflowsDir, file), "utf-8");
|
|
66
|
+
compiledContext += `### Workflow: ${file}\n\n`;
|
|
67
|
+
compiledContext += content + "\n\n";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let targetFile = ".tribunal-compiled.md";
|
|
72
|
+
if (flags.target) {
|
|
73
|
+
if (flags.target === "aider") targetFile = ".aider.conf.yml";
|
|
74
|
+
if (flags.target === "claude") targetFile = ".claude.json";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const outputPath = path.join(cwd, targetFile);
|
|
78
|
+
fs.writeFileSync(outputPath, compiledContext, "utf-8");
|
|
79
|
+
|
|
80
|
+
ok(`Compiled rules written to ${c('cyan', targetFile)}`);
|
|
81
|
+
if (!quiet) {
|
|
82
|
+
log(` ${c('gray', 'Load this file into your terminal agent (e.g. Claude Code, Aider, OpenCode)')}`);
|
|
83
|
+
}
|
|
84
|
+
}
|