tribunal-kit 4.3.1 → 4.4.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.
Files changed (67) 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/scripts/_colors.js +18 -18
  10. package/.agent/scripts/_utils.js +42 -42
  11. package/.agent/scripts/append_flow.js +72 -72
  12. package/.agent/scripts/auto_preview.js +197 -197
  13. package/.agent/scripts/bundle_analyzer.js +290 -290
  14. package/.agent/scripts/case_law_manager.js +17 -6
  15. package/.agent/scripts/checklist.js +266 -266
  16. package/.agent/scripts/colors.js +17 -17
  17. package/.agent/scripts/compress_skills.js +141 -141
  18. package/.agent/scripts/consolidate_skills.js +149 -149
  19. package/.agent/scripts/context_broker.js +611 -609
  20. package/.agent/scripts/deep_compress.js +150 -150
  21. package/.agent/scripts/dependency_analyzer.js +272 -272
  22. package/.agent/scripts/graph_builder.js +151 -37
  23. package/.agent/scripts/graph_visualizer.js +384 -0
  24. package/.agent/scripts/inner_loop_validator.js +451 -465
  25. package/.agent/scripts/lint_runner.js +187 -187
  26. package/.agent/scripts/minify_context.js +100 -100
  27. package/.agent/scripts/mutation_runner.js +280 -0
  28. package/.agent/scripts/patch_skills_meta.js +156 -156
  29. package/.agent/scripts/patch_skills_output.js +244 -244
  30. package/.agent/scripts/schema_validator.js +297 -297
  31. package/.agent/scripts/security_scan.js +303 -303
  32. package/.agent/scripts/session_manager.js +276 -276
  33. package/.agent/scripts/skill_evolution.js +644 -644
  34. package/.agent/scripts/skill_integrator.js +313 -313
  35. package/.agent/scripts/strengthen_skills.js +193 -193
  36. package/.agent/scripts/strip_tribunal.js +47 -47
  37. package/.agent/scripts/swarm_dispatcher.js +360 -360
  38. package/.agent/scripts/test_runner.js +193 -193
  39. package/.agent/scripts/utils.js +32 -32
  40. package/.agent/scripts/verify_all.js +257 -256
  41. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +1 -1
  42. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +1 -1
  43. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +1 -1
  44. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +1 -1
  45. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +1 -1
  46. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +1 -1
  47. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +1 -1
  48. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +1 -1
  49. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +1 -1
  50. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +1 -1
  51. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +1 -1
  52. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +1 -1
  53. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +1 -1
  54. package/.agent/skills/doc.md +1 -1
  55. package/.agent/skills/knowledge-graph/SKILL.md +32 -16
  56. package/.agent/skills/testing-patterns/SKILL.md +19 -2
  57. package/.agent/skills/ui-ux-pro-max/SKILL.md +480 -43
  58. package/.agent/workflows/generate.md +183 -183
  59. package/.agent/workflows/tribunal-speed.md +183 -183
  60. package/README.md +1 -1
  61. package/bin/tribunal-kit.js +134 -17
  62. package/package.json +6 -3
  63. package/scripts/changelog.js +167 -167
  64. package/scripts/sync-version.js +81 -81
  65. package/.agent/scripts/__pycache__/_colors.cpython-311.pyc +0 -0
  66. package/.agent/scripts/__pycache__/_utils.cpython-311.pyc +0 -0
  67. package/.agent/scripts/__pycache__/case_law_manager.cpython-311.pyc +0 -0
