tribunal-kit 4.4.0 → 4.4.2

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 (90) hide show
  1. package/.agent/agents/api-architect.md +66 -66
  2. package/.agent/agents/db-latency-auditor.md +216 -216
  3. package/.agent/agents/precedence-reviewer.md +250 -250
  4. package/.agent/agents/resilience-reviewer.md +88 -88
  5. package/.agent/agents/schema-reviewer.md +67 -67
  6. package/.agent/agents/throughput-optimizer.md +299 -299
  7. package/.agent/agents/ui-ux-auditor.md +292 -292
  8. package/.agent/agents/vitals-reviewer.md +223 -223
  9. package/.agent/history/architecture-graph.yaml +32 -1
  10. package/.agent/history/graph-cache.json +66 -19
  11. package/.agent/history/snapshots/bin__tribunal-kit.js.json +19 -0
  12. package/.agent/history/snapshots/eslint.config.js.json +9 -0
  13. package/.agent/history/snapshots/migrate_refs.js.json +3 -3
  14. package/.agent/history/snapshots/scripts__changelog.js.json +2 -1
  15. package/.agent/history/snapshots/scripts__sync-version.js.json +2 -1
  16. package/.agent/history/snapshots/scripts__validate-payload.js.json +1 -0
  17. package/.agent/history/snapshots/test__integration__bridges.test.js.json +2 -1
  18. package/.agent/history/snapshots/test__integration__init.test.js.json +1 -0
  19. package/.agent/history/snapshots/test__integration__routing.test.js.json +1 -0
  20. package/.agent/history/snapshots/test__integration__swarm_dispatcher.test.js.json +2 -1
  21. package/.agent/history/snapshots/test__integration__wave2.test.js.json +2 -1
  22. package/.agent/history/snapshots/test__unit__args.test.js.json +11 -1
  23. package/.agent/history/snapshots/test__unit__case_law_manager.test.js.json +1 -0
  24. package/.agent/history/snapshots/test__unit__context_broker.test.js.json +11 -0
  25. package/.agent/history/snapshots/test__unit__copyDir.test.js.json +11 -1
  26. package/.agent/history/snapshots/test__unit__graph_tools.test.js.json +1 -0
  27. package/.agent/history/snapshots/test__unit__inner_loop_validator.test.js.json +11 -0
  28. package/.agent/history/snapshots/test__unit__selfInstall.test.js.json +11 -1
  29. package/.agent/history/snapshots/test__unit__semver.test.js.json +11 -1
  30. package/.agent/history/snapshots/test__unit__swarm_dispatcher.test.js.json +1 -0
  31. package/.agent/scripts/_colors.js +154 -2
  32. package/.agent/scripts/_utils.js +205 -3
  33. package/.agent/scripts/append_flow.js +72 -72
  34. package/.agent/scripts/auto_preview.js +197 -197
  35. package/.agent/scripts/bundle_analyzer.js +90 -119
  36. package/.agent/scripts/case_law_manager.js +18 -13
  37. package/.agent/scripts/checklist.js +100 -88
  38. package/.agent/scripts/colors.js +7 -13
  39. package/.agent/scripts/compress_skills.js +141 -141
  40. package/.agent/scripts/consolidate_skills.js +149 -149
  41. package/.agent/scripts/context_broker.js +605 -609
  42. package/.agent/scripts/deep_compress.js +150 -150
  43. package/.agent/scripts/dependency_analyzer.js +68 -106
  44. package/.agent/scripts/graph_builder.js +341 -311
  45. package/.agent/scripts/graph_visualizer.js +390 -384
  46. package/.agent/scripts/graph_zoom.js +6 -4
  47. package/.agent/scripts/inner_loop_validator.js +445 -465
  48. package/.agent/scripts/lint_runner.js +27 -28
  49. package/.agent/scripts/minify_context.js +100 -100
  50. package/.agent/scripts/mutation_runner.js +280 -280
  51. package/.agent/scripts/patch_skills_meta.js +156 -156
  52. package/.agent/scripts/patch_skills_output.js +244 -244
  53. package/.agent/scripts/schema_validator.js +280 -297
  54. package/.agent/scripts/security_scan.js +37 -64
  55. package/.agent/scripts/session_manager.js +270 -276
  56. package/.agent/scripts/skill_evolution.js +637 -644
  57. package/.agent/scripts/skill_integrator.js +307 -313
  58. package/.agent/scripts/strengthen_skills.js +193 -193
  59. package/.agent/scripts/strip_tribunal.js +47 -47
  60. package/.agent/scripts/swarm_dispatcher.js +360 -360
  61. package/.agent/scripts/test_runner.js +32 -39
  62. package/.agent/scripts/utils.js +10 -25
  63. package/.agent/scripts/verify_all.js +84 -92
  64. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
  65. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
  66. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
  67. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
  68. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
  69. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
  70. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
  71. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
  72. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
  73. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
  74. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
  75. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
  76. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
  77. package/.agent/skills/doc.md +1 -1
  78. package/.agent/skills/knowledge-graph/SKILL.md +52 -52
  79. package/.agent/skills/ui-ux-pro-max/SKILL.md +562 -562
  80. package/.agent/workflows/generate.md +183 -183
  81. package/.agent/workflows/tribunal-speed.md +183 -183
  82. package/README.md +1 -1
  83. package/bin/tribunal-kit.js +76 -87
  84. package/package.json +6 -3
  85. package/scripts/changelog.js +167 -167
  86. package/scripts/sync-version.js +81 -81
  87. package/.agent/history/architecture-explorer.html +0 -352
  88. package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
  89. package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
  90. package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
