tribunal-kit 5.8.2 → 5.8.4

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.
Files changed (101) hide show
  1. package/.agent/ARCHITECTURE.md +12 -12
  2. package/.agent/agents/complexity-reviewer.md +53 -0
  3. package/.agent/agents/precedence-reviewer.md +12 -12
  4. package/.agent/agents/swarm-worker-registry.md +3 -3
  5. package/.agent/history/integrity_manifest.json +958 -0
  6. package/.agent/history/memory/.memory.idx +305 -1
  7. package/.agent/history/memory/MEMORY.md +21 -1
  8. package/.agent/rules/GEMINI.md +31 -28
  9. package/.agent/scripts/case_law_manager.js +3 -15
  10. package/.agent/scripts/context_broker.js +3 -1
  11. package/.agent/scripts/guardrail_engine.js +643 -0
  12. package/.agent/scripts/integrity_manifest.js +486 -0
  13. package/.agent/scripts/signal_detector.js +1 -1
  14. package/.agent/scripts/skill_evolution.js +3 -15
  15. package/.agent/scripts/skill_integrator.js +2 -12
  16. package/.agent/scripts/swarm_dispatcher.js +2 -12
  17. package/.agent/skills/12-principles-of-animation/SKILL.md +69 -0
  18. package/.agent/skills/60fps-animation/SKILL.md +78 -0
  19. package/.agent/skills/accessible-animation/SKILL.md +86 -0
  20. package/.agent/skills/adapt/SKILL.md +75 -0
  21. package/.agent/skills/animation-on-scroll/SKILL.md +110 -0
  22. package/.agent/skills/animation-systems/SKILL.md +69 -0
  23. package/.agent/skills/antfu-conventions/SKILL.md +74 -0
  24. package/.agent/skills/app-builder/SKILL.md +1 -1
  25. package/.agent/skills/apple-design/SKILL.md +108 -0
  26. package/.agent/skills/audit-and-fix/SKILL.md +83 -0
  27. package/.agent/skills/baseline-ui/SKILL.md +74 -0
  28. package/.agent/skills/better-colors/SKILL.md +124 -0
  29. package/.agent/skills/better-typography/SKILL.md +111 -0
  30. package/.agent/skills/better-ui/SKILL.md +102 -0
  31. package/.agent/skills/bolder/SKILL.md +68 -0
  32. package/.agent/skills/build-primitive/SKILL.md +70 -0
  33. package/.agent/skills/clarify/SKILL.md +75 -0
  34. package/.agent/skills/cobejs/SKILL.md +96 -0
  35. package/.agent/skills/codebase-design/SKILL.md +84 -0
  36. package/.agent/skills/colorize/SKILL.md +77 -0
  37. package/.agent/skills/compact-landing/SKILL.md +70 -0
  38. package/.agent/skills/company-logos/SKILL.md +73 -0
  39. package/.agent/skills/create-design-md/SKILL.md +104 -0
  40. package/.agent/skills/critique/SKILL.md +95 -0
  41. package/.agent/skills/delight/SKILL.md +65 -0
  42. package/.agent/skills/design-lab/SKILL.md +59 -0
  43. package/.agent/skills/diagnosing-bugs/SKILL.md +190 -0
  44. package/.agent/skills/distill/SKILL.md +65 -0
  45. package/.agent/skills/domain-modeling/SKILL.md +78 -0
  46. package/.agent/skills/fixing-accessibility/SKILL.md +98 -0
  47. package/.agent/skills/fixing-metadata/SKILL.md +97 -0
  48. package/.agent/skills/fixing-motion-performance/SKILL.md +96 -0
  49. package/.agent/skills/gpt-taste/SKILL.md +68 -0
  50. package/.agent/skills/harden/SKILL.md +74 -0
  51. package/.agent/skills/impeccable/SKILL.md +72 -0
  52. package/.agent/skills/improve-codebase-architecture/SKILL.md +67 -0
  53. package/.agent/skills/improve-ui/SKILL.md +83 -0
  54. package/.agent/skills/landing-page/SKILL.md +88 -0
  55. package/.agent/skills/lint-and-validate/SKILL.md +1 -2
  56. package/.agent/skills/local-first-architecture/SKILL.md +66 -0
  57. package/.agent/skills/lottie-animation/SKILL.md +82 -0
  58. package/.agent/skills/marquee-loop/SKILL.md +96 -0
  59. package/.agent/skills/masked-reveal/SKILL.md +88 -0
  60. package/.agent/skills/micro-interaction/SKILL.md +100 -0
  61. package/.agent/skills/morphing-icons/SKILL.md +85 -0
  62. package/.agent/skills/page-transition-animation/SKILL.md +108 -0
  63. package/.agent/skills/parallel-agents/SKILL.md +5 -5
  64. package/.agent/skills/polish/SKILL.md +63 -0
  65. package/.agent/skills/pricing-page/SKILL.md +68 -0
  66. package/.agent/skills/progressive-blur/SKILL.md +100 -0
  67. package/.agent/skills/project-idioms/SKILL.md +7 -7
  68. package/.agent/skills/quieter/SKILL.md +68 -0
  69. package/.agent/skills/react-doctor/SKILL.md +70 -0
  70. package/.agent/skills/redesign-skill/SKILL.md +65 -0
  71. package/.agent/skills/shape/SKILL.md +73 -0
  72. package/.agent/skills/soft-skill/SKILL.md +72 -0
  73. package/.agent/skills/sounds-on-the-web/SKILL.md +100 -0
  74. package/.agent/skills/svg-animation/SKILL.md +91 -0
  75. package/.agent/skills/swiss-design/SKILL.md +64 -0
  76. package/.agent/skills/taste-skill/SKILL.md +71 -0
  77. package/.agent/skills/tdd-workflow/SKILL.md +36 -165
  78. package/.agent/skills/test-result-analyzer/SKILL.md +1 -1
  79. package/.agent/skills/thermo-nuclear-code-quality-review/SKILL.md +82 -0
  80. package/.agent/skills/to-spring-or-not-to-spring/SKILL.md +66 -0
  81. package/.agent/skills/transitions-dev/SKILL.md +101 -0
  82. package/.agent/skills/typeset/SKILL.md +76 -0
  83. package/.agent/skills/ui-skills-root/SKILL.md +85 -0
  84. package/.agent/skills/web-quality-audit/SKILL.md +67 -0
  85. package/.agent/workflows/fix.md +2 -2
  86. package/.agent/workflows/preview.md +5 -5
  87. package/.agent/workflows/status.md +1 -1
  88. package/.agent/workflows/tribunal-full.md +3 -3
  89. package/.agent/workflows/tribunal-speed.md +2 -2
  90. package/README.md +348 -238
  91. package/bin/tribunal-kit.js +62 -1482
  92. package/dist/cli.js +13 -0
  93. package/dist/commands/align.js +1 -1
  94. package/dist/commands/compile.js +1 -1
  95. package/dist/commands/guardrail.js +275 -0
  96. package/dist/commands/init.js +10 -9
  97. package/dist/commands/optimize.js +318 -0
  98. package/dist/utils/version.js +1 -1
  99. package/package.json +10 -8
  100. package/scripts/fix-vbc.js +98 -0
  101. package/scripts/fix-vbc.ps1 +119 -0
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cmdOptimizeSkill = cmdOptimizeSkill;
7
+
8
+ const fs = __importDefault(require("fs"));
9
+ const path = __importDefault(require("path"));
10
+ const os = __importDefault(require("os"));
11
+ const https = __importDefault(require("https"));
12
+ const { execSync } = require("child_process");
13
+ const logger = require("../utils/logger");
14
+ const helpers = require("../utils/helpers");
15
+
16
+ // ── LLM Helpers ──────────────────────────────────────────────────────────────
17
+ function detectLlmProvider() {
18
+ if (process.env.ANTHROPIC_API_KEY)
19
+ return { provider: "anthropic", key: process.env.ANTHROPIC_API_KEY };
20
+ if (process.env.OPENAI_API_KEY)
21
+ return { provider: "openai", key: process.env.OPENAI_API_KEY };
22
+ if (process.env.GEMINI_API_KEY)
23
+ return { provider: "gemini", key: process.env.GEMINI_API_KEY };
24
+ return null;
25
+ }
26
+
27
+ function httpsPost(hostname, apiPath, headers, body) {
28
+ return new Promise((resolve, reject) => {
29
+ const data = JSON.stringify(body);
30
+ const req = https.request(
31
+ {
32
+ method: "POST",
33
+ hostname,
34
+ path: apiPath,
35
+ headers: { ...headers, "Content-Length": Buffer.byteLength(data) },
36
+ },
37
+ (res) => {
38
+ let raw = "";
39
+ res.on("data", (c) => { raw += c; });
40
+ res.on("end", () => resolve(raw));
41
+ res.on("error", reject);
42
+ },
43
+ );
44
+ req.on("error", reject);
45
+ req.setTimeout(30000, () => {
46
+ req.destroy(new Error("LLM API timeout"));
47
+ });
48
+ req.write(data);
49
+ req.end();
50
+ });
51
+ }
52
+
53
+ async function callLlmApi(prompt, provider, apiKey) {
54
+ try {
55
+ if (provider === "anthropic") {
56
+ const raw = await httpsPost(
57
+ "api.anthropic.com",
58
+ "/v1/messages",
59
+ {
60
+ "Content-Type": "application/json",
61
+ "x-api-key": apiKey,
62
+ "anthropic-version": "2023-06-01",
63
+ },
64
+ {
65
+ model: "claude-3-5-sonnet-latest",
66
+ max_tokens: 1024,
67
+ messages: [{ role: "user", content: prompt }],
68
+ },
69
+ );
70
+ const json = JSON.parse(raw);
71
+ return json?.content?.[0]?.text ?? null;
72
+ }
73
+
74
+ if (provider === "openai") {
75
+ const raw = await httpsPost(
76
+ "api.openai.com",
77
+ "/v1/chat/completions",
78
+ {
79
+ "Content-Type": "application/json",
80
+ Authorization: `Bearer ${apiKey}`,
81
+ },
82
+ {
83
+ model: "gpt-4o-mini",
84
+ max_tokens: 1024,
85
+ messages: [{ role: "user", content: prompt }],
86
+ temperature: 0.1,
87
+ },
88
+ );
89
+ const json = JSON.parse(raw);
90
+ return json?.choices?.[0]?.message?.content ?? null;
91
+ }
92
+
93
+ if (provider === "gemini") {
94
+ const raw = await httpsPost(
95
+ "generativelanguage.googleapis.com",
96
+ `/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`,
97
+ { "Content-Type": "application/json" },
98
+ {
99
+ contents: [{ parts: [{ text: prompt }] }],
100
+ generationConfig: { maxOutputTokens: 1024, temperature: 0.1 },
101
+ },
102
+ );
103
+ const json = JSON.parse(raw);
104
+ return json?.candidates?.[0]?.content?.parts?.[0]?.text ?? null;
105
+ }
106
+ } catch (e) {
107
+ logger.err(`LLM API Call failed: ${e.message}`);
108
+ return null;
109
+ }
110
+ return null;
111
+ }
112
+
113
+ // ── Core Binary Resolver ─────────────────────────────────────────────────────
114
+ function getCoreBinaryPath(targetDir) {
115
+ const isWindows = os.default.platform() === "win32";
116
+ const ext = isWindows ? ".exe" : "";
117
+
118
+ // Dev build target checks
119
+ const devPath = path.default.resolve(targetDir, 'target', 'release', `tribunal-core${ext}`);
120
+ if (fs.default.existsSync(devPath)) return devPath;
121
+
122
+ const debugPath = path.default.resolve(targetDir, 'target', 'debug', `tribunal-core${ext}`);
123
+ if (fs.default.existsSync(debugPath)) return debugPath;
124
+
125
+ // Production npm package checks
126
+ const pkgName = `@tribunal-kit/core-${os.default.platform()}-${os.default.arch()}`;
127
+ try {
128
+ const pkgPath = require.resolve(`${pkgName}/package.json`);
129
+ const binPath = path.default.resolve(path.default.dirname(pkgPath), `bin/tribunal-core${ext}`);
130
+ if (fs.default.existsSync(binPath)) return binPath;
131
+ } catch {}
132
+
133
+ return null;
134
+ }
135
+
136
+ // ── Main Optimizer Command ───────────────────────────────────────────────────
137
+ async function cmdOptimizeSkill(flags, processArgs, quiet = false) {
138
+ const targetDir = flags.path ? path.default.resolve(flags.path) : process.cwd();
139
+ const agentDest = path.default.join(targetDir, '.agent');
140
+
141
+ if (!fs.default.existsSync(agentDest)) {
142
+ logger.err('.agent/ not found. Run: npx tribunal-kit init');
143
+ process.exit(1);
144
+ }
145
+
146
+ helpers.banner(quiet);
147
+
148
+ // Detect LLM Credentials
149
+ const llm = detectLlmProvider();
150
+ if (!llm) {
151
+ logger.err("No LLM API Key detected in environment. Please set GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY.");
152
+ process.exit(1);
153
+ }
154
+
155
+ // Resolve Core Binary
156
+ const binPath = getCoreBinaryPath(targetDir);
157
+ if (!binPath) {
158
+ logger.err("tribunal-core binary not found. Run 'cargo build --release' or install the core package.");
159
+ process.exit(1);
160
+ }
161
+
162
+ // Parse loop parameters
163
+ const skillName = flags.target || 'project-idioms';
164
+ const skillPath = path.default.join(agentDest, 'skills', skillName, 'SKILL.md');
165
+
166
+ if (!fs.default.existsSync(skillPath)) {
167
+ logger.err(`Target skill file not found: ${skillPath}`);
168
+ process.exit(1);
169
+ }
170
+
171
+ // Find the harness command
172
+ const positionalArgs = processArgs.slice(3).filter(arg => !arg.startsWith("--"));
173
+ if (positionalArgs.length === 0) {
174
+ logger.err("Harness command is required. Usage: tk optimize-skill --target <skill-name> \"<harness-command>\"");
175
+ process.exit(1);
176
+ }
177
+ const harnessCmd = positionalArgs[0];
178
+
179
+ const epochs = 4;
180
+ const editBudget = 4;
181
+
182
+ logger.log(` ${logger.c('cyan', '⊘')} Starting SkillOpt loop for skill: ${logger.bold(skillName)}`);
183
+ logger.log(` ${logger.c('cyan', '⊘')} Harness: "${logger.bold(harnessCmd)}"`);
184
+ logger.log(` ${logger.c('cyan', '⊘')} Provider: ${logger.bold(llm.provider)}`);
185
+ console.log();
186
+
187
+ let bestScore = 0.0;
188
+ let currentSkillText = fs.default.readFileSync(skillPath, 'utf8');
189
+
190
+ for (let epoch = 1; epoch <= epochs; epoch++) {
191
+ logger.log(` ${logger.c('cyan', 'ā–¶')} ${logger.bold(`Epoch ${epoch}/${epochs}`)}`);
192
+
193
+ // 1. Run Rollout Harness
194
+ logger.log(` ${logger.c('gray', 'ā—')} Running rollout batch execution...`);
195
+ let rolloutLogs = "";
196
+ let rolloutSuccess = true;
197
+ try {
198
+ rolloutLogs = execSync(harnessCmd, { encoding: 'utf8', cwd: targetDir, stdio: 'pipe' });
199
+ } catch (e) {
200
+ rolloutLogs = e.stdout + "\n" + e.stderr;
201
+ rolloutSuccess = false;
202
+ }
203
+
204
+ const _initialScore = rolloutSuccess ? 1.0 : 0.0;
205
+ logger.log(` ${logger.c('gray', 'ā—')} Rollout score: ${rolloutSuccess ? logger.c('green', '1.0') : logger.c('red', '0.0')}`);
206
+
207
+ // 2. Call LLM for Patch Proposals
208
+ logger.log(` ${logger.c('gray', 'ā—')} Requesting optimizer reflections from LLM...`);
209
+ const reflectionPrompt = `
210
+ You are a SkillOpt text-space optimizer coach.
211
+ Analyze the following rollout run logs and current skill document, then propose bounded add/delete/replace/insert_after edits.
212
+ The goal is to fix failure patterns and make the procedural memory rules clearer and more robust.
213
+
214
+ Current Skill Content:
215
+ """
216
+ ${currentSkillText}
217
+ """
218
+
219
+ Rollout Logs:
220
+ ${rolloutLogs.slice(-4000)}
221
+
222
+ Output ONLY a JSON array containing proposed edits. No markdown formatting, no explanation.
223
+ Each edit must follow this schema:
224
+ [
225
+ {
226
+ "op": "append" | "insert_after" | "replace" | "delete",
227
+ "target": "<exact text match to replace/insert_after/delete, leave null for append>",
228
+ "content": "<exact markdown/rules to add, replace, or insert>",
229
+ "support_count": 1,
230
+ "source_type": "${rolloutSuccess ? "success" : "failure"}"
231
+ }
232
+ ]
233
+ `;
234
+
235
+ const llmResponse = await callLlmApi(reflectionPrompt, llm.provider, llm.key);
236
+ if (!llmResponse) {
237
+ logger.warn(" āš ļø LLM returned empty response. Skipping epoch step.");
238
+ continue;
239
+ }
240
+
241
+ // Clean LLM JSON response from markdown wrappers if present
242
+ let cleanedJson = llmResponse.trim();
243
+ if (cleanedJson.startsWith("```json")) {
244
+ cleanedJson = cleanedJson.replace(/^```json/, "").replace(/```$/, "").trim();
245
+ } else if (cleanedJson.startsWith("```")) {
246
+ cleanedJson = cleanedJson.replace(/^```/, "").replace(/```$/, "").trim();
247
+ }
248
+
249
+ // 3. Invoke Rust binary for optimizing step
250
+ logger.log(` ${logger.c('gray', 'ā—')} Merging and applying bounded edits via Rust Core...`);
251
+ let optResultStr = "";
252
+ try {
253
+ const tempFile = path.default.join(os.default.tmpdir(), `edits-${Date.now()}.json`);
254
+ fs.default.writeFileSync(tempFile, cleanedJson, 'utf8');
255
+
256
+ optResultStr = execSync(
257
+ `"${binPath}" optimize-step --skill-path "${skillPath}" --edits-json "${cleanedJson.replace(/"/g, '\\"')}" --budget ${editBudget}`,
258
+ { encoding: 'utf8', cwd: targetDir, stdio: 'pipe' }
259
+ );
260
+
261
+ try { fs.default.unlinkSync(tempFile); } catch {}
262
+ } catch (e) {
263
+ logger.err(` āœ– Rust Core optimization failed: ${e.message}`);
264
+ continue;
265
+ }
266
+
267
+ let optReport;
268
+ try {
269
+ optReport = JSON.parse(optResultStr.trim());
270
+ } catch {
271
+ logger.err(" āœ– Failed to parse optimizer report from Rust Core.");
272
+ continue;
273
+ }
274
+
275
+ if (optReport.applied_count === 0) {
276
+ logger.log(` ${logger.c('yellow', 'ā—')} No edits applied (deduplicated or target not found).`);
277
+ continue;
278
+ }
279
+
280
+ logger.log(` ${logger.c('green', 'ā—')} Applied ${optReport.applied_count} edits to skill.`);
281
+
282
+ // 4. Run Validation Harness
283
+ logger.log(` ${logger.c('gray', 'ā—')} Evaluating candidate skill against validation split...`);
284
+ let valSuccess = true;
285
+ try {
286
+ execSync(harnessCmd, { encoding: 'utf8', cwd: targetDir, stdio: 'pipe' });
287
+ } catch {
288
+ valSuccess = false;
289
+ }
290
+
291
+ const candidateScore = valSuccess ? 1.0 : 0.0;
292
+
293
+ // 5. Validation Gate
294
+ if (candidateScore > bestScore || (candidateScore === 1.0 && bestScore === 0.0)) {
295
+ logger.ok(` āœ” Gate Accepted! Score improved/stabilized to ${logger.c('green', String(candidateScore))}.`);
296
+ bestScore = candidateScore;
297
+ currentSkillText = fs.default.readFileSync(skillPath, 'utf8');
298
+ } else {
299
+ logger.warn(` āš ļø Gate Rejected. Score (${candidateScore}) <= Best (${bestScore}). Reverting edits.`);
300
+ fs.default.writeFileSync(skillPath, currentSkillText, 'utf8');
301
+
302
+ // Save to rejected-edit buffer history
303
+ const rejectedPath = path.default.join(agentDest, 'history', 'skill-optimization');
304
+ fs.default.mkdirSync(rejectedPath, { recursive: true });
305
+ const bufFile = path.default.join(rejectedPath, 'rejected-buffer.json');
306
+ let buffer = [];
307
+ if (fs.default.existsSync(bufFile)) {
308
+ try { buffer = JSON.parse(fs.default.readFileSync(bufFile, 'utf8')); } catch {}
309
+ }
310
+ buffer.push({ epoch, timestamp: new Date().toISOString(), edits: optReport.reports });
311
+ fs.default.writeFileSync(bufFile, JSON.stringify(buffer, null, 2), 'utf8');
312
+ }
313
+ console.log();
314
+ }
315
+
316
+ logger.ok(`šŸŽ‰ SkillOpt training complete. Best validation score: ${logger.c('green', String(bestScore))}`);
317
+ console.log();
318
+ }
@@ -7,7 +7,7 @@ exports.compareSemver = compareSemver;
7
7
  exports.fetchLatestVersion = fetchLatestVersion;
