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.
- package/.agent/agents/api-architect.md +66 -66
- package/.agent/agents/db-latency-auditor.md +216 -216
- package/.agent/agents/precedence-reviewer.md +250 -250
- package/.agent/agents/resilience-reviewer.md +88 -88
- package/.agent/agents/schema-reviewer.md +67 -67
- package/.agent/agents/throughput-optimizer.md +299 -299
- package/.agent/agents/ui-ux-auditor.md +292 -292
- package/.agent/agents/vitals-reviewer.md +223 -223
- package/.agent/history/architecture-graph.yaml +32 -1
- package/.agent/history/graph-cache.json +66 -19
- package/.agent/history/snapshots/bin__tribunal-kit.js.json +19 -0
- package/.agent/history/snapshots/eslint.config.js.json +9 -0
- package/.agent/history/snapshots/migrate_refs.js.json +3 -3
- package/.agent/history/snapshots/scripts__changelog.js.json +2 -1
- package/.agent/history/snapshots/scripts__sync-version.js.json +2 -1
- package/.agent/history/snapshots/scripts__validate-payload.js.json +1 -0
- package/.agent/history/snapshots/test__integration__bridges.test.js.json +2 -1
- package/.agent/history/snapshots/test__integration__init.test.js.json +1 -0
- package/.agent/history/snapshots/test__integration__routing.test.js.json +1 -0
- package/.agent/history/snapshots/test__integration__swarm_dispatcher.test.js.json +2 -1
- package/.agent/history/snapshots/test__integration__wave2.test.js.json +2 -1
- package/.agent/history/snapshots/test__unit__args.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__case_law_manager.test.js.json +1 -0
- package/.agent/history/snapshots/test__unit__context_broker.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__copyDir.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__graph_tools.test.js.json +1 -0
- package/.agent/history/snapshots/test__unit__inner_loop_validator.test.js.json +11 -0
- package/.agent/history/snapshots/test__unit__selfInstall.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__semver.test.js.json +11 -1
- package/.agent/history/snapshots/test__unit__swarm_dispatcher.test.js.json +1 -0
- package/.agent/scripts/_colors.js +154 -2
- package/.agent/scripts/_utils.js +205 -3
- package/.agent/scripts/append_flow.js +72 -72
- package/.agent/scripts/auto_preview.js +197 -197
- package/.agent/scripts/bundle_analyzer.js +90 -119
- package/.agent/scripts/case_law_manager.js +18 -13
- package/.agent/scripts/checklist.js +100 -88
- package/.agent/scripts/colors.js +7 -13
- package/.agent/scripts/compress_skills.js +141 -141
- package/.agent/scripts/consolidate_skills.js +149 -149
- package/.agent/scripts/context_broker.js +605 -609
- package/.agent/scripts/deep_compress.js +150 -150
- package/.agent/scripts/dependency_analyzer.js +68 -106
- package/.agent/scripts/graph_builder.js +341 -311
- package/.agent/scripts/graph_visualizer.js +390 -384
- package/.agent/scripts/graph_zoom.js +6 -4
- package/.agent/scripts/inner_loop_validator.js +445 -465
- package/.agent/scripts/lint_runner.js +27 -28
- package/.agent/scripts/minify_context.js +100 -100
- package/.agent/scripts/mutation_runner.js +280 -280
- package/.agent/scripts/patch_skills_meta.js +156 -156
- package/.agent/scripts/patch_skills_output.js +244 -244
- package/.agent/scripts/schema_validator.js +280 -297
- package/.agent/scripts/security_scan.js +37 -64
- package/.agent/scripts/session_manager.js +270 -276
- package/.agent/scripts/skill_evolution.js +637 -644
- package/.agent/scripts/skill_integrator.js +307 -313
- package/.agent/scripts/strengthen_skills.js +193 -193
- package/.agent/scripts/strip_tribunal.js +47 -47
- package/.agent/scripts/swarm_dispatcher.js +360 -360
- package/.agent/scripts/test_runner.js +32 -39
- package/.agent/scripts/utils.js +10 -25
- package/.agent/scripts/verify_all.js +84 -92
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
- package/.agent/skills/doc.md +1 -1
- package/.agent/skills/knowledge-graph/SKILL.md +52 -52
- package/.agent/skills/ui-ux-pro-max/SKILL.md +562 -562
- package/.agent/workflows/generate.md +183 -183
- package/.agent/workflows/tribunal-speed.md +183 -183
- package/README.md +1 -1
- package/bin/tribunal-kit.js +76 -87
- package/package.json +6 -3
- package/scripts/changelog.js +167 -167
- package/scripts/sync-version.js +81 -81
- package/.agent/history/architecture-explorer.html +0 -352
- package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
- package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
|
@@ -15,25 +15,16 @@ const fs = require('fs');
|
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const { spawnSync } = require('child_process');
|
|
17
17
|
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
RED, GREEN, YELLOW, BLUE, BOLD, DIM, CYAN, RESET,
|
|
20
|
+
banner, sectionHeader, timer, formatMs,
|
|
21
|
+
ok, fail, skip,
|
|
22
|
+
} = require('./_colors');
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
console.log(`\n${BOLD}${BLUE}━━━ ${title} ━━━${RESET}`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function ok(msg) {
|
|
25
|
-
console.log(` ${GREEN}✅ ${msg}${RESET}`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function fail(msg) {
|
|
29
|
-
console.log(` ${RED}❌ ${msg}${RESET}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function skip(msg) {
|
|
33
|
-
console.log(` ${YELLOW}⏭️ ${msg}${RESET}`);
|
|
34
|
-
}
|
|
24
|
+
const { loadJson } = require('./_utils');
|
|
35
25
|
|
|
36
26
|
function runTests(label, cmd, cwd) {
|
|
27
|
+
const elapsed = timer();
|
|
37
28
|
try {
|
|
38
29
|
const executable = process.platform === 'win32' && (cmd[0] === 'npx' || cmd[0] === 'npm') ? `${cmd[0]}.cmd` : cmd[0];
|
|
39
30
|
const result = spawnSync(executable, cmd.slice(1), {
|
|
@@ -43,6 +34,8 @@ function runTests(label, cmd, cwd) {
|
|
|
43
34
|
shell: process.platform === 'win32'
|
|
44
35
|
});
|
|
45
36
|
|
|
37
|
+
const ms = elapsed();
|
|
38
|
+
|
|
46
39
|
if (result.error && !result.stdout && !result.stderr) {
|
|
47
40
|
console.log(` Error: ${result.error.message}`);
|
|
48
41
|
}
|
|
@@ -56,11 +49,11 @@ function runTests(label, cmd, cwd) {
|
|
|
56
49
|
}
|
|
57
50
|
|
|
58
51
|
if (result.status === 0) {
|
|
59
|
-
ok(`${label} — all tests passed`);
|
|
52
|
+
ok(`${label} — all tests passed ${DIM}(${formatMs(ms)})${RESET}`);
|
|
60
53
|
return true;
|
|
61
54
|
}
|
|
62
55
|
|
|
63
|
-
fail(`${label} — test failures detected`);
|
|
56
|
+
fail(`${label} — test failures detected ${DIM}(${formatMs(ms)})${RESET}`);
|
|
64
57
|
return false;
|
|
65
58
|
} catch {
|
|
66
59
|
skip(`${label} — tool not installed`);
|
|
@@ -69,20 +62,15 @@ function runTests(label, cmd, cwd) {
|
|
|
69
62
|
}
|
|
70
63
|
|
|
71
64
|
function detectTestFramework(projectRoot) {
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (deps.mocha) return "mocha";
|
|
82
|
-
if (scripts.test) return "npm-test";
|
|
83
|
-
} catch {
|
|
84
|
-
if (fs.readFileSync(pkgJson, 'utf8').includes('"test"')) return "npm-test";
|
|
85
|
-
}
|
|
65
|
+
const pkg = loadJson(path.join(projectRoot, "package.json"));
|
|
66
|
+
if (pkg) {
|
|
67
|
+
const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
|
|
68
|
+
const scripts = pkg.scripts || {};
|
|
69
|
+
|
|
70
|
+
if (deps.vitest) return "vitest";
|
|
71
|
+
if (deps.jest) return "jest";
|
|
72
|
+
if (deps.mocha) return "mocha";
|
|
73
|
+
if (scripts.test) return "npm-test";
|
|
86
74
|
}
|
|
87
75
|
|
|
88
76
|
if (fs.existsSync(path.join(projectRoot, "pytest.ini")) ||
|
|
@@ -137,16 +125,18 @@ function main() {
|
|
|
137
125
|
process.exit(1);
|
|
138
126
|
}
|
|
139
127
|
|
|
140
|
-
console.log(`${BOLD}Tribunal — test_runner.js${RESET}`);
|
|
141
|
-
console.log(`Project: ${projectRoot}`);
|
|
142
|
-
|
|
143
128
|
const framework = detectTestFramework(projectRoot);
|
|
129
|
+
console.log(banner('test_runner.js', {
|
|
130
|
+
Project: projectRoot,
|
|
131
|
+
Framework: framework || 'none detected',
|
|
132
|
+
}));
|
|
133
|
+
|
|
144
134
|
if (!framework) {
|
|
145
135
|
skip("No test framework detected in this project");
|
|
146
136
|
process.exit(0);
|
|
147
137
|
}
|
|
148
138
|
|
|
149
|
-
|
|
139
|
+
console.log(sectionHeader(`Running tests (${framework})`));
|
|
150
140
|
|
|
151
141
|
let cmd = [];
|
|
152
142
|
let passed = true;
|
|
@@ -181,9 +171,12 @@ function main() {
|
|
|
181
171
|
passed = runTests("go test", cmd, projectRoot);
|
|
182
172
|
}
|
|
183
173
|
|
|
184
|
-
console.log(`\n${BOLD}━━━ Test Summary ━━━${RESET}`);
|
|
185
|
-
if (passed)
|
|
186
|
-
|
|
174
|
+
console.log(`\n${BOLD}${CYAN}━━━ Test Summary ━━━${RESET}`);
|
|
175
|
+
if (passed) {
|
|
176
|
+
console.log(`\n${GREEN}${BOLD} ✔ Tests passed (${framework}).${RESET}\n`);
|
|
177
|
+
} else {
|
|
178
|
+
console.log(`\n${RED}${BOLD} ✖ Tests failed (${framework}).${RESET}\n`);
|
|
179
|
+
}
|
|
187
180
|
|
|
188
181
|
process.exit(passed ? 0 : 1);
|
|
189
182
|
}
|
package/.agent/scripts/utils.js
CHANGED
|
@@ -1,32 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* utils.js
|
|
3
|
-
*
|
|
2
|
+
* utils.js — Backward-compatible re-export of _utils.js
|
|
3
|
+
* ══════════════════════════════════════════════════════
|
|
4
|
+
* All utilities are defined in _utils.js.
|
|
5
|
+
* This file re-exports them for scripts that import from './utils.js'.
|
|
6
|
+
*
|
|
7
|
+
* New scripts should import from './_utils' directly.
|
|
4
8
|
*/
|
|
5
9
|
'use strict';
|
|
6
10
|
|
|
7
|
-
const
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
|
|
10
|
-
function findAgentDir() {
|
|
11
|
-
let current = path.resolve(process.cwd());
|
|
12
|
-
const root = path.parse(current).root;
|
|
13
|
-
while (current !== root) {
|
|
14
|
-
const candidate = path.join(current, '.agent');
|
|
15
|
-
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
16
|
-
return candidate;
|
|
17
|
-
}
|
|
18
|
-
current = path.dirname(current);
|
|
19
|
-
}
|
|
20
|
-
console.error("\x1b[91m✖ Error: '.agent' directory not found. Please run 'npx tribunal-kit init' first.\x1b[0m");
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function ensureUtf8Stdout() {
|
|
25
|
-
// In Node.js, process.stdout is typically already UTF-8 capable,
|
|
26
|
-
// but this exists for compatibility with legacy python workflows.
|
|
27
|
-
}
|
|
11
|
+
const _utils = require('./_utils');
|
|
28
12
|
|
|
29
13
|
module.exports = {
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
..._utils,
|
|
15
|
+
// Legacy export for compatibility
|
|
16
|
+
ensureUtf8Stdout: function() {},
|
|
32
17
|
};
|
|
@@ -15,65 +15,68 @@ const fs = require('fs');
|
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const { execFileSync } = require('child_process');
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const BOLD = '\x1b[1m';
|
|
24
|
-
const RESET = '\x1b[0m';
|
|
18
|
+
const {
|
|
19
|
+
RED, GREEN, YELLOW, BLUE, BOLD, DIM, CYAN, RESET,
|
|
20
|
+
banner, sectionHeader, summaryTable, timer, formatMs,
|
|
21
|
+
ok, fail, skip,
|
|
22
|
+
} = require('./_colors');
|
|
25
23
|
|
|
26
|
-
const
|
|
24
|
+
const { walkDir, hasNpm, SOURCE_EXTENSIONS } = require('./_utils');
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
console.log(`\n${BOLD}${BLUE}━━━ ${title} ━━━${RESET}`);
|
|
30
|
-
}
|
|
26
|
+
// ── Results Tracking ────────────────────────────────────────────────────────
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
const RESULTS = [];
|
|
29
|
+
|
|
30
|
+
function trackOk(label, ms, note) {
|
|
31
|
+
const timing = ms != null ? `${DIM}(${formatMs(ms)})${RESET}` : '';
|
|
32
|
+
const noteStr = note ? ` ${DIM}${note}${RESET}` : '';
|
|
33
|
+
console.log(` ${GREEN}✅ ${label}${RESET} ${timing}${noteStr}`);
|
|
34
|
+
RESULTS.push({ name: label, status: 'pass', ms, note: note || '' });
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
function
|
|
37
|
+
function trackFail(label, ms, note) {
|
|
38
|
+
const timing = ms != null ? `${DIM}(${formatMs(ms)})${RESET}` : '';
|
|
39
39
|
const noteStr = note ? `\n ${note}` : '';
|
|
40
|
-
console.log(` ${RED}❌ ${label}${RESET}${noteStr}`);
|
|
41
|
-
RESULTS.push({ label,
|
|
40
|
+
console.log(` ${RED}❌ ${label}${RESET} ${timing}${noteStr}`);
|
|
41
|
+
RESULTS.push({ name: label, status: 'fail', ms, note: note || '' });
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function
|
|
44
|
+
function trackSkip(label, reason) {
|
|
45
45
|
console.log(` ${YELLOW}⏭️ ${label} — ${reason}${RESET}`);
|
|
46
|
-
RESULTS.push({ label,
|
|
46
|
+
RESULTS.push({ name: label, status: 'skip', note: `skipped: ${reason}` });
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// ── Command Runner ──────────────────────────────────────────────────────────
|
|
50
|
+
|
|
49
51
|
/**
|
|
50
52
|
* Run a shell command and return true if it exits with code 0.
|
|
51
53
|
*/
|
|
52
54
|
function run(label, cmd, cwd) {
|
|
55
|
+
const elapsed = timer();
|
|
53
56
|
try {
|
|
54
57
|
const isWindows = process.platform === 'win32';
|
|
55
|
-
let bin = cmd[0];
|
|
56
|
-
if (isWindows && (bin === 'npm' || bin === 'npx')) bin += '.cmd';
|
|
57
58
|
|
|
58
|
-
execFileSync(
|
|
59
|
+
execFileSync(cmd[0], cmd.slice(1), {
|
|
59
60
|
cwd,
|
|
60
61
|
stdio: 'pipe',
|
|
61
62
|
timeout: 120000,
|
|
62
63
|
encoding: 'utf8',
|
|
64
|
+
shell: isWindows
|
|
63
65
|
});
|
|
64
|
-
|
|
66
|
+
trackOk(label, elapsed());
|
|
65
67
|
return true;
|
|
66
68
|
} catch (err) {
|
|
69
|
+
const ms = elapsed();
|
|
67
70
|
if (err.code === 'ENOENT') {
|
|
68
|
-
|
|
71
|
+
trackSkip(label, 'tool not installed — skipping');
|
|
69
72
|
return true;
|
|
70
73
|
}
|
|
71
74
|
if (err.killed) {
|
|
72
|
-
|
|
75
|
+
trackFail(label, ms, 'timed out after 120s');
|
|
73
76
|
return false;
|
|
74
77
|
}
|
|
75
78
|
const output = ((err.stdout || '') + (err.stderr || '')).trim();
|
|
76
|
-
|
|
79
|
+
trackFail(label, ms, output ? output.slice(0, 500) : 'non-zero exit code');
|
|
77
80
|
return false;
|
|
78
81
|
}
|
|
79
82
|
}
|
|
@@ -81,140 +84,130 @@ function run(label, cmd, cwd) {
|
|
|
81
84
|
|
|
82
85
|
/**
|
|
83
86
|
* Scan source files for obviously hardcoded credentials.
|
|
87
|
+
* Uses shared walkDir from _utils.js to eliminate duplicated walker code.
|
|
84
88
|
*/
|
|
85
89
|
function scanSecrets(cwd) {
|
|
90
|
+
const elapsed = timer();
|
|
86
91
|
const patterns = ['password=', 'secret=', 'api_key=', 'private_key=', 'auth_token='];
|
|
87
92
|
const found = [];
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const lines = content.split('\n');
|
|
105
|
-
for (let i = 0; i < lines.length; i++) {
|
|
106
|
-
const low = lines[i].toLowerCase().trim();
|
|
107
|
-
const hasPattern = patterns.some(p => low.includes(p));
|
|
108
|
-
if (hasPattern && !low.startsWith('#') && low.includes('=')) {
|
|
109
|
-
const rel = path.relative(cwd, fullPath);
|
|
110
|
-
found.push(`${rel}:${i + 1}`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
93
|
+
|
|
94
|
+
const sourceExtensions = new Set(['.ts', '.tsx', '.js', '.jsx', '.py']);
|
|
95
|
+
const files = walkDir(cwd, { extensions: sourceExtensions });
|
|
96
|
+
|
|
97
|
+
for (const fullPath of files) {
|
|
98
|
+
let content;
|
|
99
|
+
try { content = fs.readFileSync(fullPath, 'utf8'); } catch { continue; }
|
|
100
|
+
|
|
101
|
+
const lines = content.split('\n');
|
|
102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
103
|
+
const low = lines[i].toLowerCase().trim();
|
|
104
|
+
const hasPattern = patterns.some(p => low.includes(p));
|
|
105
|
+
if (hasPattern && !low.startsWith('#') && low.includes('=')) {
|
|
106
|
+
const rel = path.relative(cwd, fullPath);
|
|
107
|
+
found.push(`${rel}:${i + 1}`);
|
|
113
108
|
}
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
const ms = elapsed();
|
|
119
113
|
if (found.length > 0) {
|
|
120
|
-
|
|
114
|
+
trackFail('Secret scan', ms, found.slice(0, 5).join('\n '));
|
|
121
115
|
return false;
|
|
122
116
|
}
|
|
123
|
-
|
|
117
|
+
trackOk('Secret scan — no hardcoded credentials found', ms, `${files.length} files scanned`);
|
|
124
118
|
return true;
|
|
125
119
|
}
|
|
126
120
|
|
|
127
121
|
|
|
128
|
-
/**
|
|
129
|
-
* Check if there's a package.json to run npm commands against.
|
|
130
|
-
*/
|
|
131
|
-
function hasNpm(cwd) {
|
|
132
|
-
return fs.existsSync(path.join(cwd, 'package.json'));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
122
|
/**
|
|
137
123
|
* Run all verification checks. Returns number of failures.
|
|
138
124
|
*/
|
|
139
125
|
function verifyAll(cwd, skipped) {
|
|
140
126
|
let failures = 0;
|
|
127
|
+
RESULTS.length = 0; // Reset for clean runs (prevents accumulation in tests)
|
|
128
|
+
const totalTimer = timer();
|
|
141
129
|
|
|
142
|
-
|
|
130
|
+
console.log(sectionHeader('Secret Scan', 1));
|
|
143
131
|
if (!skipped.includes('secrets')) {
|
|
144
132
|
if (!scanSecrets(cwd)) failures++;
|
|
145
133
|
} else {
|
|
146
|
-
|
|
134
|
+
trackSkip('Secret scan', 'skipped by flag');
|
|
147
135
|
}
|
|
148
136
|
|
|
149
|
-
|
|
137
|
+
console.log(sectionHeader('TypeScript', 2));
|
|
150
138
|
if (!skipped.includes('typescript')) {
|
|
151
139
|
if (hasNpm(cwd)) {
|
|
152
140
|
if (!run('tsc --noEmit', ['npx', 'tsc', '--noEmit'], cwd)) failures++;
|
|
153
141
|
} else {
|
|
154
|
-
|
|
142
|
+
trackSkip('TypeScript', 'no package.json found in project');
|
|
155
143
|
}
|
|
156
144
|
} else {
|
|
157
|
-
|
|
145
|
+
trackSkip('TypeScript', 'skipped by flag');
|
|
158
146
|
}
|
|
159
147
|
|
|
160
|
-
|
|
148
|
+
console.log(sectionHeader('ESLint', 3));
|
|
161
149
|
if (!skipped.includes('lint')) {
|
|
162
150
|
if (hasNpm(cwd)) {
|
|
163
151
|
if (!run('ESLint', ['npx', 'eslint', '.', '--max-warnings=0'], cwd)) failures++;
|
|
164
152
|
} else {
|
|
165
|
-
|
|
153
|
+
trackSkip('ESLint', 'no package.json found in project');
|
|
166
154
|
}
|
|
167
155
|
} else {
|
|
168
|
-
|
|
156
|
+
trackSkip('ESLint', 'skipped by flag');
|
|
169
157
|
}
|
|
170
158
|
|
|
171
|
-
|
|
159
|
+
console.log(sectionHeader('Unit Tests', 4));
|
|
172
160
|
if (!skipped.includes('tests')) {
|
|
173
161
|
if (hasNpm(cwd)) {
|
|
174
162
|
if (!run('Test suite', ['npm', 'test', '--', '--passWithNoTests'], cwd)) failures++;
|
|
175
163
|
} else {
|
|
176
|
-
|
|
164
|
+
trackSkip('Tests', 'no package.json found in project');
|
|
177
165
|
}
|
|
178
166
|
} else {
|
|
179
|
-
|
|
167
|
+
trackSkip('Tests', 'skipped by flag');
|
|
180
168
|
}
|
|
181
169
|
|
|
182
|
-
|
|
170
|
+
console.log(sectionHeader('Build', 5));
|
|
183
171
|
if (!skipped.includes('build')) {
|
|
184
172
|
if (hasNpm(cwd)) {
|
|
185
173
|
if (!run('npm run build', ['npm', 'run', 'build'], cwd)) failures++;
|
|
186
174
|
} else {
|
|
187
|
-
|
|
175
|
+
trackSkip('Build', 'no package.json found in project');
|
|
188
176
|
}
|
|
189
177
|
} else {
|
|
190
|
-
|
|
178
|
+
trackSkip('Build', 'skipped by flag');
|
|
191
179
|
}
|
|
192
180
|
|
|
193
|
-
|
|
181
|
+
console.log(sectionHeader('Dependency Audit', 6));
|
|
194
182
|
if (!skipped.includes('deps')) {
|
|
195
183
|
if (hasNpm(cwd)) {
|
|
196
184
|
if (!run('npm audit', ['npm', 'audit', '--audit-level=high'], cwd)) failures++;
|
|
197
185
|
} else {
|
|
198
|
-
|
|
186
|
+
trackSkip('Dependency audit', 'no package.json found in project');
|
|
199
187
|
}
|
|
200
188
|
} else {
|
|
201
|
-
|
|
189
|
+
trackSkip('Dependency audit', 'skipped by flag');
|
|
202
190
|
}
|
|
203
191
|
|
|
204
|
-
// ━━━ Summary ━━━
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
192
|
+
// ━━━ Summary Table ━━━
|
|
193
|
+
const totalMs = totalTimer();
|
|
194
|
+
console.log(`\n${BOLD}${CYAN}━━━ Verification Summary ━━━${RESET}`);
|
|
195
|
+
summaryTable(RESULTS);
|
|
196
|
+
|
|
197
|
+
const passCount = RESULTS.filter(r => r.status === 'pass').length;
|
|
198
|
+
const failCount = RESULTS.filter(r => r.status === 'fail').length;
|
|
199
|
+
const skipCount = RESULTS.filter(r => r.status === 'skip').length;
|
|
200
|
+
|
|
201
|
+
console.log(`\n ${DIM}Total: ${RESULTS.length} checks in ${formatMs(totalMs)}${RESET}`);
|
|
202
|
+
console.log(` ${GREEN}${passCount} passed${RESET} ${failCount > 0 ? `${RED}${failCount} failed${RESET} ` : ''}${skipCount > 0 ? `${YELLOW}${skipCount} skipped${RESET}` : ''}`);
|
|
211
203
|
|
|
212
204
|
console.log();
|
|
213
205
|
if (failures === 0) {
|
|
214
|
-
console.log(`${GREEN}${BOLD}All checks passed — safe to deploy.${RESET}`);
|
|
206
|
+
console.log(`${GREEN}${BOLD} ✔ All checks passed — safe to deploy.${RESET}`);
|
|
215
207
|
} else {
|
|
216
|
-
console.log(`${RED}${BOLD}${failures} check(s) failed — fix before deploying.${RESET}`);
|
|
208
|
+
console.log(`${RED}${BOLD} ✖ ${failures} check(s) failed — fix before deploying.${RESET}`);
|
|
217
209
|
}
|
|
210
|
+
console.log();
|
|
218
211
|
|
|
219
212
|
return failures;
|
|
220
213
|
}
|
|
@@ -240,8 +233,7 @@ function main() {
|
|
|
240
233
|
const args = parseArgs(process.argv);
|
|
241
234
|
const cwd = process.cwd();
|
|
242
235
|
|
|
243
|
-
console.log(
|
|
244
|
-
console.log(`Project: ${cwd}\n`);
|
|
236
|
+
console.log(banner('verify_all.js', { Project: cwd }));
|
|
245
237
|
|
|
246
238
|
const failures = verifyAll(cwd, args.skip);
|
|
247
239
|
process.exit(failures > 0 ? 1 : 0);
|
|
@@ -119,4 +119,4 @@ project-name/
|
|
|
119
119
|
- **Mutations**: Use Server Actions combined with React 19's `useActionState` to handle loading and error states instead of manual useState.
|
|
120
120
|
- **Type Safety**: Share Zod schemas between Server Actions (input validation) and Client Forms.
|
|
121
121
|
- **Security**: Always validate input data with Zod before passing it to Prisma.
|
|
122
|
-
- **Styling**: Use native CSS variables in Tailwind v4 for easier dynamic theming.
|
|
122
|
+
- **Styling**: Use native CSS variables in Tailwind v4 for easier dynamic theming.
|
|
@@ -166,4 +166,4 @@ export const metadata: Metadata = {
|
|
|
166
166
|
- **React Server Components (RSC)**: Default all components to Server Components. Only add `'use client'` when you need state (`useState`) or event listeners (`onClick`).
|
|
167
167
|
- **Image Optimization**: Use the `<Image />` component but remember `unoptimized: true` for static export or use an external image CDN (Cloudinary/Imgix).
|
|
168
168
|
- **Font Optimization**: Use `next/font` (Google Fonts) to automatically host fonts and prevent layout shift.
|
|
169
|
-
- **Responsive**: Mobile-first design using Tailwind prefixes like `sm:`, `md:`, `lg:`.
|
|
169
|
+
- **Responsive**: Mobile-first design using Tailwind prefixes like `sm:`, `md:`, `lg:`.
|
|
@@ -131,4 +131,4 @@ project-name/
|
|
|
131
131
|
```
|
|
132
132
|
- **Data Fetching**: Sử dụng `useFetch` với `server: false` cho các tác vụ client-only, hoặc dùng Server Functions để type-safety tốt hơn.
|
|
133
133
|
- **State**: Dùng `defineStore` (Pinia) cho global state, `useState` của Nuxt cho state đơn giản chia sẻ giữa Server/Client.
|
|
134
|
-
- **Type Safety**: Tự động tạo type cho API routes (`$fetch` typed automatically).
|
|
134
|
+
- **Type Safety**: Tự động tạo type cho API routes (`$fetch` typed automatically).
|
|
@@ -116,4 +116,4 @@ project-name/
|
|
|
116
116
|
- **React 19**: Reduce usage of `useMemo` or `useCallback` thanks to React Compiler (if enabled).
|
|
117
117
|
- **Components**: Build UI primitives (Box, Text) with NativeWind className for reusability.
|
|
118
118
|
- **Assets**: Use `expo-image` instead of default `<Image />` for better caching and performance.
|
|
119
|
-
- **API**: Always wrap API calls with TanStack Query, avoid direct calls in `useEffect`.
|
|
119
|
+
- **API**: Always wrap API calls with TanStack Query, avoid direct calls in `useEffect`.
|
package/.agent/skills/doc.md
CHANGED
|
@@ -174,4 +174,4 @@ By creating Skills, you transform a general AI model into an expert for your pro
|
|
|
174
174
|
- ✅ Automatically add license headers
|
|
175
175
|
- ✅ The Agent automatically knows how to work with your team
|
|
176
176
|
|
|
177
|
-
Instead of constantly reminding the AI to "remember to add the license" or "fix the commit format," now the Agent will do it automatically!
|
|
177
|
+
Instead of constantly reminding the AI to "remember to add the license" or "fix the commit format," now the Agent will do it automatically!
|