@@ -1,313 +1,307 @@
1
- #!/usr/bin/env node
2
- /**
3
- * skill_integrator.js — Automated Skill-Script Integration Analyzer
4
- *
5
- * This script scans active skills in `.agent/skills/` and maps them to their
6
- * corresponding executable scripts in `.agent/scripts/`. It helps the Orchestrator
7
- * and other agents know which skills have automated CLI actions available.
8
- *
9
- * Usage:
10
- * node .agent/scripts/skill_integrator.js
11
- * node .agent/scripts/skill_integrator.js --skill <skill-name>
12
- * node .agent/scripts/skill_integrator.js --report
13
- * node .agent/scripts/skill_integrator.js --verify
14
- * node .agent/scripts/skill_integrator.js --report --verify
15
- */
16
-
17
- 'use strict';
18
-
19
- const fs = require('fs');
20
- const path = require('path');
21
- const { execFileSync } = require('child_process');
22
-
23
- // Colors for terminal output
24
- const CYAN = '\x1b[96m';
25
- const GREEN = '\x1b[92m';
26
- const YELLOW = '\x1b[93m';
27
- const RED = '\x1b[91m';
28
- const BOLD = '\x1b[1m';
29
- const RESET = '\x1b[0m';
30
-
31
- const REPORT_FILE = 'skill-integration-report.md';
32
-
33
- function findAgentDir(startPathStr) {
34
- let current = path.resolve(startPathStr);
35
- const root = path.parse(current).root;
36
- while (current !== root) {
37
- const agentDir = path.join(current, '.agent');
38
- if (fs.existsSync(agentDir) && fs.statSync(agentDir).isDirectory()) {
39
- return agentDir;
40
- }
41
- current = path.dirname(current);
42
- }
43
- return null;
44
- }
45
-
46
- function getAssociatedScript(skillDir, scriptsDir) {
47
- /** Check if the skill has an explicit frontmatter script or an implicit script file. */
48
- const skillName = path.basename(skillDir);
49
-
50
- // 1. Implicit check: does a script with the same name exist? (Check for both .js and .py)
51
- const implicitJsScript = path.join(scriptsDir, `${skillName}.js`);
52
- if (fs.existsSync(implicitJsScript)) {
53
- return `.agent/scripts/${skillName}.js`;
54
- }
55
-
56
- const implicitPyScript = path.join(scriptsDir, `${skillName}.py`);
57
- if (fs.existsSync(implicitPyScript)) {
58
- return `.agent/scripts/${skillName}.py`;
59
- }
60
-
61
- // 2. Explicit check: does the SKILL.md define 'script:' in its frontmatter?
62
- const skillMd = path.join(skillDir, 'SKILL.md');
63
- if (fs.existsSync(skillMd)) {
64
- try {
65
- const content = fs.readFileSync(skillMd, 'utf8');
66
- const match = content.match(/---([\s\S]*?)---/);
67
- if (match) {
68
- const frontmatter = match[1];
69
- const scriptMatch = frontmatter.match(/(?:^|\n)script:\s*([^\n]+)/);
70
- if (scriptMatch) {
71
- return scriptMatch[1].trim();
72
- }
73
- }
74
- } catch (err) {
75
- // ignore
76
- }
77
- }
78
-
79
- return null;
80
- }
81
-
82
- function scanAllSkills(agentDir) {
83
- const skillsDir = path.join(agentDir, 'skills');
84
- const scriptsDir = path.join(agentDir, 'scripts');
85
-
86
- if (!fs.existsSync(skillsDir) || !fs.existsSync(scriptsDir)) {
87
- console.log(`${YELLOW}Warning: '.agent/skills' or '.agent/scripts' directory not found.${RESET}`);
88
- return {};
89
- }
90
-
91
- const integratedSkills = {};
92
- const items = fs.readdirSync(skillsDir, { withFileTypes: true });
93
-
94
- // sort items by name
95
- items.sort((a, b) => a.name.localeCompare(b.name));
96
-
97
- for (const item of items) {
98
- if (item.isDirectory()) {
99
- const skillDir = path.join(skillsDir, item.name);
100
- const scriptPath = getAssociatedScript(skillDir, scriptsDir);
101
- if (scriptPath) {
102
- integratedSkills[item.name] = scriptPath;
103
- }
104
- }
105
- }
106
-
107
- return integratedSkills;
108
- }
109
-
110
- function verifyScript(scriptPathStr, workspaceRoot) {
111
- /**
112
- * Verify a mapped script exists on disk and has valid syntax.
113
- * Returns { valid: boolean, message: string }.
114
- */
115
- const fullPath = path.resolve(workspaceRoot, scriptPathStr);
116
-
117
- if (!fs.existsSync(fullPath)) {
118
- return { valid: false, message: `File not found: ${fullPath}` };
119
- }
120
-
121
- try {
122
- if (fullPath.endsWith('.js')) {
123
- // use node to syntax check
124
- execFileSync('node', ['-c', fullPath], { stdio: 'pipe' });
125
- } else if (fullPath.endsWith('.py')) {
126
- // use python to syntax check
127
- execFileSync('python', ['-m', 'py_compile', fullPath], { stdio: 'pipe' });
128
- }
129
- return { valid: true, message: 'Syntax OK' };
130
- } catch (e) {
131
- let msg = e.message;
132
- if (e.stderr) {
133
- msg = e.stderr.toString().trim();
134
- }
135
- return { valid: false, message: `Syntax error: ${msg.split('\n')[0]}` };
136
- }
137
- }
138
-
139
- function checkSkill(skillName, agentDir) {
140
- const skillDir = path.join(agentDir, 'skills', skillName);
141
- const scriptsDir = path.join(agentDir, 'scripts');
142
-
143
- if (!fs.existsSync(skillDir)) {
144
- console.log(`${YELLOW}Skill '${skillName}' not found in .agent/skills/${RESET}`);
145
- return;
146
- }
147
-
148
- const scriptPath = getAssociatedScript(skillDir, scriptsDir);
149
- if (scriptPath) {
150
- console.log(`${GREEN}✓ Associated script found:${RESET} ${scriptPath}`);
151
- const runner = scriptPath.endsWith('.py') ? 'python' : 'node';
152
- console.log(`\nTo execute:\n ${runner} ${scriptPath}`);
153
- } else {
154
- console.log(`No executable script mapped for '${skillName}'.`);
155
- }
156
- }
157
-
158
- function cmdReport(integratedSkills, workspaceRoot) {
159
- /** Write a Markdown integration report to REPORT_FILE. */
160
- const keys = Object.keys(integratedSkills).sort();
161
- const generated = new Date().toISOString().slice(0, 16);
162
-
163
- let content = `# Skill-Script Integration Report\n\n`;
164
- content += `Generated: ${generated}\n`;
165
- content += `Integrated skills: ${keys.length}\n\n`;
166
- content += `---\n\n`;
167
- content += `| Skill | Script | Exists |\n`;
168
- content += `|---|---|---|\n`;
169
-
170
- for (const skill of keys) {
171
- const script = integratedSkills[skill];
172
- const scriptPath = path.resolve(workspaceRoot, script);
173
- const exists = fs.existsSync(scriptPath) ? '✅' : '❌ Missing';
174
- content += `| \`${skill}\` | \`${script}\` | ${exists} |\n`;
175
- }
176
-
177
- content += `\n---\n\n`;
178
- content += `_Run \`node .agent/scripts/skill_integrator.js --verify\` to validate syntax of all mapped scripts._\n`;
179
-
180
- const reportPath = path.join(workspaceRoot, REPORT_FILE);
181
- fs.writeFileSync(reportPath, content, 'utf8');
182
-
183
- console.log(`${GREEN}✅ Report written to:${RESET} ${reportPath}`);
184
- }
185
-
186
- function cmdVerify(integratedSkills, workspaceRoot) {
187
- /**
188
- * Validate each mapped script: check existence and syntax.
189
- * Returns true if all pass, false if any fail.
190
- */
191
- const keys = Object.keys(integratedSkills).sort();
192
- if (keys.length === 0) {
193
- console.log(`${YELLOW}No integrated scripts found to verify.${RESET}`);
194
- return true;
195
- }
196
-
197
- console.log(`\n${BOLD}${CYAN}━━━ Skill-Script Verification (${keys.length} scripts) ━━━${RESET}\n`);
198
-
199
- let allPassed = true;
200
- const failures = [];
201
-
202
- for (const skill of keys) {
203
- const script = integratedSkills[skill];
204
- const res = verifyScript(script, workspaceRoot);
205
- if (res.valid) {
206
- console.log(` ${GREEN}✅ PASS${RESET} ${BOLD}${skill}${RESET} → ${script}`);
207
- } else {
208
- console.log(` ${RED}❌ FAIL${RESET} ${BOLD}${skill}${RESET} → ${script}`);
209
- console.log(` ${RED}${res.message}${RESET}`);
210
- allPassed = false;
211
- failures.push(skill);
212
- }
213
- }
214
-
215
- console.log(`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
216
- if (allPassed) {
217
- console.log(`${GREEN}All ${keys.length} mapped scripts passed verification.${RESET}\n`);
218
- } else {
219
- console.log(`${RED}${failures.length} script(s) failed verification. Fix before deploying.${RESET}\n`);
220
- }
221
-
222
- return allPassed;
223
- }
224
-
225
- function main() {
226
- const rawArgs = process.argv.slice(2);
227
-
228
- if (rawArgs.length > 0 && ['-h', '--help', 'help'].includes(rawArgs[0])) {
229
- console.log(`
230
- ${BOLD}skill_integrator.js${RESET} — Skill-Script Integrator
231
-
232
- ${BOLD}Usage:${RESET}
233
- node .agent/scripts/skill_integrator.js
234
- node .agent/scripts/skill_integrator.js --skill <skill-name>
235
- node .agent/scripts/skill_integrator.js --report
236
- node .agent/scripts/skill_integrator.js --verify
237
- node .agent/scripts/skill_integrator.js --report --verify
238
-
239
- ${BOLD}Options:${RESET}
240
- --skill <name> Validate a specific skill by name
241
- --workspace <dir> Workspace root directory (default: current dir)
242
- --report Generate a Markdown integration report (skill-integration-report.md)
243
- --verify Validate syntax of all mapped scripts (exits 1 on any failure)
244
- `);
245
- return;
246
- }
247
-
248
- // Parse args
249
- let skillArg = null;
250
- let workspaceArg = '.';
251
- let reportArg = false;
252
- let verifyArg = false;
253
-
254
- for (let i = 0; i < rawArgs.length; i++) {
255
- if (rawArgs[i] === '--skill' && i + 1 < rawArgs.length) {
256
- skillArg = rawArgs[++i];
257
- } else if (rawArgs[i] === '--workspace' && i + 1 < rawArgs.length) {
258
- workspaceArg = rawArgs[++i];
259
- } else if (rawArgs[i] === '--report') {
260
- reportArg = true;
261
- } else if (rawArgs[i] === '--verify') {
262
- verifyArg = true;
263
- }
264
- }
265
-
266
- const workspaceRoot = path.resolve(workspaceArg);
267
- const agentDir = findAgentDir(workspaceRoot);
268
-
269
- if (!agentDir) {
270
- console.log(`${YELLOW}Error: Could not find .agent directory starting from ${workspaceRoot}${RESET}`);
271
- process.exit(1);
272
- }
273
-
274
- if (skillArg) {
275
- checkSkill(skillArg, agentDir);
276
- return;
277
- }
278
-
279
- const integratedSkills = scanAllSkills(agentDir);
280
-
281
- if (reportArg) {
282
- cmdReport(integratedSkills, workspaceRoot);
283
- }
284
-
285
- if (verifyArg) {
286
- const passed = cmdVerify(integratedSkills, workspaceRoot);
287
- if (!passed) {
288
- process.exit(1);
289
- }
290
- return;
291
- }
292
-
293
- if (!reportArg && !verifyArg) {
294
- const keys = Object.keys(integratedSkills).sort();
295
- if (keys.length === 0) {
296
- console.log("No integrated scripts found for any active skills.");
297
- } else {
298
- console.log(`\n${BOLD}${CYAN}--- Skill-Script Integrations (${keys.length}) ---${RESET}\n`);
299
- for (const skill of keys) {
300
- const script = integratedSkills[skill];
301
- console.log(` ${BOLD}${skill}${RESET}`);
302
- console.log(` ↳ ${GREEN}${script}${RESET}\n`);
303
- }
304
- console.log(`${CYAN}To run a skill script, use: python <path> or node <path>${RESET}\n`);
305
- }
306
- }
307
- }
308
-
309
- module.exports = { getAssociatedScript, verifyScript };
310
-
311
- if (require.main === module) {
312
- main();
313
- }
1
+ #!/usr/bin/env node
2
+ /**
3
+ * skill_integrator.js — Automated Skill-Script Integration Analyzer
4
+ *
5
+ * This script scans active skills in `.agent/skills/` and maps them to their
6
+ * corresponding executable scripts in `.agent/scripts/`. It helps the Orchestrator
7
+ * and other agents know which skills have automated CLI actions available.
8
+ *
9
+ * Usage:
10
+ * node .agent/scripts/skill_integrator.js
11
+ * node .agent/scripts/skill_integrator.js --skill <skill-name>
12
+ * node .agent/scripts/skill_integrator.js --report
13
+ * node .agent/scripts/skill_integrator.js --verify
14
+ * node .agent/scripts/skill_integrator.js --report --verify
15
+ */
16
+
17
+ 'use strict';
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const { execFileSync } = require('child_process');
22
+
23
+ const { CYAN, GREEN, YELLOW, RED, BOLD, RESET } = require('./_colors');
24
+
25
+ const REPORT_FILE = 'skill-integration-report.md';
26
+
27
+ function findAgentDir(startPathStr) {
28
+ let current = path.resolve(startPathStr);
29
+ const root = path.parse(current).root;
30
+ while (current !== root) {
31
+ const agentDir = path.join(current, '.agent');
32
+ if (fs.existsSync(agentDir) && fs.statSync(agentDir).isDirectory()) {
33
+ return agentDir;
34
+ }
35
+ current = path.dirname(current);
36
+ }
37
+ return null;
38
+ }
39
+
40
+ function getAssociatedScript(skillDir, scriptsDir) {
41
+ /** Check if the skill has an explicit frontmatter script or an implicit script file. */
42
+ const skillName = path.basename(skillDir);
43
+
44
+ // 1. Implicit check: does a script with the same name exist? (Check for both .js and .py)
45
+ const implicitJsScript = path.join(scriptsDir, `${skillName}.js`);
46
+ if (fs.existsSync(implicitJsScript)) {
47
+ return `.agent/scripts/${skillName}.js`;
48
+ }
49
+
50
+ const implicitPyScript = path.join(scriptsDir, `${skillName}.py`);
51
+ if (fs.existsSync(implicitPyScript)) {
52
+ return `.agent/scripts/${skillName}.py`;
53
+ }
54
+
55
+ // 2. Explicit check: does the SKILL.md define 'script:' in its frontmatter?
56
+ const skillMd = path.join(skillDir, 'SKILL.md');
57
+ if (fs.existsSync(skillMd)) {
58
+ try {
59
+ const content = fs.readFileSync(skillMd, 'utf8');
60
+ const match = content.match(/---([\s\S]*?)---/);
61
+ if (match) {
62
+ const frontmatter = match[1];
63
+ const scriptMatch = frontmatter.match(/(?:^|\n)script:\s*([^\n]+)/);
64
+ if (scriptMatch) {
65
+ return scriptMatch[1].trim();
66
+ }
67
+ }
68
+ } catch {
69
+ // ignore
70
+ }
71
+ }
72
+
73
+ return null;
74
+ }
75
+
76
+ function scanAllSkills(agentDir) {
77
+ const skillsDir = path.join(agentDir, 'skills');
78
+ const scriptsDir = path.join(agentDir, 'scripts');
79
+
80
+ if (!fs.existsSync(skillsDir) || !fs.existsSync(scriptsDir)) {
81
+ console.log(`${YELLOW}Warning: '.agent/skills' or '.agent/scripts' directory not found.${RESET}`);
82
+ return {};
83
+ }
84
+
85
+ const integratedSkills = {};
86
+ const items = fs.readdirSync(skillsDir, { withFileTypes: true });
87
+
88
+ // sort items by name
89
+ items.sort((a, b) => a.name.localeCompare(b.name));
90
+
91
+ for (const item of items) {
92
+ if (item.isDirectory()) {
93
+ const skillDir = path.join(skillsDir, item.name);
94
+ const scriptPath = getAssociatedScript(skillDir, scriptsDir);
95
+ if (scriptPath) {
96
+ integratedSkills[item.name] = scriptPath;
97
+ }
98
+ }
99
+ }
100
+
101
+ return integratedSkills;
102
+ }
103
+
104
+ function verifyScript(scriptPathStr, workspaceRoot) {
105
+ /**
106
+ * Verify a mapped script exists on disk and has valid syntax.
107
+ * Returns { valid: boolean, message: string }.
108
+ */
109
+ const fullPath = path.resolve(workspaceRoot, scriptPathStr);
110
+
111
+ if (!fs.existsSync(fullPath)) {
112
+ return { valid: false, message: `File not found: ${fullPath}` };
113
+ }
114
+
115
+ try {
116
+ if (fullPath.endsWith('.js')) {
117
+ // use node to syntax check
118
+ execFileSync('node', ['-c', fullPath], { stdio: 'pipe' });
119
+ } else if (fullPath.endsWith('.py')) {
120
+ // use python to syntax check
121
+ execFileSync('python', ['-m', 'py_compile', fullPath], { stdio: 'pipe' });
122
+ }
123
+ return { valid: true, message: 'Syntax OK' };
124
+ } catch (e) {
125
+ let msg = e.message;
126
+ if (e.stderr) {
127
+ msg = e.stderr.toString().trim();
128
+ }
129
+ return { valid: false, message: `Syntax error: ${msg.split('\n')[0]}` };
130
+ }
131
+ }
132
+
133
+ function checkSkill(skillName, agentDir) {
134
+ const skillDir = path.join(agentDir, 'skills', skillName);
135
+ const scriptsDir = path.join(agentDir, 'scripts');
136
+
137
+ if (!fs.existsSync(skillDir)) {
138
+ console.log(`${YELLOW}Skill '${skillName}' not found in .agent/skills/${RESET}`);
139
+ return;
140
+ }
141
+
142
+ const scriptPath = getAssociatedScript(skillDir, scriptsDir);
143
+ if (scriptPath) {
144
+ console.log(`${GREEN} Associated script found:${RESET} ${scriptPath}`);
145
+ const runner = scriptPath.endsWith('.py') ? 'python' : 'node';
146
+ console.log(`\nTo execute:\n ${runner} ${scriptPath}`);
147
+ } else {
148
+ console.log(`No executable script mapped for '${skillName}'.`);
149
+ }
150
+ }
151
+
152
+ function cmdReport(integratedSkills, workspaceRoot) {
153
+ /** Write a Markdown integration report to REPORT_FILE. */
154
+ const keys = Object.keys(integratedSkills).sort();
155
+ const generated = new Date().toISOString().slice(0, 16);
156
+
157
+ let content = `# Skill-Script Integration Report\n\n`;
158
+ content += `Generated: ${generated}\n`;
159
+ content += `Integrated skills: ${keys.length}\n\n`;
160
+ content += `---\n\n`;
161
+ content += `| Skill | Script | Exists |\n`;
162
+ content += `|---|---|---|\n`;
163
+
164
+ for (const skill of keys) {
165
+ const script = integratedSkills[skill];
166
+ const scriptPath = path.resolve(workspaceRoot, script);
167
+ const exists = fs.existsSync(scriptPath) ? '✅' : '❌ Missing';
168
+ content += `| \`${skill}\` | \`${script}\` | ${exists} |\n`;
169
+ }
170
+
171
+ content += `\n---\n\n`;
172
+ content += `_Run \`node .agent/scripts/skill_integrator.js --verify\` to validate syntax of all mapped scripts._\n`;
173
+
174
+ const reportPath = path.join(workspaceRoot, REPORT_FILE);
175
+ fs.writeFileSync(reportPath, content, 'utf8');
176
+
177
+ console.log(`${GREEN}✅ Report written to:${RESET} ${reportPath}`);
178
+ }
179
+
180
+ function cmdVerify(integratedSkills, workspaceRoot) {
181
+ /**
182
+ * Validate each mapped script: check existence and syntax.
183
+ * Returns true if all pass, false if any fail.
184
+ */
185
+ const keys = Object.keys(integratedSkills).sort();
186
+ if (keys.length === 0) {
187
+ console.log(`${YELLOW}No integrated scripts found to verify.${RESET}`);
188
+ return true;
189
+ }
190
+
191
+ console.log(`\n${BOLD}${CYAN}━━━ Skill-Script Verification (${keys.length} scripts) ━━━${RESET}\n`);
192
+
193
+ let allPassed = true;
194
+ const failures = [];
195
+
196
+ for (const skill of keys) {
197
+ const script = integratedSkills[skill];
198
+ const res = verifyScript(script, workspaceRoot);
199
+ if (res.valid) {
200
+ console.log(` ${GREEN}✅ PASS${RESET} ${BOLD}${skill}${RESET} ${script}`);
201
+ } else {
202
+ console.log(` ${RED}❌ FAIL${RESET} ${BOLD}${skill}${RESET} ${script}`);
203
+ console.log(` ${RED}${res.message}${RESET}`);
204
+ allPassed = false;
205
+ failures.push(skill);
206
+ }
207
+ }
208
+
209
+ console.log(`\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`);
210
+ if (allPassed) {
211
+ console.log(`${GREEN}All ${keys.length} mapped scripts passed verification.${RESET}\n`);
212
+ } else {
213
+ console.log(`${RED}${failures.length} script(s) failed verification. Fix before deploying.${RESET}\n`);
214
+ }
215
+
216
+ return allPassed;
217
+ }
218
+
219
+ function main() {
220
+ const rawArgs = process.argv.slice(2);
221
+
222
+ if (rawArgs.length > 0 && ['-h', '--help', 'help'].includes(rawArgs[0])) {
223
+ console.log(`
224
+ ${BOLD}skill_integrator.js${RESET} — Skill-Script Integrator
225
+
226
+ ${BOLD}Usage:${RESET}
227
+ node .agent/scripts/skill_integrator.js
228
+ node .agent/scripts/skill_integrator.js --skill <skill-name>
229
+ node .agent/scripts/skill_integrator.js --report
230
+ node .agent/scripts/skill_integrator.js --verify
231
+ node .agent/scripts/skill_integrator.js --report --verify
232
+
233
+ ${BOLD}Options:${RESET}
234
+ --skill <name> Validate a specific skill by name
235
+ --workspace <dir> Workspace root directory (default: current dir)
236
+ --report Generate a Markdown integration report (skill-integration-report.md)
237
+ --verify Validate syntax of all mapped scripts (exits 1 on any failure)
238
+ `);
239
+ return;
240
+ }
241
+
242
+ // Parse args
243
+ let skillArg = null;
244
+ let workspaceArg = '.';
245
+ let reportArg = false;
246
+ let verifyArg = false;
247
+
248
+ for (let i = 0; i < rawArgs.length; i++) {
249
+ if (rawArgs[i] === '--skill' && i + 1 < rawArgs.length) {
250
+ skillArg = rawArgs[++i];
251
+ } else if (rawArgs[i] === '--workspace' && i + 1 < rawArgs.length) {
252
+ workspaceArg = rawArgs[++i];
253
+ } else if (rawArgs[i] === '--report') {
254
+ reportArg = true;
255
+ } else if (rawArgs[i] === '--verify') {
256
+ verifyArg = true;
257
+ }
258
+ }
259
+
260
+ const workspaceRoot = path.resolve(workspaceArg);
261
+ const agentDir = findAgentDir(workspaceRoot);
262
+
263
+ if (!agentDir) {
264
+ console.log(`${YELLOW}Error: Could not find .agent directory starting from ${workspaceRoot}${RESET}`);
265
+ process.exit(1);
266
+ }
267
+
268
+ if (skillArg) {
269
+ checkSkill(skillArg, agentDir);
270
+ return;
271
+ }
272
+
273
+ const integratedSkills = scanAllSkills(agentDir);
274
+
275
+ if (reportArg) {
276
+ cmdReport(integratedSkills, workspaceRoot);
277
+ }
278
+
279
+ if (verifyArg) {
280
+ const passed = cmdVerify(integratedSkills, workspaceRoot);
281
+ if (!passed) {
282
+ process.exit(1);
283
+ }
284
+ return;
285
+ }
286
+
287
+ if (!reportArg && !verifyArg) {
288
+ const keys = Object.keys(integratedSkills).sort();
289
+ if (keys.length === 0) {
290
+ console.log("No integrated scripts found for any active skills.");
291
+ } else {
292
+ console.log(`\n${BOLD}${CYAN}--- Skill-Script Integrations (${keys.length}) ---${RESET}\n`);
293
+ for (const skill of keys) {
294
+ const script = integratedSkills[skill];
295
+ console.log(` ${BOLD}${skill}${RESET}`);
296
+ console.log(` ↳ ${GREEN}${script}${RESET}\n`);
297
+ }
298
+ console.log(`${CYAN}To run a skill script, use: python <path> or node <path>${RESET}\n`);
299
+ }
300
+ }
301
+ }
302
+
303
+ module.exports = { getAssociatedScript, verifyScript };
304
+
305
+ if (require.main === module) {
306
+ main();
307
+ }