8
8
  exports.autoUpdateCheck = autoUpdateCheck;
9
9
  const https_1 = __importDefault(require("https"));
10
- const child_process_1 = require("child_process");
10
+ const _child_process_1 = require("child_process");
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  const path_1 = __importDefault(require("path"));
13
13
  const os_1 = __importDefault(require("os"));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tribunal-kit",
3
- "version": "5.8.2",
4
- "description": "The operating system for AI software engineering — governance, memory, review pipelines, and reusable skills for every coding agent. 43 specialist agents, 34 workflows, 20 parallel Tribunal code reviewers, MCP server, Rust core engine, and long-running autonomous agent harness for Cursor, VSCode, Windsurf, Claude Code, and Aider.",
3
+ "version": "5.8.4",
4
+ "description": "The operating system for AI software engineering — governance, memory, review pipelines, and reusable skills for every coding agent. 44 specialist agents, 34 workflows, 20 parallel Tribunal code reviewers, MCP server, Rust core engine, and long-running autonomous agent harness for Cursor, VSCode, Windsurf, Claude Code, and Aider.",
5
5
  "keywords": [
6
6
  "ai",
7
7
  "ai-agent",
@@ -91,6 +91,8 @@
91
91
  "validate-payload": "node scripts/validate-payload.js",
92
92
  "benchmark": "node scripts/benchmark.js",
93
93
  "benchmark:rust": "cargo build --release && node scripts/benchmark.js",
94
+ "build:rust": "cargo build --release",
95
+ "test:rust": "cargo test --manifest-path crates/core/Cargo.toml",
94
96
  "build": "echo 'No build step required for this project'"
95
97
  },
