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/README.md CHANGED
@@ -7,8 +7,11 @@
7
7
  TRIBUNAL KIT
8
8
  </h1>
9
9
 
10
- <p style="font-size: 1.15em; color: #88888b; font-weight: 500; letter-spacing: 3px; margin: 10px 0 25px 0; text-transform: uppercase;">
11
- The Operating System for AI Software Engineering
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.0-ccff00?style=for-the-badge&color=111111&logo=github&logoColor=ccff00" alt="Release Version" />
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
- <!-- INTRO KEYNOTE -->
37
- <div style="background: linear-gradient(145deg, #111115, #16161c); border: 1px solid #22222a; border-radius: 12px; padding: 24px; margin-bottom: 40px; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);">
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;">Security Envelope</span>
40
- <strong style="color: #ffffff; font-size: 1.1em;">AI GENERATES CODE. TRIBUNAL KIT GOVERNS IT.</strong>
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
- A zero-bloat <strong>.agent/</strong> intelligence payload and <strong>Model Context Protocol (MCP) server</strong> that upgrades your IDEs (<a href="#" style="color: #ccff00; text-decoration: none;">Cursor</a>, <a href="#" style="color: #ccff00; text-decoration: none;">VSCode</a>, <a href="#" style="color: #ccff00; text-decoration: none;">Windsurf</a>) and terminal AI coding assistants (<a href="#" style="color: #ccff00; text-decoration: none;">Claude Code</a>, <a href="#" style="color: #ccff00; text-decoration: none;">Aider</a>) with <strong>51 specialist agents</strong>, <strong>37 workflows</strong>, <strong>171 reusable skills</strong>, and a parallel <strong>27-reviewer Tribunal pipeline</strong>. Establishes absolute runtime correctness, optimizes context windows, and heavily mitigates AI code hallucinations.
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="#-quick-start" style="color: #a0a0a5; text-decoration: none;">Quick Start (Set Up in Under 60 Seconds)</a></li>
60
- <li>👉 <a href="#-the-tribunal-pipeline" style="color: #a0a0a5; text-decoration: none;">The Tribunal Pipeline — Mitigating AI Code Hallucinations</a></li>
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="#-supreme-court-case-law--memory" style="color: #a0a0a5; text-decoration: none;">Supreme Court Case Law & Persistent Memory</a></li>
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
- ## 🛠️ Quick Start (Set Up in Under 60 Seconds)
203
+ ## 🛠️ Advanced Setup
188
204
 
189
- Get Tribunal Kit up and running in any project instantly:
205
+ Already ran `npx tribunal-kit init`? Here's how to go further:
190
206
 
191
207
  ```bash
192
- # 1. Initialize the intelligence payload
193
- npx tribunal-kit init
208
+ # Install Git pre-push governance hook
209
+ npx tribunal-kit hook
194
210
 
195
- # 2. Synchronize configuration bridges with Cursor / Windsurf / VSCode
196
- npx tribunal-kit sync
211
+ # Scan your workspace for AI hallucinations (phantom packages, unverified APIs)
212
+ npx tribunal-kit guardrail
197
213
 
198
- # 3. Verify project rule integrity
199
- npx tribunal-kit status
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
- > Run `npx tribunal-kit hook` to install a Git `pre-push` hook. This ensures your custom rules and agent configurations are auto-evolved and verified before code is pushed to your remote repository.
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
- | 5.x | ✅ Active support |
8
- | 4.x | ⚠️ Critical fixes only |
9
- | < 4.0 | ❌ End of life |
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: "2024-11-05",
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
- // Run synchronously by spawning a minimal script
341
- const result = spawnSync(
342
- process.execPath,
343
- [
344
- "-e",
345
- `
346
- const { generateIDEBridges } = require('${path.resolve(__dirname, "../dist/commands/init.js").replace(/\\/g, "\\\\")}');
347
- generateIDEBridges('${cwd.replace(/\\/g, "\\\\")}', '${agentDest.replace(/\\/g, "\\\\")}', false).then(() => console.log('Sync complete'));
348
- `,
349
- ],
350
- { encoding: "utf8", timeout: SPAWN_TIMEOUT_MS },
351
- );
352
- return {
353
- content: [
354
- {
355
- type: "text",
356
- text: result.stdout || result.stderr || "Sync complete",
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(process.cwd(), ".agent", "agents");
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(process.cwd(), ".agent", "agents");
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(process.cwd(), ".agent", "skills");
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(process.cwd(), ".agent", "skills");
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 = path.join(process.cwd(), ".agent");
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 = path.join(process.cwd(), ".agent");
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 = path.join(process.cwd(), ".agent");
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
- console.warn(
169
- "\x1b[93m⚠ Rust binary not found in target/. Falling back to JS engine.\x1b[0m",
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();
@@ -43,8 +43,9 @@ function acquireLock(agentDest) {
43
43
  if (err.code !== 'EEXIST') {
44
44
  throw err;
45
45
  }
46
- const start = Date.now();
47
- while (Date.now() - start < 50) {}
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 {
@@ -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
  };