tribunal-kit 5.8.3 → 5.8.5
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 +5 -5
- package/.agent/history/integrity_manifest.json +1026 -0
- package/.agent/history/memory/.memory.idx +1217 -1
- package/.agent/history/memory/MEMORY.md +81 -1
- package/.agent/rules/GEMINI.md +1 -1
- package/.agent/scripts/_utils.js +28 -7
- package/.agent/scripts/case_law_manager.js +3 -15
- package/.agent/scripts/context_broker.js +3 -20
- package/.agent/scripts/guardrail_engine.js +643 -0
- package/.agent/scripts/integrity_manifest.js +492 -0
- package/.agent/scripts/marathon_harness.js +10 -1
- package/.agent/scripts/signal_detector.js +1 -1
- package/.agent/scripts/skill_evolution.js +39 -36
- package/.agent/scripts/skill_integrator.js +2 -12
- package/.agent/scripts/swarm_dispatcher.js +54 -5
- package/.agent/skills/12-principles-of-animation/SKILL.md +69 -0
- package/.agent/skills/60fps-animation/SKILL.md +78 -0
- package/.agent/skills/accessible-animation/SKILL.md +86 -0
- package/.agent/skills/adapt/SKILL.md +75 -0
- package/.agent/skills/animation-on-scroll/SKILL.md +110 -0
- package/.agent/skills/animation-systems/SKILL.md +69 -0
- package/.agent/skills/antfu-conventions/SKILL.md +74 -0
- package/.agent/skills/api-patterns/scripts/__pycache__/api_validator.cpython-311.pyc +0 -0
- package/.agent/skills/apple-design/SKILL.md +108 -0
- package/.agent/skills/audit-and-fix/SKILL.md +83 -0
- package/.agent/skills/baseline-ui/SKILL.md +74 -0
- package/.agent/skills/better-colors/SKILL.md +132 -0
- package/.agent/skills/better-typography/SKILL.md +111 -0
- package/.agent/skills/better-ui/SKILL.md +102 -0
- package/.agent/skills/bolder/SKILL.md +68 -0
- package/.agent/skills/build-primitive/SKILL.md +70 -0
- package/.agent/skills/clarify/SKILL.md +75 -0
- package/.agent/skills/cobejs/SKILL.md +96 -0
- package/.agent/skills/codebase-design/SKILL.md +84 -0
- package/.agent/skills/colorize/SKILL.md +77 -0
- package/.agent/skills/compact-landing/SKILL.md +70 -0
- package/.agent/skills/company-logos/SKILL.md +73 -0
- package/.agent/skills/create-design-md/SKILL.md +104 -0
- package/.agent/skills/critique/SKILL.md +95 -0
- package/.agent/skills/database-design/scripts/__pycache__/schema_validator.cpython-311.pyc +0 -0
- package/.agent/skills/delight/SKILL.md +65 -0
- package/.agent/skills/design-lab/SKILL.md +59 -0
- package/.agent/skills/diagnosing-bugs/SKILL.md +190 -0
- package/.agent/skills/distill/SKILL.md +65 -0
- package/.agent/skills/domain-modeling/SKILL.md +78 -0
- package/.agent/skills/fixing-accessibility/SKILL.md +100 -0
- package/.agent/skills/fixing-metadata/SKILL.md +97 -0
- package/.agent/skills/fixing-motion-performance/SKILL.md +96 -0
- package/.agent/skills/frontend-design/SKILL.md +80 -81
- package/.agent/skills/frontend-design/scripts/__pycache__/accessibility_checker.cpython-311.pyc +0 -0
- package/.agent/skills/frontend-design/scripts/__pycache__/ux_audit.cpython-311.pyc +0 -0
- package/.agent/skills/geo-fundamentals/scripts/__pycache__/geo_checker.cpython-311.pyc +0 -0
- package/.agent/skills/gpt-taste/SKILL.md +68 -0
- package/.agent/skills/harden/SKILL.md +74 -0
- package/.agent/skills/i18n-localization/scripts/__pycache__/i18n_checker.cpython-311.pyc +0 -0
- package/.agent/skills/impeccable/SKILL.md +74 -0
- package/.agent/skills/improve-codebase-architecture/SKILL.md +67 -0
- package/.agent/skills/improve-ui/SKILL.md +83 -0
- package/.agent/skills/landing-page/SKILL.md +88 -0
- package/.agent/skills/lint-and-validate/SKILL.md +0 -1
- package/.agent/skills/lint-and-validate/scripts/__pycache__/lint_runner.cpython-311.pyc +0 -0
- package/.agent/skills/lint-and-validate/scripts/__pycache__/type_coverage.cpython-311.pyc +0 -0
- package/.agent/skills/local-first-architecture/SKILL.md +66 -0
- package/.agent/skills/lottie-animation/SKILL.md +82 -0
- package/.agent/skills/marquee-loop/SKILL.md +96 -0
- package/.agent/skills/masked-reveal/SKILL.md +88 -0
- package/.agent/skills/micro-interaction/SKILL.md +100 -0
- package/.agent/skills/mobile-design/scripts/__pycache__/mobile_audit.cpython-311.pyc +0 -0
- package/.agent/skills/morphing-icons/SKILL.md +85 -0
- package/.agent/skills/motion-engineering/SKILL.md +66 -164
- package/.agent/skills/nextjs-react-expert/scripts/__pycache__/convert_rules.cpython-311.pyc +0 -0
- package/.agent/skills/nextjs-react-expert/scripts/__pycache__/react_performance_checker.cpython-311.pyc +0 -0
- package/.agent/skills/page-transition-animation/SKILL.md +108 -0
- package/.agent/skills/parallel-agents/SKILL.md +5 -5
- package/.agent/skills/performance-profiling/scripts/__pycache__/lighthouse_audit.cpython-311.pyc +0 -0
- package/.agent/skills/polish/SKILL.md +63 -0
- package/.agent/skills/pricing-page/SKILL.md +68 -0
- package/.agent/skills/progressive-blur/SKILL.md +100 -0
- package/.agent/skills/quieter/SKILL.md +68 -0
- package/.agent/skills/react-doctor/SKILL.md +70 -0
- package/.agent/skills/redesign-skill/SKILL.md +65 -0
- package/.agent/skills/seo-fundamentals/scripts/__pycache__/seo_checker.cpython-311.pyc +0 -0
- package/.agent/skills/shape/SKILL.md +73 -0
- package/.agent/skills/soft-skill/SKILL.md +72 -0
- package/.agent/skills/sounds-on-the-web/SKILL.md +100 -0
- package/.agent/skills/svg-animation/SKILL.md +91 -0
- package/.agent/skills/swiss-design/SKILL.md +64 -0
- package/.agent/skills/taste-skill/SKILL.md +71 -0
- package/.agent/skills/tdd-workflow/SKILL.md +36 -165
- package/.agent/skills/testing-patterns/scripts/__pycache__/test_runner.cpython-311.pyc +0 -0
- package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +82 -0
- package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +66 -0
- package/.agent/skills/transitions-dev/SKILL.md +101 -0
- package/.agent/skills/typeset/SKILL.md +76 -0
- package/.agent/skills/ui-skills-root/SKILL.md +85 -0
- package/.agent/skills/vulnerability-scanner/scripts/__pycache__/security_scan.cpython-311.pyc +0 -0
- package/.agent/skills/web-quality-audit/SKILL.md +67 -0
- package/.agent/skills/webapp-testing/scripts/__pycache__/playwright_runner.cpython-311.pyc +0 -0
- package/.agent/workflows/generate.md +1 -1
- package/.agent/workflows/tribunal-full.md +2 -2
- package/.agent/workflows/tribunal-speed.md +2 -2
- package/CONTRIBUTING.md +1 -1
- package/README.md +349 -239
- package/bin/mcp-server.js +45 -45
- package/bin/tribunal-kit.js +62 -1482
- package/bin/wrapper.js +50 -25
- package/dist/cli.js +43 -0
- package/dist/commands/align.js +1 -1
- package/dist/commands/compile.js +1 -1
- package/dist/commands/guardrail.js +275 -0
- package/dist/commands/init.js +35 -10
- package/dist/commands/native.js +228 -0
- package/dist/commands/optimize.js +318 -0
- package/dist/commands/validate.js +67 -0
- package/dist/mcp/server.js +4 -138
- package/dist/utils/version.js +1 -1
- package/package.json +13 -10
- package/scripts/benchmark.js +42 -0
- package/scripts/fix-vbc.js +98 -0
- package/scripts/fix-vbc.ps1 +119 -0
- package/scripts/sync-version.js +129 -76
package/bin/wrapper.js
CHANGED
|
@@ -21,8 +21,13 @@ const RUST_COMMANDS = new Set([
|
|
|
21
21
|
"hook",
|
|
22
22
|
"uninstall",
|
|
23
23
|
"memory",
|
|
24
|
+
"min-context",
|
|
25
|
+
"dag-schedule",
|
|
26
|
+
"context-compress",
|
|
27
|
+
"optimize-step",
|
|
24
28
|
]);
|
|
25
29
|
|
|
30
|
+
|
|
26
31
|
// Determine the path to the compiled Rust binary
|
|
27
32
|
// In a full production release, this checks optionalDependencies in node_modules
|
|
28
33
|
// For development, it checks the local target/release folder
|
|
@@ -30,6 +35,11 @@ function getBinaryPath() {
|
|
|
30
35
|
if (process.env.TRIBUNAL_FORCE_JS === "1") {
|
|
31
36
|
return null;
|
|
32
37
|
}
|
|
38
|
+
|
|
39
|
+
if (process.env.TRIBUNAL_CORE_PATH && fs.existsSync(process.env.TRIBUNAL_CORE_PATH)) {
|
|
40
|
+
return process.env.TRIBUNAL_CORE_PATH;
|
|
41
|
+
}
|
|
42
|
+
|
|
33
43
|
const isWindows = os.platform() === "win32";
|
|
34
44
|
const ext = isWindows ? ".exe" : "";
|
|
35
45
|
const platform = os.platform();
|
|
@@ -38,46 +48,61 @@ function getBinaryPath() {
|
|
|
38
48
|
// First, try production resolution (from optionalDependencies)
|
|
39
49
|
const pkgName = `@tribunal-kit/core-${platform}-${arch}`;
|
|
40
50
|
try {
|
|
41
|
-
// Try to resolve the binary from the optional dependency package
|
|
42
51
|
const pkgPath = require.resolve(`${pkgName}/package.json`);
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
`bin/tribunal-core${ext}`,
|
|
46
|
-
);
|
|
52
|
+
const pkgDir = path.dirname(pkgPath);
|
|
53
|
+
const binPath = path.resolve(pkgDir, `bin/tribunal-core${ext}`);
|
|
47
54
|
if (fs.existsSync(binPath)) {
|
|
48
55
|
return binPath;
|
|
49
56
|
}
|
|
57
|
+
const rootBinPath = path.resolve(pkgDir, `tribunal-core${ext}`);
|
|
58
|
+
if (fs.existsSync(rootBinPath)) {
|
|
59
|
+
return rootBinPath;
|
|
60
|
+
}
|
|
50
61
|
} catch {
|
|
51
62
|
// Package not found, ignore and fall back to local dev targets
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
// Second, try to find the binary
|
|
55
|
-
const
|
|
56
|
-
__dirname,
|
|
57
|
-
"..",
|
|
58
|
-
"target",
|
|
59
|
-
"
|
|
60
|
-
`tribunal-core${ext}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
// Second, try to find the binary in local dev target directories
|
|
66
|
+
const candidatePaths = [
|
|
67
|
+
path.resolve(__dirname, "..", "target", "release", `tribunal-core${ext}`),
|
|
68
|
+
path.resolve(__dirname, "..", "target", "debug", `tribunal-core${ext}`),
|
|
69
|
+
path.resolve(__dirname, "..", "..", "target", "release", `tribunal-core${ext}`),
|
|
70
|
+
path.resolve(__dirname, "..", "..", "target", "debug", `tribunal-core${ext}`),
|
|
71
|
+
path.resolve(process.cwd(), "target", "release", `tribunal-core${ext}`),
|
|
72
|
+
path.resolve(process.cwd(), "target", "debug", `tribunal-core${ext}`),
|
|
73
|
+
path.resolve(process.cwd(), "tribunal-kit", "target", "release", `tribunal-core${ext}`),
|
|
74
|
+
path.resolve(process.cwd(), "tribunal-kit", "target", "debug", `tribunal-core${ext}`),
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
for (const candidate of candidatePaths) {
|
|
78
|
+
if (fs.existsSync(candidate)) {
|
|
79
|
+
return candidate;
|
|
80
|
+
}
|
|
64
81
|
}
|
|
65
82
|
|
|
66
|
-
// Third,
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
// Third, attempt on-demand compilation if Cargo.toml exists locally and cargo is installed
|
|
84
|
+
const cargoTomlPath = path.resolve(__dirname, "..", "Cargo.toml");
|
|
85
|
+
if (fs.existsSync(cargoTomlPath)) {
|
|
86
|
+
try {
|
|
87
|
+
const buildResult = spawnSync("cargo", ["build", "--release"], {
|
|
88
|
+
cwd: path.resolve(__dirname, ".."),
|
|
89
|
+
stdio: "ignore",
|
|
90
|
+
});
|
|
91
|
+
if (buildResult.status === 0) {
|
|
92
|
+
const releasePath = candidatePaths[0];
|
|
93
|
+
if (fs.existsSync(releasePath)) {
|
|
94
|
+
return releasePath;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
// cargo not available or build failed, fallback gracefully
|
|
99
|
+
}
|
|
76
100
|
}
|
|
77
101
|
|
|
78
102
|
return null;
|
|
79
103
|
}
|
|
80
104
|
|
|
105
|
+
|
|
81
106
|
function runRustBinary(binPath, args) {
|
|
82
107
|
const stdio = [
|
|
83
108
|
"inherit",
|
package/dist/cli.js
CHANGED
|
@@ -105,6 +105,13 @@ function cmdHelp(quiet = false) {
|
|
|
105
105
|
(0, logger_1.log)(cmd('hook', 'Install pre-push git hook for auto-learning'));
|
|
106
106
|
(0, logger_1.log)(cmd('compile', 'Compile rules into a static instruction file for terminal agents'));
|
|
107
107
|
(0, logger_1.log)(cmd('memory', '4-Type Taxonomy Persistent Memory Engine (store, recall, gc, stats, export)'));
|
|
108
|
+
(0, logger_1.log)(cmd('optimize-skill', 'Optimize project skills actively using SkillOpt validation gates'));
|
|
109
|
+
(0, logger_1.log)(cmd('validate', 'Validate a JSON payload against a Tribunal schema'));
|
|
110
|
+
(0, logger_1.log)(cmd('min-context', 'Remove empty lines from a context file'));
|
|
111
|
+
(0, logger_1.log)(cmd('dag-schedule', 'Compute parallel execution waves from task dependencies'));
|
|
112
|
+
(0, logger_1.log)(cmd('context-compress', 'Compress a context file while retaining VERIFY comments'));
|
|
113
|
+
(0, logger_1.log)(cmd('optimize-step', 'Apply bounded SkillOpt edits from a JSON payload'));
|
|
114
|
+
(0, logger_1.log)(cmd('guardrail', 'Validate .agent/ integrity (phantom refs, count mismatches, drift)'));
|
|
108
115
|
(0, logger_1.log)(cmd('uninstall', 'Remove .agent/ folder from project'));
|
|
109
116
|
console.log();
|
|
110
117
|
(0, logger_1.log)((0, logger_1.bold)(' Options'));
|
|
@@ -153,6 +160,7 @@ function cmdHelp(quiet = false) {
|
|
|
153
160
|
(0, logger_1.log)(ex('echo "Certainly! Here is - item 1" | tk align'));
|
|
154
161
|
(0, logger_1.log)(ex('tk align output.md --write'));
|
|
155
162
|
(0, logger_1.log)(ex('tk memory store --type semantic --content "Uses PostgreSQL" --tags db,orm'));
|
|
163
|
+
(0, logger_1.log)(ex('tk optimize-skill --target project-idioms "npm test"'));
|
|
156
164
|
(0, logger_1.log)(ex('tk memory recall --query "database" --budget 2000'));
|
|
157
165
|
(0, logger_1.log)(ex('tk memory gc'));
|
|
158
166
|
(0, logger_1.log)(ex('tk memory stats'));
|
|
@@ -254,6 +262,41 @@ async function runWithUpdateCheck(command, flags) {
|
|
|
254
262
|
await cmdMemory(flags, process.argv, quiet);
|
|
255
263
|
break;
|
|
256
264
|
}
|
|
265
|
+
case 'optimize-skill': {
|
|
266
|
+
const cmdOptimizeSkill = loadCmd('./commands/optimize', 'cmdOptimizeSkill');
|
|
267
|
+
await cmdOptimizeSkill(flags, process.argv, quiet);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
case 'guardrail': {
|
|
271
|
+
const cmdGuardrail = loadCmd('./commands/guardrail', 'cmdGuardrail');
|
|
272
|
+
await cmdGuardrail(flags, process.argv, quiet);
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
case 'validate': {
|
|
276
|
+
const cmdValidate = loadCmd('./commands/validate', 'cmdValidate');
|
|
277
|
+
cmdValidate(flags, process.argv, quiet);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
case 'min-context': {
|
|
281
|
+
const cmdMinContext = loadCmd('./commands/native', 'cmdMinContext');
|
|
282
|
+
cmdMinContext(process.argv, quiet);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case 'dag-schedule': {
|
|
286
|
+
const cmdDagSchedule = loadCmd('./commands/native', 'cmdDagSchedule');
|
|
287
|
+
cmdDagSchedule(process.argv, quiet);
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 'context-compress': {
|
|
291
|
+
const cmdContextCompress = loadCmd('./commands/native', 'cmdContextCompress');
|
|
292
|
+
cmdContextCompress(process.argv, quiet);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
case 'optimize-step': {
|
|
296
|
+
const cmdOptimizeStep = loadCmd('./commands/native', 'cmdOptimizeStep');
|
|
297
|
+
cmdOptimizeStep(process.argv, quiet);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
257
300
|
case 'help':
|
|
258
301
|
case '--help':
|
|
259
302
|
case '-h':
|
package/dist/commands/align.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const readline = require("readline");
|
|
6
|
-
const {
|
|
6
|
+
const { _log, err, ok, c, bold, _warn } = require("../utils/logger");
|
|
7
7
|
|
|
8
8
|
function alignText(text) {
|
|
9
9
|
if (!text) return "";
|
package/dist/commands/compile.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.cmdCompile = cmdCompile;
|
|
|
4
4
|
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const path = require("path");
|
|
7
|
-
const { log, err, ok, c, bold,
|
|
7
|
+
const { log, err, ok, c, bold, _dbg } = require("../utils/logger");
|
|
8
8
|
|
|
9
9
|
async function cmdCompile(flags, quiet) {
|
|
10
10
|
const cwd = process.cwd();
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* guardrail.js — CLI command handler for `tk guardrail`
|
|
4
|
+
*
|
|
5
|
+
* Validates .agent/ files against the integrity manifest using
|
|
6
|
+
* the Neurosymbolic Guardrail Engine.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* tk guardrail → Scan all .agent/ files
|
|
10
|
+
* tk guardrail --file output.md → Validate a specific file
|
|
11
|
+
* tk guardrail --fix → Auto-fix simple violations
|
|
12
|
+
* tk guardrail --json → Output as JSON
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.cmdGuardrail = cmdGuardrail;
|
|
16
|
+
|
|
17
|
+
const fs = require("fs");
|
|
18
|
+
const path = require("path");
|
|
19
|
+
const logger_1 = require("../utils/logger");
|
|
20
|
+
|
|
21
|
+
async function cmdGuardrail(flags, argv, quiet) {
|
|
22
|
+
const projectRoot = flags.path || process.cwd();
|
|
23
|
+
const agentDir = path.join(projectRoot, ".agent");
|
|
24
|
+
|
|
25
|
+
if (!fs.existsSync(agentDir)) {
|
|
26
|
+
(0, logger_1.err)("No .agent/ directory found. Run `tk init` first.");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Resolve script paths (installed vs local development)
|
|
31
|
+
const scriptsDir = path.join(agentDir, "scripts");
|
|
32
|
+
const manifestScript = path.join(scriptsDir, "integrity_manifest.js");
|
|
33
|
+
const guardrailScript = path.join(scriptsDir, "guardrail_engine.js");
|
|
34
|
+
|
|
35
|
+
if (!fs.existsSync(manifestScript)) {
|
|
36
|
+
(0, logger_1.err)(
|
|
37
|
+
"integrity_manifest.js not found in .agent/scripts/. Your installation may be outdated — run `tk update`.",
|
|
38
|
+
);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(guardrailScript)) {
|
|
43
|
+
(0, logger_1.err)(
|
|
44
|
+
"guardrail_engine.js not found in .agent/scripts/. Your installation may be outdated — run `tk update`.",
|
|
45
|
+
);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Step 1: Generate manifest
|
|
50
|
+
if (!quiet) {
|
|
51
|
+
(0, logger_1.log)(
|
|
52
|
+
` ${(0, logger_1.c)("cyan", "◆")} Generating integrity manifest...`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const { generateManifest, saveManifest } = require(manifestScript);
|
|
57
|
+
const manifest = generateManifest(projectRoot);
|
|
58
|
+
|
|
59
|
+
if (manifest.error) {
|
|
60
|
+
(0, logger_1.err)(manifest.error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Save manifest for future use
|
|
65
|
+
saveManifest(manifest, projectRoot);
|
|
66
|
+
|
|
67
|
+
// Step 2: Determine files to validate
|
|
68
|
+
const { validate } = require(guardrailScript);
|
|
69
|
+
const fileArg = extractFileArg(argv);
|
|
70
|
+
const fixMode = flags.write || argv.includes("--fix");
|
|
71
|
+
const jsonMode = argv.includes("--json");
|
|
72
|
+
|
|
73
|
+
let filesToCheck = [];
|
|
74
|
+
|
|
75
|
+
if (fileArg) {
|
|
76
|
+
const resolved = path.resolve(fileArg);
|
|
77
|
+
if (!fs.existsSync(resolved)) {
|
|
78
|
+
(0, logger_1.err)(`File not found: ${fileArg}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
filesToCheck.push(resolved);
|
|
82
|
+
} else {
|
|
83
|
+
// Scan all .agent/ markdown files
|
|
84
|
+
filesToCheck = walkAgentFiles(agentDir);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!quiet) {
|
|
88
|
+
(0, logger_1.log)(
|
|
89
|
+
` ${(0, logger_1.c)("cyan", "◆")} Scanning ${filesToCheck.length} files...`,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Step 3: Run guardrail engine
|
|
94
|
+
let totalViolations = 0;
|
|
95
|
+
let totalCritical = 0;
|
|
96
|
+
let totalAutoFixed = 0;
|
|
97
|
+
const allResults = [];
|
|
98
|
+
|
|
99
|
+
for (const file of filesToCheck) {
|
|
100
|
+
const content = fs.readFileSync(file, "utf8");
|
|
101
|
+
const result = validate(content, manifest, {
|
|
102
|
+
autoFix: fixMode,
|
|
103
|
+
context: { projectRoot, filePath: file },
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (result.violations.length > 0) {
|
|
107
|
+
totalViolations += result.violations.length;
|
|
108
|
+
totalCritical += result.violations.filter(
|
|
109
|
+
(v) => v.severity === "critical",
|
|
110
|
+
).length;
|
|
111
|
+
|
|
112
|
+
allResults.push({
|
|
113
|
+
file: path.relative(projectRoot, file),
|
|
114
|
+
...result,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Apply auto-fix
|
|
118
|
+
if (
|
|
119
|
+
fixMode &&
|
|
120
|
+
result.autoFixedContent &&
|
|
121
|
+
result.autoFixedContent !== content
|
|
122
|
+
) {
|
|
123
|
+
fs.writeFileSync(file, result.autoFixedContent, "utf8");
|
|
124
|
+
totalAutoFixed++;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Step 4: Output results
|
|
130
|
+
if (jsonMode) {
|
|
131
|
+
console.log(
|
|
132
|
+
JSON.stringify(
|
|
133
|
+
{
|
|
134
|
+
manifest_summary: {
|
|
135
|
+
agents: manifest.agents.total,
|
|
136
|
+
reviewers: manifest.agents.reviewer_count,
|
|
137
|
+
skills: manifest.skills.total,
|
|
138
|
+
scripts: manifest.scripts.total,
|
|
139
|
+
workflows: manifest.workflows.total,
|
|
140
|
+
},
|
|
141
|
+
files_scanned: filesToCheck.length,
|
|
142
|
+
total_violations: totalViolations,
|
|
143
|
+
critical_violations: totalCritical,
|
|
144
|
+
auto_fixed: totalAutoFixed,
|
|
145
|
+
results: allResults,
|
|
146
|
+
},
|
|
147
|
+
null,
|
|
148
|
+
2,
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (quiet) {
|
|
155
|
+
process.exit(totalCritical > 0 ? 1 : 0);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Human-readable output
|
|
160
|
+
console.log();
|
|
161
|
+
console.log(
|
|
162
|
+
` ${(0, logger_1.c)("cyan", "🛡️")} ${(0, logger_1.bold)("Guardrail Validation Report")}`,
|
|
163
|
+
);
|
|
164
|
+
console.log(` ${(0, logger_1.c)("gray", "─".repeat(40))}`);
|
|
165
|
+
console.log(
|
|
166
|
+
` Agents: ${(0, logger_1.c)("white", String(manifest.agents.total))} (${manifest.agents.reviewer_count} reviewers)`,
|
|
167
|
+
);
|
|
168
|
+
console.log(
|
|
169
|
+
` Skills: ${(0, logger_1.c)("white", String(manifest.skills.total))}`,
|
|
170
|
+
);
|
|
171
|
+
console.log(
|
|
172
|
+
` Scripts: ${(0, logger_1.c)("white", String(manifest.scripts.total))}`,
|
|
173
|
+
);
|
|
174
|
+
console.log(
|
|
175
|
+
` Workflows: ${(0, logger_1.c)("white", String(manifest.workflows.total))}`,
|
|
176
|
+
);
|
|
177
|
+
console.log(` ${(0, logger_1.c)("gray", "─".repeat(40))}`);
|
|
178
|
+
console.log(
|
|
179
|
+
` Files scanned: ${(0, logger_1.c)("white", String(filesToCheck.length))}`,
|
|
180
|
+
);
|
|
181
|
+
console.log(
|
|
182
|
+
` Violations: ${totalViolations > 0 ? (0, logger_1.c)("yellow", String(totalViolations)) : (0, logger_1.c)("green", "0")}`,
|
|
183
|
+
);
|
|
184
|
+
console.log(
|
|
185
|
+
` Critical: ${totalCritical > 0 ? (0, logger_1.c)("red", String(totalCritical)) : (0, logger_1.c)("green", "0")}`,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (fixMode && totalAutoFixed > 0) {
|
|
189
|
+
console.log(
|
|
190
|
+
` Auto-fixed: ${(0, logger_1.c)("green", String(totalAutoFixed))}`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log(` ${(0, logger_1.c)("gray", "─".repeat(40))}`);
|
|
195
|
+
|
|
196
|
+
// Show violations
|
|
197
|
+
for (const result of allResults) {
|
|
198
|
+
console.log(
|
|
199
|
+
`\n 📄 ${(0, logger_1.c)("cyan", result.file)} — ${result.summary}`,
|
|
200
|
+
);
|
|
201
|
+
for (const v of result.violations) {
|
|
202
|
+
const icon =
|
|
203
|
+
v.severity === "critical"
|
|
204
|
+
? (0, logger_1.c)("red", "●")
|
|
205
|
+
: v.severity === "warning"
|
|
206
|
+
? (0, logger_1.c)("yellow", "●")
|
|
207
|
+
: (0, logger_1.c)("blue", "●");
|
|
208
|
+
console.log(
|
|
209
|
+
` ${icon} [${(0, logger_1.c)("gray", v.rule)}] ${v.message}`,
|
|
210
|
+
);
|
|
211
|
+
if (v.suggestion) {
|
|
212
|
+
console.log(
|
|
213
|
+
` ${(0, logger_1.c)("gray", "💡")} ${(0, logger_1.c)("gray", v.suggestion)}`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (totalViolations === 0) {
|
|
220
|
+
console.log(
|
|
221
|
+
`\n ${(0, logger_1.c)("green", "✅")} All files clean. Zero phantom references. Zero count mismatches.`,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log();
|
|
226
|
+
process.exit(totalCritical > 0 ? 1 : 0);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
function extractFileArg(argv) {
|
|
232
|
+
const raw = argv.slice(2);
|
|
233
|
+
const fileIdx = raw.indexOf("--file");
|
|
234
|
+
if (fileIdx !== -1 && raw[fileIdx + 1]) {
|
|
235
|
+
return raw[fileIdx + 1];
|
|
236
|
+
}
|
|
237
|
+
// Also check for positional arg after 'guardrail'
|
|
238
|
+
for (const arg of raw) {
|
|
239
|
+
if (arg === "guardrail" || arg.startsWith("--")) continue;
|
|
240
|
+
if (fs.existsSync(arg)) return arg;
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function walkAgentFiles(dir, fileList = []) {
|
|
246
|
+
if (!fs.existsSync(dir)) return fileList;
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const entries = fs.readdirSync(dir);
|
|
250
|
+
for (const entry of entries) {
|
|
251
|
+
if (
|
|
252
|
+
["node_modules", ".git", "history", ".backups", ".shared"].includes(
|
|
253
|
+
entry,
|
|
254
|
+
)
|
|
255
|
+
) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const fullPath = path.join(dir, entry);
|
|
259
|
+
try {
|
|
260
|
+
const stat = fs.statSync(fullPath);
|
|
261
|
+
if (stat.isDirectory()) {
|
|
262
|
+
walkAgentFiles(fullPath, fileList);
|
|
263
|
+
} else if (entry.endsWith(".md") || entry.endsWith(".json")) {
|
|
264
|
+
fileList.push(fullPath);
|
|
265
|
+
}
|
|
266
|
+
} catch {
|
|
267
|
+
// Skip
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} catch {
|
|
271
|
+
// Skip
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return fileList;
|
|
275
|
+
}
|
package/dist/commands/init.js
CHANGED
|
@@ -267,12 +267,13 @@ async function cmdInit(flags, quiet = false) {
|
|
|
267
267
|
console.log(drawRow(' Next Steps:', (0, logger_1.c)('gray', ' Next Steps:')));
|
|
268
268
|
console.log(stepRow('/generate', 'Generate code with reviews'));
|
|
269
269
|
console.log(stepRow('/review', 'Audit existing code for issues'));
|
|
270
|
-
console.log(stepRow('/tribunal-full', 'Run all
|
|
270
|
+
console.log(stepRow('/tribunal-full', 'Run all 19 reviewers in parallel'));
|
|
271
271
|
console.log(drawRow('', ''));
|
|
272
272
|
console.log(` ${(0, logger_1.c)(borderCol, '└' + '─'.repeat(W) + '┘')}`);
|
|
273
273
|
console.log();
|
|
274
274
|
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '✦ Generating IDE bridge files...')}`);
|
|
275
|
-
await generateIDEBridges(targetDir, agentDest, dryRun);
|
|
275
|
+
await generateIDEBridges(targetDir, agentDest, dryRun, isMinimal);
|
|
276
|
+
await scaffoldDesignSystem(targetDir, agentSrc, dryRun);
|
|
276
277
|
}
|
|
277
278
|
console.log();
|
|
278
279
|
}
|
|
@@ -286,8 +287,9 @@ async function cmdInit(flags, quiet = false) {
|
|
|
286
287
|
process.exit(1);
|
|
287
288
|
}
|
|
288
289
|
}
|
|
289
|
-
async function generateIDEBridges(targetDir, agentDest, dryRun = false) {
|
|
290
|
-
const
|
|
290
|
+
async function generateIDEBridges(targetDir, agentDest, dryRun = false, isMinimal = false) {
|
|
291
|
+
const rulesFilename = isMinimal ? 'kernel.md' : 'GEMINI.md';
|
|
292
|
+
const rulesFile = path_1.default.join(agentDest, 'rules', rulesFilename);
|
|
291
293
|
let rulesContent = '';
|
|
292
294
|
try {
|
|
293
295
|
rulesContent = await fs_1.default.promises.readFile(rulesFile, 'utf8');
|
|
@@ -317,21 +319,21 @@ async function generateIDEBridges(targetDir, agentDest, dryRun = false) {
|
|
|
317
319
|
// ── 1. Cursor (.cursorrules) ──────────────────────────
|
|
318
320
|
const cursorRules = `# Tribunal Kit — Cursor Bridge
|
|
319
321
|
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
320
|
-
# Source: .agent/rules
|
|
322
|
+
# Source: .agent/rules/${rulesFilename}
|
|
321
323
|
|
|
322
324
|
${rulesContent}
|
|
323
325
|
`;
|
|
324
326
|
// ── 2. Windsurf (.windsurfrules) ─────────────────────
|
|
325
327
|
const windsurfRules = `# Tribunal Kit — Windsurf Bridge
|
|
326
328
|
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
327
|
-
# Source: .agent/rules
|
|
329
|
+
# Source: .agent/rules/${rulesFilename}
|
|
328
330
|
|
|
329
331
|
${rulesContent}
|
|
330
332
|
`;
|
|
331
333
|
// ── 3. Gemini / Antigravity (.gemini/settings.json) ──
|
|
332
334
|
const geminiSettings = JSON.stringify({
|
|
333
335
|
"rules": [
|
|
334
|
-
{ "path":
|
|
336
|
+
{ "path": `../.agent/rules/${rulesFilename}`, "trigger": "always_on" }
|
|
335
337
|
],
|
|
336
338
|
"agents": { "directory": "../.agent/agents" },
|
|
337
339
|
"skills": { "directory": "../.agent/skills" },
|
|
@@ -344,21 +346,21 @@ trigger: always_on
|
|
|
344
346
|
|
|
345
347
|
# Tribunal Kit — Gemini Bridge
|
|
346
348
|
# Auto-generated by tribunal-kit init.
|
|
347
|
-
# Full rules: .agent/rules
|
|
349
|
+
# Full rules: .agent/rules/${rulesFilename}
|
|
348
350
|
|
|
349
351
|
${rulesContent}
|
|
350
352
|
`;
|
|
351
353
|
// ── 4. GitHub Copilot (.github/copilot-instructions.md) ──
|
|
352
354
|
const copilotInstructions = `# Tribunal Kit — Copilot Bridge
|
|
353
355
|
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
354
|
-
# Source: .agent/rules
|
|
356
|
+
# Source: .agent/rules/${rulesFilename}
|
|
355
357
|
|
|
356
358
|
${rulesContent}
|
|
357
359
|
`;
|
|
358
360
|
// ── 5. Claude (.claude/CLAUDE.md) ─────────────────────
|
|
359
361
|
const claudeRules = `# Tribunal Kit — Claude Bridge
|
|
360
362
|
# Auto-generated by tribunal-kit init. Do not edit manually.
|
|
361
|
-
# Source: .agent/rules
|
|
363
|
+
# Source: .agent/rules/${rulesFilename}
|
|
362
364
|
|
|
363
365
|
${rulesContent}
|
|
364
366
|
`;
|
|
@@ -374,4 +376,27 @@ ${rulesContent}
|
|
|
374
376
|
await Promise.all(bridges.map(b => writeBridge(b.path, b.content, b.label)));
|
|
375
377
|
console.log();
|
|
376
378
|
}
|
|
379
|
+
async function scaffoldDesignSystem(targetDir, agentSrc, dryRun = false) {
|
|
380
|
+
const designMdSrc = path_1.default.join(agentSrc, 'templates', 'DESIGN.md');
|
|
381
|
+
const designTokensSrc = path_1.default.join(agentSrc, 'templates', 'design-tokens.json');
|
|
382
|
+
const designMdDest = path_1.default.join(targetDir, 'DESIGN.md');
|
|
383
|
+
const designTokensDest = path_1.default.join(targetDir, 'design-tokens.json');
|
|
384
|
+
|
|
385
|
+
const copyIfMissing = async (src, dest, label) => {
|
|
386
|
+
if (!fs_1.default.existsSync(src)) return;
|
|
387
|
+
if (fs_1.default.existsSync(dest)) {
|
|
388
|
+
(0, logger_1.dbg)(` skip (exists): ${path_1.default.basename(dest)}`);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (dryRun) {
|
|
392
|
+
(0, logger_1.dbg)(` would create: ${dest}`);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
await fs_1.default.promises.copyFile(src, dest);
|
|
396
|
+
(0, logger_1.ok)(`${label} → ${(0, logger_1.c)('gray', path_1.default.relative(targetDir, dest))}`);
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
await copyIfMissing(designMdSrc, designMdDest, 'DESIGN.md System');
|
|
400
|
+
await copyIfMissing(designTokensSrc, designTokensDest, 'Design Tokens');
|
|
401
|
+
}
|
|
377
402
|
|