@@ -1,256 +1,257 @@
1
- #!/usr/bin/env node
2
- /**
3
- * verify_all.js — Full pre-deploy validation suite for the Tribunal Agent Kit.
4
- *
5
- * Runs comprehensive checks before any production deployment.
6
- *
7
- * Usage:
8
- * node .agent/scripts/verify_all.js
9
- * node .agent/scripts/verify_all.js --skip build,deps
10
- */
11
-
12
- 'use strict';
13
-
14
- const fs = require('fs');
15
- const path = require('path');
16
- const { execFileSync } = require('child_process');
17
-
18
- // ━━━ ANSI colors ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
19
- const RED = '\x1b[91m';
20
- const GREEN = '\x1b[92m';
21
- const YELLOW = '\x1b[93m';
22
- const BLUE = '\x1b[94m';
23
- const BOLD = '\x1b[1m';
24
- const RESET = '\x1b[0m';
25
-
26
- const RESULTS = [];
27
-
28
- function section(title) {
29
- console.log(`\n${BOLD}${BLUE}━━━ ${title} ━━━${RESET}`);
30
- }
31
-
32
- function ok(label, note) {
33
- const msg = `${GREEN}✅ ${label}${RESET}` + (note ? ` ${YELLOW}(${note})${RESET}` : '');
34
- console.log(` ${msg}`);
35
- RESULTS.push({ label, passed: true, note: note || '' });
36
- }
37
-
38
- function fail(label, note) {
39
- const noteStr = note ? `\n ${note}` : '';
40
- console.log(` ${RED}❌ ${label}${RESET}${noteStr}`);
41
- RESULTS.push({ label, passed: false, note: note || '' });
42
- }
43
-
44
- function skip(label, reason) {
45
- console.log(` ${YELLOW}⏭️ ${label} — ${reason}${RESET}`);
46
- RESULTS.push({ label, passed: true, note: `skipped: ${reason}` });
47
- }
48
-
49
- /**
50
- * Run a shell command and return true if it exits with code 0.
51
- */
52
- function run(label, cmd, cwd) {
53
- try {
54
- const isWindows = process.platform === 'win32';
55
- let bin = cmd[0];
56
- if (isWindows && (bin === 'npm' || bin === 'npx')) bin += '.cmd';
57
-
58
- execFileSync(bin, cmd.slice(1), {
59
- cwd,
60
- stdio: 'pipe',
61
- timeout: 120000,
62
- encoding: 'utf8',
63
- });
64
- ok(label);
65
- return true;
66
- } catch (err) {
67
- if (err.code === 'ENOENT') {
68
- skip(label, 'tool not installed — skipping');
69
- return true;
70
- }
71
- if (err.killed) {
72
- fail(label, 'timed out after 120s');
73
- return false;
74
- }
75
- const output = ((err.stdout || '') + (err.stderr || '')).trim();
76
- fail(label, output ? output.slice(0, 500) : 'non-zero exit code');
77
- return false;
78
- }
79
- }
80
-
81
-
82
- /**
83
- * Scan source files for obviously hardcoded credentials.
84
- */
85
- function scanSecrets(cwd) {
86
- const patterns = ['password=', 'secret=', 'api_key=', 'private_key=', 'auth_token='];
87
- const found = [];
88
- const skipDirs = new Set(['node_modules', '.git', 'dist', '__pycache__', '.agent']);
89
-
90
- function walk(dir) {
91
- let entries;
92
- try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
93
-
94
- for (const entry of entries) {
95
- const fullPath = path.join(dir, entry.name);
96
- if (entry.isDirectory()) {
97
- if (!skipDirs.has(entry.name)) walk(fullPath);
98
- } else if (entry.isFile()) {
99
- if (!/\.(ts|js|tsx|jsx|py)$/.test(entry.name)) continue;
100
-
101
- let content;
102
- try { content = fs.readFileSync(fullPath, 'utf8'); } catch { continue; }
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
- }
113
- }
114
- }
115
- }
116
-
117
- walk(cwd);
118
-
119
- if (found.length > 0) {
120
- fail('Secret scan', found.slice(0, 5).join('\n '));
121
- return false;
122
- }
123
- ok('Secret scan — no hardcoded credentials found');
124
- return true;
125
- }
126
-
127
-
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
- /**
137
- * Run all verification checks. Returns number of failures.
138
- */
139
- function verifyAll(cwd, skipped) {
140
- let failures = 0;
141
-
142
- section('1 — Secret Scan');
143
- if (!skipped.includes('secrets')) {
144
- if (!scanSecrets(cwd)) failures++;
145
- } else {
146
- skip('Secret scan', 'skipped by flag');
147
- }
148
-
149
- section('2 — TypeScript');
150
- if (!skipped.includes('typescript')) {
151
- if (hasNpm(cwd)) {
152
- if (!run('tsc --noEmit', ['npx', 'tsc', '--noEmit'], cwd)) failures++;
153
- } else {
154
- skip('TypeScript', 'no package.json found in project');
155
- }
156
- } else {
157
- skip('TypeScript', 'skipped by flag');
158
- }
159
-
160
- section('3 — ESLint');
161
- if (!skipped.includes('lint')) {
162
- if (hasNpm(cwd)) {
163
- if (!run('ESLint', ['npx', 'eslint', '.', '--max-warnings=0'], cwd)) failures++;
164
- } else {
165
- skip('ESLint', 'no package.json found in project');
166
- }
167
- } else {
168
- skip('ESLint', 'skipped by flag');
169
- }
170
-
171
- section('4 — Unit Tests');
172
- if (!skipped.includes('tests')) {
173
- if (hasNpm(cwd)) {
174
- if (!run('Test suite', ['npm', 'test', '--', '--passWithNoTests'], cwd)) failures++;
175
- } else {
176
- skip('Tests', 'no package.json found in project');
177
- }
178
- } else {
179
- skip('Tests', 'skipped by flag');
180
- }
181
-
182
- section('5 — Build');
183
- if (!skipped.includes('build')) {
184
- if (hasNpm(cwd)) {
185
- if (!run('npm run build', ['npm', 'run', 'build'], cwd)) failures++;
186
- } else {
187
- skip('Build', 'no package.json found in project');
188
- }
189
- } else {
190
- skip('Build', 'skipped by flag');
191
- }
192
-
193
- section('6 — Dependency Audit');
194
- if (!skipped.includes('deps')) {
195
- if (hasNpm(cwd)) {
196
- if (!run('npm audit', ['npm', 'audit', '--audit-level=high'], cwd)) failures++;
197
- } else {
198
- skip('Dependency audit', 'no package.json found in project');
199
- }
200
- } else {
201
- skip('Dependency audit', 'skipped by flag');
202
- }
203
-
204
- // ━━━ Summary ━━━
205
- console.log(`\n${BOLD}━━━ Summary ━━━${RESET}`);
206
- for (const { label, passed, note } of RESULTS) {
207
- const status = passed ? `${GREEN}✅${RESET}` : `${RED}❌${RESET}`;
208
- const noteStr = (!passed && note) ? ` ${YELLOW}(${note})${RESET}` : '';
209
- console.log(` ${status} ${label}${noteStr}`);
210
- }
211
-
212
- console.log();
213
- if (failures === 0) {
214
- console.log(`${GREEN}${BOLD}All checks passed — safe to deploy.${RESET}`);
215
- } else {
216
- console.log(`${RED}${BOLD}${failures} check(s) failed — fix before deploying.${RESET}`);
217
- }
218
-
219
- return failures;
220
- }
221
-
222
-
223
- /**
224
- * Parse CLI arguments manually (no external dependencies).
225
- */
226
- function parseArgs(argv) {
227
- const args = { skip: [] };
228
- const raw = argv.slice(2);
229
-
230
- for (let i = 0; i < raw.length; i++) {
231
- if (raw[i] === '--skip' && raw[i + 1]) {
232
- args.skip = raw[++i].split(',').map(s => s.trim().toLowerCase()).filter(Boolean);
233
- }
234
- }
235
- return args;
236
- }
237
-
238
-
239
- function main() {
240
- const args = parseArgs(process.argv);
241
- const cwd = process.cwd();
242
-
243
- console.log(`${BOLD}Tribunal — verify_all.js${RESET}`);
244
- console.log(`Project: ${cwd}\n`);
245
-
246
- const failures = verifyAll(cwd, args.skip);
247
- process.exit(failures > 0 ? 1 : 0);
248
- }
249
-
250
-
251
- // ━━━ Exports for testing & programmatic use ━━━
252
- module.exports = { verifyAll, scanSecrets, hasNpm };
253
-
254
- if (require.main === module) {
255
- main();
256
- }
1
+ #!/usr/bin/env node
2
+ /**
3
+ * verify_all.js — Full pre-deploy validation suite for the Tribunal Agent Kit.
4
+ *
5
+ * Runs comprehensive checks before any production deployment.
6
+ *
7
+ * Usage:
8
+ * node .agent/scripts/verify_all.js
9
+ * node .agent/scripts/verify_all.js --skip build,deps
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+ const { execFileSync } = require('child_process');
17
+
18
+ // ━━━ ANSI colors ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
19
+ const RED = '\x1b[91m';
20
+ const GREEN = '\x1b[92m';
21
+ const YELLOW = '\x1b[93m';
22
+ const BLUE = '\x1b[94m';
23
+ const BOLD = '\x1b[1m';
24
+ const RESET = '\x1b[0m';
25
+
26
+ const RESULTS = [];
27
+
28
+ function section(title) {
29
+ console.log(`\n${BOLD}${BLUE}━━━ ${title} ━━━${RESET}`);
30
+ }
31
+
32
+ function ok(label, note) {
33
+ const msg = `${GREEN}✅ ${label}${RESET}` + (note ? ` ${YELLOW}(${note})${RESET}` : '');
34
+ console.log(` ${msg}`);
35
+ RESULTS.push({ label, passed: true, note: note || '' });
36
+ }
37
+
38
+ function fail(label, note) {
39
+ const noteStr = note ? `\n ${note}` : '';
40
+ console.log(` ${RED}❌ ${label}${RESET}${noteStr}`);
41
+ RESULTS.push({ label, passed: false, note: note || '' });
42
+ }
43
+
44
+ function skip(label, reason) {
45
+ console.log(` ${YELLOW}⏭️ ${label} — ${reason}${RESET}`);
46
+ RESULTS.push({ label, passed: true, note: `skipped: ${reason}` });
47
+ }
48
+
49
+ /**
50
+ * Run a shell command and return true if it exits with code 0.
51
+ */
52
+ function run(label, cmd, cwd) {
53
+ try {
54
+ const isWindows = process.platform === 'win32';
55
+ const bin = cmd[0];
56
+
57
+ execFileSync(bin, cmd.slice(1), {
58
+ cwd,
59
+ stdio: 'pipe',
60
+ timeout: 120000,
61
+ encoding: 'utf8',
62
+ shell: isWindows
63
+ });
64
+ ok(label);
65
+ return true;
66
+ } catch (err) {
67
+ if (err.code === 'ENOENT') {
68
+ skip(label, 'tool not installed — skipping');
69
+ return true;
70
+ }
71
+ if (err.killed) {
72
+ fail(label, 'timed out after 120s');
73
+ return false;
74
+ }
75
+ const output = ((err.stdout || '') + (err.stderr || '')).trim();
76
+ fail(label, output ? output.slice(0, 500) : 'non-zero exit code');
77
+ return false;
78
+ }
79
+ }
80
+
81
+
82
+ /**
83
+ * Scan source files for obviously hardcoded credentials.
84
+ */
85
+ function scanSecrets(cwd) {
86
+ const patterns = ['password=', 'secret=', 'api_key=', 'private_key=', 'auth_token='];
87
+ const found = [];
88
+ const skipDirs = new Set(['node_modules', '.git', 'dist', '__pycache__', '.agent']);
89
+
90
+ function walk(dir) {
91
+ let entries;
92
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
93
+
94
+ for (const entry of entries) {
95
+ const fullPath = path.join(dir, entry.name);
96
+ if (entry.isDirectory()) {
97
+ if (!skipDirs.has(entry.name)) walk(fullPath);
98
+ } else if (entry.isFile()) {
99
+ if (!/\.(ts|js|tsx|jsx|py)$/.test(entry.name)) continue;
100
+
101
+ let content;
102
+ try { content = fs.readFileSync(fullPath, 'utf8'); } catch { continue; }
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
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ walk(cwd);
118
+
119
+ if (found.length > 0) {
120
+ fail('Secret scan', found.slice(0, 5).join('\n '));
121
+ return false;
122
+ }
123
+ ok('Secret scan — no hardcoded credentials found');
124
+ return true;
125
+ }
126
+
127
+
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
+ /**
137
+ * Run all verification checks. Returns number of failures.
138
+ */
139
+ function verifyAll(cwd, skipped) {
140
+ let failures = 0;
141
+ RESULTS.length = 0; // Reset for clean runs (prevents accumulation in tests)
142
+
143
+ section('1 — Secret Scan');
144
+ if (!skipped.includes('secrets')) {
145
+ if (!scanSecrets(cwd)) failures++;
146
+ } else {
147
+ skip('Secret scan', 'skipped by flag');
148
+ }
149
+
150
+ section('2 — TypeScript');
151
+ if (!skipped.includes('typescript')) {
152
+ if (hasNpm(cwd)) {
153
+ if (!run('tsc --noEmit', ['npx', 'tsc', '--noEmit'], cwd)) failures++;
154
+ } else {
155
+ skip('TypeScript', 'no package.json found in project');
156
+ }
157
+ } else {
158
+ skip('TypeScript', 'skipped by flag');
159
+ }
160
+
161
+ section('3 — ESLint');
162
+ if (!skipped.includes('lint')) {
163
+ if (hasNpm(cwd)) {
164
+ if (!run('ESLint', ['npx', 'eslint', '.', '--max-warnings=0'], cwd)) failures++;
165
+ } else {
166
+ skip('ESLint', 'no package.json found in project');
167
+ }
168
+ } else {
169
+ skip('ESLint', 'skipped by flag');
170
+ }
171
+
172
+ section('4 — Unit Tests');
173
+ if (!skipped.includes('tests')) {
174
+ if (hasNpm(cwd)) {
175
+ if (!run('Test suite', ['npm', 'test', '--', '--passWithNoTests'], cwd)) failures++;
176
+ } else {
177
+ skip('Tests', 'no package.json found in project');
178
+ }
179
+ } else {
180
+ skip('Tests', 'skipped by flag');
181
+ }
182
+
183
+ section('5 — Build');
184
+ if (!skipped.includes('build')) {
185
+ if (hasNpm(cwd)) {
186
+ if (!run('npm run build', ['npm', 'run', 'build'], cwd)) failures++;
187
+ } else {
188
+ skip('Build', 'no package.json found in project');
189
+ }
190
+ } else {
191
+ skip('Build', 'skipped by flag');
192
+ }
193
+
194
+ section('6 — Dependency Audit');
195
+ if (!skipped.includes('deps')) {
196
+ if (hasNpm(cwd)) {
197
+ if (!run('npm audit', ['npm', 'audit', '--audit-level=high'], cwd)) failures++;
198
+ } else {
199
+ skip('Dependency audit', 'no package.json found in project');
200
+ }
201
+ } else {
202
+ skip('Dependency audit', 'skipped by flag');
203
+ }
204
+
205
+ // ━━━ Summary ━━━
206
+ console.log(`\n${BOLD}━━━ Summary ━━━${RESET}`);
207
+ for (const { label, passed, note } of RESULTS) {
208
+ const status = passed ? `${GREEN}✅${RESET}` : `${RED}❌${RESET}`;
209
+ const noteStr = (!passed && note) ? ` ${YELLOW}(${note})${RESET}` : '';
210
+ console.log(` ${status} ${label}${noteStr}`);
211
+ }
212
+
213
+ console.log();
214
+ if (failures === 0) {
215
+ console.log(`${GREEN}${BOLD}All checks passed — safe to deploy.${RESET}`);
216
+ } else {
217
+ console.log(`${RED}${BOLD}${failures} check(s) failed — fix before deploying.${RESET}`);
218
+ }
219
+
220
+ return failures;
221
+ }
222
+
223
+
224
+ /**
225
+ * Parse CLI arguments manually (no external dependencies).
226
+ */
227
+ function parseArgs(argv) {
228
+ const args = { skip: [] };
229
+ const raw = argv.slice(2);
230
+
231
+ for (let i = 0; i < raw.length; i++) {
232
+ if (raw[i] === '--skip' && raw[i + 1]) {
233
+ args.skip = raw[++i].split(',').map(s => s.trim().toLowerCase()).filter(Boolean);
234
+ }
235
+ }
236
+ return args;
237
+ }
238
+
239
+
240
+ function main() {
241
+ const args = parseArgs(process.argv);
242
+ const cwd = process.cwd();
243
+
244
+ console.log(`${BOLD}Tribunal — verify_all.js${RESET}`);
245
+ console.log(`Project: ${cwd}\n`);
246
+
247
+ const failures = verifyAll(cwd, args.skip);
248
+ process.exit(failures > 0 ? 1 : 0);
249
+ }
250
+
251
+
252
+ // ━━━ Exports for testing & programmatic use ━━━
253
+ module.exports = { verifyAll, scanSecrets, hasNpm };
254
+
255
+ if (require.main === module) {
256
+ main();
257
+ }
@@ -73,4 +73,4 @@ project-name/
73
73
  - Use Content Collections for type safety
74
74
  - Leverage static generation
75
75
  - Add islands only where needed
76
- - Optimize images with Astro Image
76
+ - Optimize images with Astro Image
@@ -89,4 +89,4 @@ project-name/
89
89
  - Use type-safe messaging
90
90
  - Wrap Chrome APIs in promises
91
91
  - Minimize permissions
92
- - Handle offline gracefully
92
+ - Handle offline gracefully
@@ -85,4 +85,4 @@ npm publish
85
85
  - Support both interactive and non-interactive modes
86
86
  - Use consistent output styling
87
87
  - Validate inputs with Zod
88
- - Exit with proper codes (0 success, 1 error)
88
+ - Exit with proper codes (0 success, 1 error)
@@ -85,4 +85,4 @@ project-name/
85
85
  - Type-safe IPC with typed handlers
86
86
  - Custom title bar for native feel
87
87
  - Handle window state (maximize, minimize)
88
- - Auto-updates with electron-updater
88
+ - Auto-updates with electron-updater
@@ -80,4 +80,4 @@ project-name/
80
80
  - Validate all inputs with Zod
81
81
  - Centralized error handling
82
82
  - Environment-based config
83
- - Use Prisma for type-safe DB access
83
+ - Use Prisma for type-safe DB access
@@ -87,4 +87,4 @@ project_name/
87
87
  - Riverpod for state, React Query pattern for server state
88
88
  - Freezed for immutable data classes
89
89
  - Go Router for declarative navigation
90
- - Material 3 theming
90
+ - Material 3 theming
@@ -87,4 +87,4 @@ project-name/
87
87
  - Shared configs in packages/config
88
88
  - Shared types in packages/types
89
89
  - Internal packages with `workspace:*`
90
- - Use Turbo remote caching for CI
90
+ - Use Turbo remote caching for CI
@@ -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.
@@ -119,4 +119,4 @@ project-name/
119
119
  7. Run project:
120
120
  ```bash
121
121
  npm run dev
122
- ```
122
+ ```
@@ -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).
@@ -80,4 +80,4 @@ project-name/
80
80
  - Pydantic v2 for validation
81
81
  - SQLAlchemy 2.0 async sessions
82
82
  - Alembic for migrations
83
- - pytest-asyncio for tests
83
+ - pytest-asyncio for tests
@@ -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`.
@@ -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!