tribunal-kit 6.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/.manifest.json +78 -0
- package/.agent/ARCHITECTURE.md +19 -244
- package/.agent/history/memory/.memory.idx +2185 -1
- package/.agent/history/memory/MEMORY.md +145 -1
- package/.agent/routing_index.json +3 -2
- package/.agent/rules/GEMINI.md +1 -1
- package/.agent/skill_topic_map.json +218 -0
- package/.agent/skills/agentic-workflows-2026/SKILL.md +76 -0
- package/.agent/skills/ai-app-hardening/SKILL.md +58 -0
- package/.agent/skills/context-engineering-pro/SKILL.md +69 -0
- package/.agent/skills/duckdb-analytical-sql/SKILL.md +55 -0
- package/.agent/skills/edge-ai-mobile/SKILL.md +46 -0
- package/.agent/skills/expo-router-v4/SKILL.md +80 -0
- package/.agent/skills/opentelemetry-observability/SKILL.md +58 -0
- package/.agent/skills/platform-engineering-opentofu/SKILL.md +67 -0
- package/.agent/skills/playwright-ai-e2e/SKILL.md +59 -0
- package/.agent/skills/property-based-testing/SKILL.md +60 -0
- package/.agent/skills/vector-search-pgvector/SKILL.md +77 -0
- package/.agent/skills/zero-trust-passkeys/SKILL.md +85 -0
- package/.agent/workflows/tribunal-full.md +13 -13
- package/README.md +79 -57
- package/SECURITY.md +3 -3
- package/bin/mcp-server.js +180 -34
- package/bin/wrapper.js +7 -4
- package/dist/cli.js +20 -0
- package/dist/commands/memory.js +3 -2
- package/dist/commands/native.js +36 -0
- package/dist/esm/index.mjs +32 -0
- package/dist/index.d.ts +50 -2
- package/package.json +15 -12
- package/scripts/sync-version.js +1 -1
package/README.md
CHANGED
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
TRIBUNAL KIT
|
|
8
8
|
</h1>
|
|
9
9
|
|
|
10
|
-
<p style="font-size: 1.
|
|
11
|
-
|
|
10
|
+
<p style="font-size: 1.35em; color: #ffffff; font-weight: 600; margin: 15px 0 8px 0;">
|
|
11
|
+
Your AI writes code that doesn't exist. Tribunal Kit stops it.
|
|
12
|
+
</p>
|
|
13
|
+
<p style="font-size: 0.95em; color: #88888b; font-weight: 400; letter-spacing: 1px; margin: 0 0 25px 0;">
|
|
14
|
+
The governance layer for AI coding agents — 51 specialists, 27 reviewers, Rust core.
|
|
12
15
|
</p>
|
|
13
16
|
|
|
14
17
|
<!-- BADGES -->
|
|
@@ -16,15 +19,28 @@
|
|
|
16
19
|
<a href="https://www.npmjs.com/package/tribunal-kit">
|
|
17
20
|
<img src="https://img.shields.io/npm/v/tribunal-kit?style=for-the-badge&logo=npm&logoColor=white&color=ff1637" alt="NPM Version" />
|
|
18
21
|
</a>
|
|
22
|
+
<a href="https://www.npmjs.com/package/tribunal-kit">
|
|
23
|
+
<img src="https://img.shields.io/npm/dw/tribunal-kit?style=for-the-badge&logo=npm&logoColor=white&color=1a1a1f&label=Downloads" alt="NPM Downloads" />
|
|
24
|
+
</a>
|
|
25
|
+
<a href="https://github.com/Harmitx7/tribunal-kit">
|
|
26
|
+
<img src="https://img.shields.io/github/stars/Harmitx7/tribunal-kit?style=for-the-badge&logo=github&logoColor=white&color=111111&label=Stars" alt="GitHub Stars" />
|
|
27
|
+
</a>
|
|
28
|
+
<a href="https://github.com/Harmitx7/tribunal-kit/actions/workflows/ci.yml">
|
|
29
|
+
<img src="https://img.shields.io/github/actions/workflow/status/Harmitx7/tribunal-kit/ci.yml?style=for-the-badge&logo=githubactions&logoColor=white&label=CI" alt="CI Status" />
|
|
30
|
+
</a>
|
|
31
|
+
<br>
|
|
19
32
|
<a href="LICENSE">
|
|
20
33
|
<img src="https://img.shields.io/badge/License-MIT-1a1a1f?style=for-the-badge&color=2d2d30" alt="License" />
|
|
21
34
|
</a>
|
|
22
35
|
<a href="CHANGELOG.md">
|
|
23
|
-
<img src="https://img.shields.io/badge/Release-v6.0.
|
|
36
|
+
<img src="https://img.shields.io/badge/Release-v6.0.1-ccff00?style=for-the-badge&color=111111&logo=github&logoColor=ccff00" alt="Release Version" />
|
|
24
37
|
</a>
|
|
25
38
|
<a href="mcp_config.json">
|
|
26
39
|
<img src="https://img.shields.io/badge/MCP-Ready-00c2ff?style=for-the-badge&logo=openai&logoColor=111" alt="MCP Server" />
|
|
27
40
|
</a>
|
|
41
|
+
<a href="package.json">
|
|
42
|
+
<img src="https://img.shields.io/badge/Dependencies-0-ccff00?style=for-the-badge&color=111111" alt="Zero Dependencies" />
|
|
43
|
+
</a>
|
|
28
44
|
<a href="SECURITY.md">
|
|
29
45
|
<img src="https://img.shields.io/badge/Security-Strict_Sandbox-ff1637?style=for-the-badge" alt="Security Policy" />
|
|
30
46
|
</a>
|
|
@@ -33,17 +49,53 @@
|
|
|
33
49
|
|
|
34
50
|
<br>
|
|
35
51
|
|
|
36
|
-
<!--
|
|
37
|
-
<div style="background: linear-gradient(145deg, #
|
|
52
|
+
<!-- THE PROBLEM -->
|
|
53
|
+
<div style="background: linear-gradient(145deg, #1a0a0a, #16161c); border: 1px solid #3a1a1a; border-radius: 12px; padding: 24px; margin-bottom: 20px;">
|
|
38
54
|
<div style="display: flex; align-items: center; margin-bottom: 12px;">
|
|
39
|
-
<span style="background-color: #ff1637; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.75em; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; margin-right: 10px;">
|
|
40
|
-
<strong style="color: #ffffff; font-size: 1.1em;">AI
|
|
55
|
+
<span style="background-color: #ff1637; color: white; padding: 4px 8px; border-radius: 4px; font-size: 0.75em; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; margin-right: 10px;">The Problem</span>
|
|
56
|
+
<strong style="color: #ffffff; font-size: 1.1em;">AI coding agents hallucinate. Constantly.</strong>
|
|
41
57
|
</div>
|
|
42
58
|
<p style="color: #c9c9d1; font-size: 0.95em; line-height: 1.6; margin: 0;">
|
|
43
|
-
|
|
59
|
+
They import packages that don't exist. They call API methods that were deprecated two versions ago. They forget your project conventions mid-conversation. They generate code that <em>looks</em> right but silently breaks at runtime. <strong>No linter catches this. No type-checker catches this.</strong> The hallucination happens at the semantic layer — and until now, nothing governed it.
|
|
44
60
|
</p>
|
|
45
61
|
</div>
|
|
46
62
|
|
|
63
|
+
<!-- THE SOLUTION -->
|
|
64
|
+
<div style="background: linear-gradient(145deg, #0a1a0a, #16161c); border: 1px solid #1a3a1a; border-radius: 12px; padding: 24px; margin-bottom: 40px;">
|
|
65
|
+
<div style="display: flex; align-items: center; margin-bottom: 12px;">
|
|
66
|
+
<span style="background-color: #ccff00; color: #111; padding: 4px 8px; border-radius: 4px; font-size: 0.75em; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; margin-right: 10px;">The Solution</span>
|
|
67
|
+
<strong style="color: #ffffff; font-size: 1.1em;">One command. Your AI stops lying.</strong>
|
|
68
|
+
</div>
|
|
69
|
+
<p style="color: #c9c9d1; font-size: 0.95em; line-height: 1.6; margin: 0 0 15px 0;">
|
|
70
|
+
Tribunal Kit wraps your coding agents in a <strong>neurosymbolic verification envelope</strong> — 51 specialist agents, 27 parallel reviewers, 183 reusable skills, and a compiled Rust core — that intercepts AI output, validates it against your actual codebase, and blocks hallucinated code before it reaches disk. Works with <strong>Cursor</strong>, <strong>VSCode</strong>, <strong>Windsurf</strong>, <strong>Claude Code</strong>, and <strong>Aider</strong>.
|
|
71
|
+
</p>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- QUICK INSTALL -->
|
|
75
|
+
```bash
|
|
76
|
+
npx tribunal-kit init # Install the governance layer (< 60 seconds)
|
|
77
|
+
npx tribunal-kit sync # Bridge with Cursor / Windsurf / VSCode
|
|
78
|
+
npx tribunal-kit status # Verify everything is locked in
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
<hr style="height: 1px; border: none; background: linear-gradient(to right, transparent, #33333f, transparent); margin: 40px 0;" />
|
|
82
|
+
|
|
83
|
+
<!-- WHAT YOU GET -->
|
|
84
|
+
|
|
85
|
+
### What's Inside
|
|
86
|
+
|
|
87
|
+
| Layer | Count | What It Does |
|
|
88
|
+
|:--|:--|:--|
|
|
89
|
+
| **Specialist Agents** | 51 | Domain-specific reasoning (frontend, backend, security, database, mobile, DevOps) |
|
|
90
|
+
| **Tribunal Reviewers** | 27 | Parallel code review pipeline that catches hallucinations before they ship |
|
|
91
|
+
| **Reusable Skills** | 183 | Deep knowledge packs (React 19, Next.js 15, Rust, Python, Vue, animations, a11y) |
|
|
92
|
+
| **Slash Workflows** | 37 | One-command operations (`/generate`, `/debug`, `/audit`, `/deploy`, `/refactor`) |
|
|
93
|
+
| **Rust Core** | 1 | Native binary for sub-50ms operations (hashing, dedup, DAG scheduling, compression) |
|
|
94
|
+
| **MCP Server** | 1 | Model Context Protocol integration for dynamic tool access |
|
|
95
|
+
| **Persistent Memory** | 4 types | Semantic, Procedural, Episodic, Working — survives across sessions |
|
|
96
|
+
| **Case Law Database** | ∞ | Records past AI mistakes as permanent precedents to prevent recurrence |
|
|
97
|
+
|
|
98
|
+
<br>
|
|
47
99
|
<hr style="height: 1px; border: none; background: linear-gradient(to right, transparent, #33333f, transparent); margin: 40px 0;" />
|
|
48
100
|
|
|
49
101
|
<!-- TABLE OF CONTENTS -->
|
|
@@ -53,15 +105,14 @@
|
|
|
53
105
|
</summary>
|
|
54
106
|
<div style="margin-top: 15px; padding-left: 10px;">
|
|
55
107
|
<ul style="list-style-type: none; padding-left: 0; line-height: 1.8;">
|
|
56
|
-
<li>👉 <a href="#-the-competitive-advantage" style="color: #a0a0a5; text-decoration: none;">Why Tribunal Kit? (The Competitive Advantage)</a></li>
|
|
57
108
|
<li>👉 <a href="#-comparative-analysis" style="color: #a0a0a5; text-decoration: none;">Comparative Analysis: Tribunal Kit vs. Alternatives</a></li>
|
|
58
109
|
<li>👉 <a href="#-state-of-the-art-performance-rust-core" style="color: #a0a0a5; text-decoration: none;">State-of-the-Art Performance (Rust Core)</a></li>
|
|
59
|
-
<li>👉 <a href="
|
|
60
|
-
<li>👉 <a href="
|
|
110
|
+
<li>👉 <a href="#%EF%B8%8F-advanced-setup" style="color: #a0a0a5; text-decoration: none;">Advanced Setup</a></li>
|
|
111
|
+
<li>👉 <a href="#%EF%B8%8F-the-tribunal-pipeline--mitigating-ai-code-hallucinations" style="color: #a0a0a5; text-decoration: none;">The Tribunal Pipeline — Mitigating AI Code Hallucinations</a></li>
|
|
61
112
|
<li>👉 <a href="#-omniscience-cognitive-alignment-engine-ocae" style="color: #a0a0a5; text-decoration: none;">Omniscience Cognitive Alignment Engine (OCAE)</a></li>
|
|
62
113
|
<li>👉 <a href="#-skillopt-autonomous-self-evolution-engine" style="color: #a0a0a5; text-decoration: none;">SkillOpt: Autonomous Self-Evolution Engine</a></li>
|
|
63
|
-
<li>👉 <a href="
|
|
64
|
-
<li>👉 <a href="#-the-marathon-harness" style="color: #a0a0a5; text-decoration: none;">The Marathon Harness — Long-Running Autonomy</a></li>
|
|
114
|
+
<li>👉 <a href="#%EF%B8%8F-supreme-court-case-law--memory" style="color: #a0a0a5; text-decoration: none;">Supreme Court Case Law & Persistent Memory</a></li>
|
|
115
|
+
<li>👉 <a href="#-the-marathon-harness--long-running-autonomy" style="color: #a0a0a5; text-decoration: none;">The Marathon Harness — Long-Running Autonomy</a></li>
|
|
65
116
|
<li>👉 <a href="#-mcp-server-integration" style="color: #a0a0a5; text-decoration: none;">Model Context Protocol (MCP) Server Integration</a></li>
|
|
66
117
|
<li>👉 <a href="#-cli-command-reference" style="color: #a0a0a5; text-decoration: none;">CLI Command Reference</a></li>
|
|
67
118
|
<li>👉 <a href="#-contributing--security" style="color: #a0a0a5; text-decoration: none;">Contributing & Security Guidelines</a></li>
|
|
@@ -69,42 +120,7 @@
|
|
|
69
120
|
</div>
|
|
70
121
|
</details>
|
|
71
122
|
|
|
72
|
-
<!-- SECTION 1 -->
|
|
73
|
-
## 🚀 The Competitive Advantage
|
|
74
|
-
|
|
75
|
-
Standard AI coding assistants generate code linearly, without validating semantic boundaries or architectural constraints. This leads to **hallucinations, token window inflation, amnesia across sessions, and instruction drift**.
|
|
76
|
-
|
|
77
|
-
Tribunal Kit wraps your coding agents in a **neurosymbolic verification envelope**. It intercepts agent outputs, runs them through parallel domain-specific reviewer swarms, enforces strict context budgeting, and uses a compiled Rust core to run self-evolution loops directly on your Git changes.
|
|
78
123
|
|
|
79
|
-
### Key Capabilities
|
|
80
|
-
|
|
81
|
-
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px;">
|
|
82
|
-
<div style="background: #111115; border: 1px solid #22222a; border-radius: 8px; padding: 20px;">
|
|
83
|
-
<div style="font-size: 1.5em; margin-bottom: 8px;">🛡️</div>
|
|
84
|
-
<h3 style="color: #ffffff; margin-top: 0;">Zero-Hallucination Guardrails</h3>
|
|
85
|
-
<p style="color: #a0a0a5; font-size: 0.9em; margin: 0; line-height: 1.5;">Enforces strict check gates (<kbd>tk guardrail</kbd>) verifying that file links, count metrics, and package imports exist before code reaches disk.</p>
|
|
86
|
-
</div>
|
|
87
|
-
<div style="background: #111115; border: 1px solid #22222a; border-radius: 8px; padding: 20px;">
|
|
88
|
-
<div style="font-size: 1.5em; margin-bottom: 8px;">🧬</div>
|
|
89
|
-
<h3 style="color: #ffffff; margin-top: 0;">SkillOpt Self-Evolution</h3>
|
|
90
|
-
<p style="color: #a0a0a5; font-size: 0.9em; margin: 0; line-height: 1.5;">Optimizes your <code>.agent</code> instruction files automatically using a multi-epoch genetic evolution loop with candidate grading and Levenshtein deduplication.</p>
|
|
91
|
-
</div>
|
|
92
|
-
<div style="background: #111115; border: 1px solid #22222a; border-radius: 8px; padding: 20px;">
|
|
93
|
-
<div style="font-size: 1.5em; margin-bottom: 8px;">🎯</div>
|
|
94
|
-
<h3 style="color: #ffffff; margin-top: 0;">Fabel-5 Output Alignment</h3>
|
|
95
|
-
<p style="color: #a0a0a5; font-size: 0.9em; margin: 0; line-height: 1.5;">Programmatically aligns AI outputs to clean prose paragraphs, stripping conversational slop and catching known framework traps (Next.js 15 route headers, React 19 hooks, Drizzle ORM filters).</p>
|
|
96
|
-
</div>
|
|
97
|
-
<div style="background: #111115; border: 1px solid #22222a; border-radius: 8px; padding: 20px;">
|
|
98
|
-
<div style="font-size: 1.5em; margin-bottom: 8px;">🧠</div>
|
|
99
|
-
<h3 style="color: #ffffff; margin-top: 0;">4-Type Persistent Memory</h3>
|
|
100
|
-
<p style="color: #a0a0a5; font-size: 0.9em; margin: 0; line-height: 1.5;">Separates memory into Semantic, Procedural, Episodic, and Working categories to prevent context decay and model amnesia.</p>
|
|
101
|
-
</div>
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
<br>
|
|
105
|
-
<hr style="height: 1px; border: none; background: linear-gradient(to right, transparent, #33333f, transparent); margin: 40px 0;" />
|
|
106
|
-
|
|
107
|
-
<!-- SECTION 2 -->
|
|
108
124
|
## 📈 Comparative Analysis
|
|
109
125
|
|
|
110
126
|
AI engineering requires more than static template rules or raw linters. See how Tribunal Kit stacks up against alternatives:
|
|
@@ -184,23 +200,29 @@ Tribunal Kit v6 splits heavy computational tasks between a native Rust core and
|
|
|
184
200
|
<br>
|
|
185
201
|
|
|
186
202
|
<!-- SECTION 4 -->
|
|
187
|
-
## 🛠️
|
|
203
|
+
## 🛠️ Advanced Setup
|
|
188
204
|
|
|
189
|
-
|
|
205
|
+
Already ran `npx tribunal-kit init`? Here's how to go further:
|
|
190
206
|
|
|
191
207
|
```bash
|
|
192
|
-
#
|
|
193
|
-
npx tribunal-kit
|
|
208
|
+
# Install Git pre-push governance hook
|
|
209
|
+
npx tribunal-kit hook
|
|
194
210
|
|
|
195
|
-
#
|
|
196
|
-
npx tribunal-kit
|
|
211
|
+
# Scan your workspace for AI hallucinations (phantom packages, unverified APIs)
|
|
212
|
+
npx tribunal-kit guardrail
|
|
197
213
|
|
|
198
|
-
#
|
|
199
|
-
npx tribunal-kit
|
|
214
|
+
# Record an AI coding mistake as permanent precedent (case law)
|
|
215
|
+
npx tribunal-kit case add
|
|
216
|
+
|
|
217
|
+
# Optimize a skill file using the SkillOpt evolution engine
|
|
218
|
+
tk optimize-skill --target ./skills/auth-security.md "npm run test:auth" --epochs 5
|
|
200
219
|
```
|
|
201
220
|
|
|
202
221
|
> [!TIP]
|
|
203
|
-
>
|
|
222
|
+
> The `tk hook` command installs a Git `pre-push` hook that auto-runs `tk guardrail` before every push — catching hallucinated imports and unverified APIs before they reach your remote.
|
|
223
|
+
|
|
224
|
+
> [!NOTE]
|
|
225
|
+
> **MCP Server**: To connect Tribunal Kit to Cursor, VSCode, or Claude Desktop as an MCP server, see the [MCP Server Integration](#-mcp-server-integration) section below.
|
|
204
226
|
|
|
205
227
|
<br>
|
|
206
228
|
<hr style="height: 1px; border: none; background: linear-gradient(to right, transparent, #33333f, transparent); margin: 40px 0;" />
|
package/SECURITY.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
| ------- | ------------------ |
|
|
7
|
-
|
|
|
8
|
-
|
|
|
9
|
-
| <
|
|
7
|
+
| 6.x | ✅ Active support |
|
|
8
|
+
| 5.x | ⚠️ Critical fixes only |
|
|
9
|
+
| < 5.0 | ❌ End of life |
|
|
10
10
|
|
|
11
11
|
## Reporting a Vulnerability
|
|
12
12
|
|
package/bin/mcp-server.js
CHANGED
|
@@ -110,24 +110,26 @@ function stripBoilerplate(text) {
|
|
|
110
110
|
return minified.trim();
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
function getAgentDir() {
|
|
114
|
+
const fs = require("fs");
|
|
115
|
+
const local = path.join(process.cwd(), ".agent");
|
|
116
|
+
if (fs.existsSync(local)) return local;
|
|
117
|
+
return path.resolve(__dirname, "../.agent");
|
|
118
|
+
}
|
|
119
|
+
|
|
113
120
|
function handleRequest(req) {
|
|
121
|
+
const fs = require("fs");
|
|
114
122
|
if (req.method === "notifications/initialized" || req.method === "notifications/cancelled") {
|
|
115
123
|
return null;
|
|
116
124
|
}
|
|
117
125
|
if (req.method === "ping") {
|
|
118
126
|
return {};
|
|
119
127
|
}
|
|
120
|
-
if (req.method === "resources/list") {
|
|
121
|
-
return { resources: [] };
|
|
122
|
-
}
|
|
123
|
-
if (req.method === "prompts/list") {
|
|
124
|
-
return { prompts: [] };
|
|
125
|
-
}
|
|
126
128
|
|
|
127
129
|
// MCP spec: method names follow path-style convention
|
|
128
130
|
if (req.method === "initialize") {
|
|
129
131
|
return {
|
|
130
|
-
protocolVersion: "
|
|
132
|
+
protocolVersion: "2025-03-26",
|
|
131
133
|
capabilities: {
|
|
132
134
|
tools: {},
|
|
133
135
|
resources: { subscribe: false, listChanged: false },
|
|
@@ -140,6 +142,148 @@ function handleRequest(req) {
|
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
144
|
|
|
145
|
+
if (req.method === "resources/list") {
|
|
146
|
+
const agentDir = getAgentDir();
|
|
147
|
+
const resources = [];
|
|
148
|
+
|
|
149
|
+
// Agents
|
|
150
|
+
const agentsDir = path.join(agentDir, "agents");
|
|
151
|
+
if (fs.existsSync(agentsDir)) {
|
|
152
|
+
const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md"));
|
|
153
|
+
for (const f of files) {
|
|
154
|
+
const name = path.basename(f, ".md");
|
|
155
|
+
resources.push({
|
|
156
|
+
uri: `tribunal://agent/${name}`,
|
|
157
|
+
name: `Agent: ${name}`,
|
|
158
|
+
description: `Tribunal Specialist Agent rule file for ${name}`,
|
|
159
|
+
mimeType: "text/markdown",
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Skills
|
|
165
|
+
const skillsDir = path.join(agentDir, "skills");
|
|
166
|
+
if (fs.existsSync(skillsDir)) {
|
|
167
|
+
const dirs = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
168
|
+
for (const d of dirs) {
|
|
169
|
+
if (d.isDirectory()) {
|
|
170
|
+
const skillFile = path.join(skillsDir, d.name, "SKILL.md");
|
|
171
|
+
if (fs.existsSync(skillFile)) {
|
|
172
|
+
resources.push({
|
|
173
|
+
uri: `tribunal://skill/${d.name}`,
|
|
174
|
+
name: `Skill: ${d.name}`,
|
|
175
|
+
description: `Tribunal Skill instruction file for ${d.name}`,
|
|
176
|
+
mimeType: "text/markdown",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Workflows
|
|
184
|
+
const workflowsDir = path.join(agentDir, "workflows");
|
|
185
|
+
if (fs.existsSync(workflowsDir)) {
|
|
186
|
+
const files = fs.readdirSync(workflowsDir).filter((f) => f.endsWith(".md"));
|
|
187
|
+
for (const f of files) {
|
|
188
|
+
const name = path.basename(f, ".md");
|
|
189
|
+
resources.push({
|
|
190
|
+
uri: `tribunal://workflow/${name}`,
|
|
191
|
+
name: `Workflow: ${name}`,
|
|
192
|
+
description: `Tribunal Workflow guide for ${name}`,
|
|
193
|
+
mimeType: "text/markdown",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return { resources };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (req.method === "resources/read") {
|
|
202
|
+
const uri = req.params && req.params.uri;
|
|
203
|
+
if (!uri) throw new Error("Missing uri parameter");
|
|
204
|
+
const agentDir = getAgentDir();
|
|
205
|
+
let filePath = null;
|
|
206
|
+
|
|
207
|
+
if (uri.startsWith("tribunal://agent/")) {
|
|
208
|
+
const name = uri.replace("tribunal://agent/", "");
|
|
209
|
+
filePath = path.join(agentDir, "agents", `${name}.md`);
|
|
210
|
+
} else if (uri.startsWith("tribunal://skill/")) {
|
|
211
|
+
const name = uri.replace("tribunal://skill/", "");
|
|
212
|
+
filePath = path.join(agentDir, "skills", name, "SKILL.md");
|
|
213
|
+
} else if (uri.startsWith("tribunal://workflow/")) {
|
|
214
|
+
const name = uri.replace("tribunal://workflow/", "");
|
|
215
|
+
filePath = path.join(agentDir, "workflows", `${name}.md`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!filePath || !fs.existsSync(filePath)) {
|
|
219
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const text = fs.readFileSync(filePath, "utf8");
|
|
223
|
+
return {
|
|
224
|
+
contents: [
|
|
225
|
+
{
|
|
226
|
+
uri,
|
|
227
|
+
mimeType: "text/markdown",
|
|
228
|
+
text,
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (req.method === "prompts/list") {
|
|
235
|
+
const agentDir = getAgentDir();
|
|
236
|
+
const prompts = [];
|
|
237
|
+
const workflowsDir = path.join(agentDir, "workflows");
|
|
238
|
+
|
|
239
|
+
if (fs.existsSync(workflowsDir)) {
|
|
240
|
+
const files = fs.readdirSync(workflowsDir).filter((f) => f.endsWith(".md"));
|
|
241
|
+
for (const f of files) {
|
|
242
|
+
const name = path.basename(f, ".md");
|
|
243
|
+
prompts.push({
|
|
244
|
+
name,
|
|
245
|
+
description: `Execute tribunal workflow /${name}`,
|
|
246
|
+
arguments: [
|
|
247
|
+
{
|
|
248
|
+
name: "task",
|
|
249
|
+
description: "The task or target file to execute the workflow against",
|
|
250
|
+
required: false,
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return { prompts };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (req.method === "prompts/get") {
|
|
261
|
+
const name = req.params && req.params.name;
|
|
262
|
+
const task = (req.params && req.params.arguments && req.params.arguments.task) || "";
|
|
263
|
+
if (!name) throw new Error("Missing prompt name parameter");
|
|
264
|
+
|
|
265
|
+
const agentDir = getAgentDir();
|
|
266
|
+
const workflowPath = path.join(agentDir, "workflows", `${name}.md`);
|
|
267
|
+
if (!fs.existsSync(workflowPath)) {
|
|
268
|
+
throw new Error(`Prompt workflow not found: ${name}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const content = fs.readFileSync(workflowPath, "utf8");
|
|
272
|
+
const promptText = task ? `${content}\n\nTarget Task/File: ${task}` : content;
|
|
273
|
+
|
|
274
|
+
return {
|
|
275
|
+
messages: [
|
|
276
|
+
{
|
|
277
|
+
role: "user",
|
|
278
|
+
content: {
|
|
279
|
+
type: "text",
|
|
280
|
+
text: promptText,
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
143
287
|
if (req.method === "tools/list") {
|
|
144
288
|
return {
|
|
145
289
|
tools: [
|
|
@@ -337,26 +481,28 @@ function handleRequest(req) {
|
|
|
337
481
|
],
|
|
338
482
|
};
|
|
339
483
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
484
|
+
try {
|
|
485
|
+
const { generateIDEBridges } = require(path.resolve(__dirname, "../dist/commands/init.js"));
|
|
486
|
+
// generateIDEBridges is async — execute synchronously in MCP context
|
|
487
|
+
generateIDEBridges(cwd, agentDest, true).then(() => {}).catch(() => {});
|
|
488
|
+
return {
|
|
489
|
+
content: [
|
|
490
|
+
{
|
|
491
|
+
type: "text",
|
|
492
|
+
text: "Sync complete",
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
};
|
|
496
|
+
} catch (e) {
|
|
497
|
+
return {
|
|
498
|
+
content: [
|
|
499
|
+
{
|
|
500
|
+
type: "text",
|
|
501
|
+
text: `Sync failed: ${e.message}`,
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
};
|
|
505
|
+
}
|
|
360
506
|
}
|
|
361
507
|
|
|
362
508
|
if (toolName === "search_case_law") {
|
|
@@ -374,7 +520,7 @@ function handleRequest(req) {
|
|
|
374
520
|
|
|
375
521
|
if (toolName === "list_tribunal_agents") {
|
|
376
522
|
const fs = require("fs");
|
|
377
|
-
const agentDir = path.join(
|
|
523
|
+
const agentDir = path.join(getAgentDir(), "agents");
|
|
378
524
|
if (!fs.existsSync(agentDir)) return { content: [{ type: "text", text: "No agents found or .agent directory missing." }] };
|
|
379
525
|
const agents = fs.readdirSync(agentDir).filter(f => f.endsWith('.md')).map(f => f.replace('.md', ''));
|
|
380
526
|
return { content: [{ type: "text", text: "Available Agents:\n- " + agents.join("\n- ") }] };
|
|
@@ -385,7 +531,7 @@ function handleRequest(req) {
|
|
|
385
531
|
const name = req.params?.arguments?.name;
|
|
386
532
|
if (!name || typeof name !== "string") throw { code: -32602, message: "Missing or invalid argument: name (string)" };
|
|
387
533
|
const sanitizedName = path.basename(name);
|
|
388
|
-
const agentsDir = path.resolve(
|
|
534
|
+
const agentsDir = path.resolve(getAgentDir(), "agents");
|
|
389
535
|
const agentPath = path.resolve(agentsDir, `${sanitizedName}.md`);
|
|
390
536
|
// Path containment: ensure resolved path stays within agents directory
|
|
391
537
|
if (!agentPath.startsWith(agentsDir)) throw { code: -32602, message: "Invalid agent name: path traversal detected" };
|
|
@@ -396,7 +542,7 @@ function handleRequest(req) {
|
|
|
396
542
|
|
|
397
543
|
if (toolName === "list_tribunal_skills") {
|
|
398
544
|
const fs = require("fs");
|
|
399
|
-
const skillsDir = path.join(
|
|
545
|
+
const skillsDir = path.join(getAgentDir(), "skills");
|
|
400
546
|
if (!fs.existsSync(skillsDir)) return { content: [{ type: "text", text: "No skills found or .agent directory missing." }] };
|
|
401
547
|
const skills = fs.readdirSync(skillsDir, { withFileTypes: true }).filter(d => d.isDirectory()).map(d => d.name);
|
|
402
548
|
return { content: [{ type: "text", text: "Available Skills:\n- " + skills.join("\n- ") }] };
|
|
@@ -407,7 +553,7 @@ function handleRequest(req) {
|
|
|
407
553
|
const name = req.params?.arguments?.name;
|
|
408
554
|
if (!name || typeof name !== "string") throw { code: -32602, message: "Missing or invalid argument: name (string)" };
|
|
409
555
|
const sanitizedName = path.basename(name);
|
|
410
|
-
const skillsDir = path.resolve(
|
|
556
|
+
const skillsDir = path.resolve(getAgentDir(), "skills");
|
|
411
557
|
const skillPath = path.resolve(skillsDir, sanitizedName, "SKILL.md");
|
|
412
558
|
// Path containment: ensure resolved path stays within skills directory
|
|
413
559
|
if (!skillPath.startsWith(skillsDir)) throw { code: -32602, message: "Invalid skill name: path traversal detected" };
|
|
@@ -423,7 +569,7 @@ function handleRequest(req) {
|
|
|
423
569
|
|
|
424
570
|
if (!task) throw { code: -32602, message: "Missing required argument: task" };
|
|
425
571
|
|
|
426
|
-
const agentDest =
|
|
572
|
+
const agentDest = getAgentDir();
|
|
427
573
|
const fs = require("fs");
|
|
428
574
|
if (!fs.existsSync(agentDest)) {
|
|
429
575
|
return { content: [{ type: "text", text: "Error: .agent/ directory not found. Run `tk init` first." }] };
|
|
@@ -445,7 +591,7 @@ function handleRequest(req) {
|
|
|
445
591
|
throw { code: -32602, message: "Missing or invalid required argument: query (string)" };
|
|
446
592
|
}
|
|
447
593
|
const budget = req.params?.arguments?.budget || 2000;
|
|
448
|
-
const agentDest =
|
|
594
|
+
const agentDest = getAgentDir();
|
|
449
595
|
const fs = require("fs");
|
|
450
596
|
if (!fs.existsSync(agentDest)) {
|
|
451
597
|
return { content: [{ type: "text", text: "Error: .agent/ directory not found. Run `tk init` first." }] };
|
|
@@ -479,7 +625,7 @@ function handleRequest(req) {
|
|
|
479
625
|
if (!validTypes.includes(memType)) {
|
|
480
626
|
throw { code: -32602, message: `Invalid memory type: "${memType}". Must be one of: ${validTypes.join(", ")}` };
|
|
481
627
|
}
|
|
482
|
-
const agentDest =
|
|
628
|
+
const agentDest = getAgentDir();
|
|
483
629
|
const fs = require("fs");
|
|
484
630
|
if (!fs.existsSync(agentDest)) {
|
|
485
631
|
return { content: [{ type: "text", text: "Error: .agent/ directory not found. Run `tk init` first." }] };
|
package/bin/wrapper.js
CHANGED
|
@@ -26,6 +26,7 @@ const RUST_COMMANDS = new Set([
|
|
|
26
26
|
"context-compress",
|
|
27
27
|
"context-broker",
|
|
28
28
|
"optimize-step",
|
|
29
|
+
"impact-tier",
|
|
29
30
|
]);
|
|
30
31
|
|
|
31
32
|
|
|
@@ -164,10 +165,12 @@ function main() {
|
|
|
164
165
|
}
|
|
165
166
|
// rustResult === false means spawn error; fall through to JS fallback
|
|
166
167
|
} else {
|
|
167
|
-
// Warn if Rust command was requested but binary is missing
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
// Warn if Rust command was requested but binary is missing (in verbose mode)
|
|
169
|
+
if (process.env.TK_VERBOSE || process.env.VERBOSE) {
|
|
170
|
+
console.warn(
|
|
171
|
+
"\x1b[93m⚠ Rust binary not found in target/. Falling back to JS engine.\x1b[0m",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
171
174
|
}
|
|
172
175
|
}
|
|
173
176
|
|
package/dist/cli.js
CHANGED
|
@@ -42,6 +42,15 @@ function parseArgs(argv) {
|
|
|
42
42
|
args.flags.minimal = true;
|
|
43
43
|
continue;
|
|
44
44
|
}
|
|
45
|
+
if (arg.startsWith('--profile=')) {
|
|
46
|
+
args.flags.profile = arg.split('=').slice(1).join('=');
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (arg === '--profile') {
|
|
50
|
+
const idx = raw.indexOf('--profile');
|
|
51
|
+
args.flags.profile = raw[idx + 1] || 'full';
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
45
54
|
if (arg === '--skip-update-check') {
|
|
46
55
|
args.flags.skipUpdateCheck = true;
|
|
47
56
|
continue;
|
|
@@ -112,6 +121,7 @@ function cmdHelp(quiet = false) {
|
|
|
112
121
|
(0, logger_1.log)(cmd('context-compress', 'Compress a context file while retaining VERIFY comments'));
|
|
113
122
|
(0, logger_1.log)(cmd('optimize-step', 'Apply bounded SkillOpt edits from a JSON payload'));
|
|
114
123
|
(0, logger_1.log)(cmd('guardrail', 'Validate .agent/ integrity (phantom refs, count mismatches, drift)'));
|
|
124
|
+
(0, logger_1.log)(cmd('impact-tier', 'Classify task governance impact tier (0-3)'));
|
|
115
125
|
(0, logger_1.log)(cmd('uninstall', 'Remove .agent/ folder from project'));
|
|
116
126
|
console.log();
|
|
117
127
|
(0, logger_1.log)((0, logger_1.bold)(' Options'));
|
|
@@ -126,6 +136,7 @@ function cmdHelp(quiet = false) {
|
|
|
126
136
|
(0, logger_1.log)(opt('--skip-update-check', 'Skip auto-update version check'));
|
|
127
137
|
(0, logger_1.log)(opt('--head', '(learn) Diff against last commit instead of staged'));
|
|
128
138
|
(0, logger_1.log)(opt('--write', '(align) Write aligned output in-place to the target file'));
|
|
139
|
+
(0, logger_1.log)(opt('--version, -v', 'Print installed version'));
|
|
129
140
|
console.log();
|
|
130
141
|
(0, logger_1.log)((0, logger_1.bold)(' Aliases'));
|
|
131
142
|
(0, logger_1.log)(` ${(0, logger_1.c)('gray', '─'.repeat(40))}`);
|
|
@@ -302,12 +313,21 @@ async function runWithUpdateCheck(command, flags) {
|
|
|
302
313
|
cmdOptimizeStep(process.argv, quiet);
|
|
303
314
|
break;
|
|
304
315
|
}
|
|
316
|
+
case 'impact-tier': {
|
|
317
|
+
const cmdImpactTier = loadCmd('./commands/native', 'cmdImpactTier');
|
|
318
|
+
cmdImpactTier(process.argv, quiet);
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
305
321
|
case 'help':
|
|
306
322
|
case '--help':
|
|
307
323
|
case '-h':
|
|
308
324
|
case null:
|
|
309
325
|
cmdHelp(quiet);
|
|
310
326
|
break;
|
|
327
|
+
case '--version':
|
|
328
|
+
case '-v':
|
|
329
|
+
(0, logger_1.log)(CURRENT_VERSION);
|
|
330
|
+
break;
|
|
311
331
|
default:
|
|
312
332
|
(0, logger_1.err)(`Unknown command: "${command}"`);
|
|
313
333
|
console.log();
|
package/dist/commands/memory.js
CHANGED
|
@@ -43,8 +43,9 @@ function acquireLock(agentDest) {
|
|
|
43
43
|
if (err.code !== 'EEXIST') {
|
|
44
44
|
throw err;
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
// Non-blocking sleep — avoids busy-wait event loop blocking
|
|
47
|
+
const waitBuf = new Int32Array(new SharedArrayBuffer(4));
|
|
48
|
+
Atomics.wait(waitBuf, 0, 0, 50);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
try {
|
package/dist/commands/native.js
CHANGED
|
@@ -219,10 +219,46 @@ function cmdOptimizeStep(processArgs, quiet = false) {
|
|
|
219
219
|
console.log(JSON.stringify(result));
|
|
220
220
|
return true;
|
|
221
221
|
}
|
|
222
|
+
function cmdImpactTier(processArgs, quiet = false) {
|
|
223
|
+
const args = processArgs.slice(3);
|
|
224
|
+
const files = getOption(args, ["--files"]) || "";
|
|
225
|
+
const lines = parseInt(getOption(args, ["--lines"]) || "0", 10);
|
|
226
|
+
const task = getOption(args, ["--task"]) || "";
|
|
227
|
+
|
|
228
|
+
const fileList = files ? files.split(",").map(f => f.trim()).filter(Boolean) : [];
|
|
229
|
+
const fileCount = fileList.length;
|
|
230
|
+
|
|
231
|
+
// Tier classification heuristics (mirrors Rust ImpactTier logic)
|
|
232
|
+
let tier = 0;
|
|
233
|
+
if (fileCount === 0 && lines <= 5) tier = 0;
|
|
234
|
+
else if (fileCount <= 1 && lines <= 50) tier = 1;
|
|
235
|
+
else if (fileCount <= 5 && lines <= 200) tier = 2;
|
|
236
|
+
else tier = 3;
|
|
237
|
+
|
|
238
|
+
// Check for high-risk patterns that force Tier 3
|
|
239
|
+
const highRiskPatterns = /\b(auth|migration|schema|security|password|token|jwt|rbac|permissions)\b/i;
|
|
240
|
+
const highRiskExtensions = /\.(sql|prisma|tf|tofu)$/i;
|
|
241
|
+
if (highRiskPatterns.test(task) || fileList.some(f => highRiskExtensions.test(f))) {
|
|
242
|
+
tier = Math.max(tier, 3);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const tierNames = ["Fast-Pass", "Express Pass", "Targeted Audit", "Full Gauntlet"];
|
|
246
|
+
const result = {
|
|
247
|
+
tier,
|
|
248
|
+
tier_name: tierNames[tier],
|
|
249
|
+
file_count: fileCount,
|
|
250
|
+
line_count: lines,
|
|
251
|
+
socratic_gate: tier >= 3 ? "required" : tier >= 2 ? "conditional" : "bypass",
|
|
252
|
+
};
|
|
253
|
+
if (!quiet) console.error(`✓ Impact Tier: ${tier} (${tierNames[tier]})`);
|
|
254
|
+
console.log(JSON.stringify(result));
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
222
257
|
|
|
223
258
|
module.exports = {
|
|
224
259
|
cmdMinContext,
|
|
225
260
|
cmdDagSchedule,
|
|
226
261
|
cmdContextCompress,
|
|
227
262
|
cmdOptimizeStep,
|
|
263
|
+
cmdImpactTier,
|
|
228
264
|
};
|