96
98
  "devDependencies": {
@@ -99,12 +101,12 @@
99
101
  "typescript": "^5.4.5"
100
102
  },
101
103
  "optionalDependencies": {
102
- "@tribunal-kit/core-darwin-arm64": "^5.8.2",
103
- "@tribunal-kit/core-darwin-x64": "^5.8.2",
104
- "@tribunal-kit/core-linux-arm64": "^5.8.2",
105
- "@tribunal-kit/core-linux-x64": "^5.8.2",
106
- "@tribunal-kit/core-win32-arm64": "^5.8.2",
107
- "@tribunal-kit/core-win32-x64": "^5.8.2"
104
+ "@tribunal-kit/core-darwin-arm64": "^5.8.4",
105
+ "@tribunal-kit/core-darwin-x64": "^5.8.4",
106
+ "@tribunal-kit/core-linux-arm64": "^5.8.4",
107
+ "@tribunal-kit/core-linux-x64": "^5.8.4",
108
+ "@tribunal-kit/core-win32-arm64": "^5.8.4",
109
+ "@tribunal-kit/core-win32-x64": "^5.8.4"
108
110
  },
109
111
  "jest": {
110
112
  "testMatch": [
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * fix-vbc.js — Batch appends missing VBC Protocol and Pre-Flight sections
4
+ * to all SKILL.md files in .agent/skills/ that are failing validation.
5
+ *
6
+ * Run: node scripts/fix-vbc.js
7
+ * Dry-run: node scripts/fix-vbc.js --dry-run
8
+ */
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+
13
+ const ROOT = path.resolve(__dirname, "..");
14
+ const SKILLS_DIR = path.join(ROOT, ".agent", "skills");
15
+ const DRY_RUN = process.argv.includes("--dry-run");
16
+
17
+ const PRE_FLIGHT_BLOCK = `
18
+ ### āœ… Pre-Flight Self-Audit
19
+
20
+ \`\`\`
21
+ āœ… Did I rely ONLY on real, verified tools and methods?
22
+ āœ… Is this solution appropriately scoped to the user's constraints?
23
+ āœ… Did I handle potential failure modes and edge cases?
24
+ āœ… Have I avoided generic boilerplate that doesn't add value?
25
+ \`\`\`
26
+ `;
27
+
28
+ const VBC_BLOCK = `
29
+ ### šŸ›‘ Verification-Before-Completion (VBC) Protocol
30
+
31
+ **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
32
+
33
+ - āŒ **Forbidden:** Declaring a task complete because the output "looks correct."
34
+ - āœ… **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.
35
+ `;
36
+
37
+ let fixedCount = 0;
38
+ let skippedCount = 0;
39
+ let errorCount = 0;
40
+
41
+ const skillDirs = fs.readdirSync(SKILLS_DIR).filter((d) => {
42
+ return fs.statSync(path.join(SKILLS_DIR, d)).isDirectory();
43
+ });
44
+
45
+ for (const dir of skillDirs) {
46
+ const skillPath = path.join(SKILLS_DIR, dir, "SKILL.md");
47
+ if (!fs.existsSync(skillPath)) continue;
48
+
49
+ let content;
50
+ try {
51
+ content = fs.readFileSync(skillPath, "utf8");
52
+ } catch (e) {
53
+ console.error(` āŒ Failed to read: ${dir}/SKILL.md — ${e.message}`);
54
+ errorCount++;
55
+ continue;
56
+ }
57
+
58
+ const hasPreFlight =
59
+ content.includes("Pre-Flight Checklist") || content.includes("Pre-Flight");
60
+ const hasVBC =
61
+ content.includes("VBC Protocol") || content.includes("VBC");
62
+
63
+ if (hasPreFlight && hasVBC) {
64
+ skippedCount++;
65
+ continue;
66
+ }
67
+
68
+ let appendText = "";
69
+
70
+ if (!hasPreFlight) {
71
+ appendText += PRE_FLIGHT_BLOCK;
72
+ console.log(` šŸ”§ ${dir}/SKILL.md — appending Pre-Flight Self-Audit`);
73
+ }
74
+
75
+ if (!hasVBC) {
76
+ appendText += VBC_BLOCK;
77
+ console.log(` šŸ”§ ${dir}/SKILL.md — appending VBC Protocol`);
78
+ }
79
+
80
+ if (DRY_RUN) {
81
+ console.log(` [DRY-RUN] Would append to ${dir}/SKILL.md`);
82
+ } else {
83
+ try {
84
+ fs.appendFileSync(skillPath, appendText, "utf8");
85
+ fixedCount++;
86
+ } catch (e) {
87
+ console.error(` āŒ Failed to write: ${dir}/SKILL.md — ${e.message}`);
88
+ errorCount++;
89
+ }
90
+ }
91
+ }
92
+
93
+ console.log(`\n━━━ VBC Fix Summary ━━━━━━━━━━━━━━━━━━━━━`);
94
+ console.log(` Fixed: ${fixedCount}`);
95
+ console.log(` Skipped: ${skippedCount} (already compliant)`);
96
+ console.log(` Errors: ${errorCount}`);
97
+ console.log(` Mode: ${DRY_RUN ? "DRY-RUN (no changes)" : "LIVE"}`);
98
+ console.log();
@@ -0,0 +1,119 @@
1
+ $ErrorActionPreference = "Stop"
2
+
3
+ $skillsDir = "c:\Users\sunrise\Desktop\pfojects\cli project\tribunal-kit\.agent\skills"
4
+
5
+ $vbcBlock = @"
6
+
7
+ ### `u{1F6D1} Verification-Before-Completion (VBC) Protocol
8
+
9
+ **CRITICAL:** You must follow a strict "evidence-based closeout" state machine.
10
+
11
+ - `u{274C} **Forbidden:** Declaring a task complete because the output "looks correct."
12
+ - `u{2705} **Required:** You are explicitly forbidden from finalizing any task without providing **concrete evidence** (terminal output, passing tests, compile success, or equivalent proof) that your output works as intended.
13
+ "@
14
+
15
+ $preFlightBlock = @"
16
+
17
+ ### `u{2705} Pre-Flight Self-Audit
18
+
19
+ ``````
20
+ `u{2705} Did I rely ONLY on real, verified tools and methods?
21
+ `u{2705} Is this solution appropriately scoped to the user's constraints?
22
+ `u{2705} Did I handle potential failure modes and edge cases?
23
+ `u{2705} Have I avoided generic boilerplate that doesn't add value?
24
+ ``````
25
+ "@
26
+
27
+ $failingSkills = @(
28
+ "12-principles-of-animation",
29
+ "60fps-animation",
30
+ "accessible-animation",
31
+ "adapt",
32
+ "animation-on-scroll",
33
+ "animation-systems",
34
+ "antfu-conventions",
35
+ "audit-and-fix",
36
+ "bolder",
37
+ "build-primitive",
38
+ "clarify",
39
+ "cobejs",
40
+ "codebase-design",
41
+ "colorize",
42
+ "compact-landing",
43
+ "company-logos",
44
+ "critique",
45
+ "delight",
46
+ "design-lab",
47
+ "diagnosing-bugs",
48
+ "distill",
49
+ "domain-modeling",
50
+ "fixing-metadata",
51
+ "gpt-taste",
52
+ "harden",
53
+ "impeccable",
54
+ "improve-codebase-architecture",
55
+ "landing-page",
56
+ "local-first-architecture",
57
+ "lottie-animation",
58
+ "marquee-loop",
59
+ "masked-reveal",
60
+ "micro-interaction",
61
+ "morphing-icons",
62
+ "page-transition-animation",
63
+ "polish",
64
+ "pricing-page",
65
+ "progressive-blur",
66
+ "quieter",
67
+ "react-doctor",
68
+ "redesign-skill",
69
+ "shape",
70
+ "soft-skill",
71
+ "sounds-on-the-web",
72
+ "svg-animation",
73
+ "swiss-design",
74
+ "taste-skill",
75
+ "tdd-workflow",
76
+ "thermo-nuclear-code-quality-review",
77
+ "to-spring-or-not-to-spring",
78
+ "transitions-dev",
79
+ "typeset",
80
+ "web-quality-audit"
81
+ )
82
+
83
+ $fixedCount = 0
84
+ $errorCount = 0
85
+
86
+ foreach ($skill in $failingSkills) {
87
+ $filePath = Join-Path $skillsDir "$skill\SKILL.md"
88
+
89
+ if (-not (Test-Path $filePath)) {
90
+ Write-Host " SKIP: $skill/SKILL.md not found" -ForegroundColor Yellow
91
+ continue
92
+ }
93
+
94
+ $content = Get-Content $filePath -Raw
95
+ $appendText = ""
96
+
97
+ $hasPreFlight = ($content -match "Pre-Flight Checklist") -or ($content -match "Pre-Flight")
98
+ $hasVBC = ($content -match "VBC Protocol") -or ($content -match "VBC")
99
+
100
+ if (-not $hasPreFlight) {
101
+ $appendText += $preFlightBlock
102
+ Write-Host " FIX: $skill/SKILL.md - adding Pre-Flight" -ForegroundColor Cyan
103
+ }
104
+
105
+ if (-not $hasVBC) {
106
+ $appendText += $vbcBlock
107
+ Write-Host " FIX: $skill/SKILL.md - adding VBC Protocol" -ForegroundColor Cyan
108
+ }
109
+
110
+ if ($appendText -ne "") {
111
+ Add-Content -Path $filePath -Value $appendText -NoNewline
112
+ $fixedCount++
113
+ Write-Host " DONE: $skill/SKILL.md" -ForegroundColor Green
114
+ }
115
+ }
116
+
117
+ Write-Host ""
118
+ Write-Host "Fixed: $fixedCount files" -ForegroundColor Green
119
+ Write-Host "Errors: $errorCount" -ForegroundColor Red