jdi-cli 0.1.0

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 (159) hide show
  1. package/AGENTS.md +209 -0
  2. package/ARCHITECTURE.md +210 -0
  3. package/COMMANDS.md +241 -0
  4. package/CREATE-EXAMPLE.md +385 -0
  5. package/CREATE.md +315 -0
  6. package/EXTENSION.md +141 -0
  7. package/LICENSE +21 -0
  8. package/MEMORY.md +471 -0
  9. package/PORTABILITY.md +438 -0
  10. package/README.md +789 -0
  11. package/bin/git-hooks/post-commit +16 -0
  12. package/bin/git-hooks/pre-commit +21 -0
  13. package/bin/jdi-build.ps1 +381 -0
  14. package/bin/jdi-build.sh +332 -0
  15. package/bin/jdi-doctor.ps1 +403 -0
  16. package/bin/jdi-doctor.sh +400 -0
  17. package/bin/jdi-install-caveman.ps1 +97 -0
  18. package/bin/jdi-install-caveman.sh +99 -0
  19. package/bin/jdi-install-playwright.ps1 +319 -0
  20. package/bin/jdi-install-playwright.sh +284 -0
  21. package/bin/jdi-install.ps1 +154 -0
  22. package/bin/jdi-install.sh +132 -0
  23. package/bin/jdi-uninstall.ps1 +309 -0
  24. package/bin/jdi-uninstall.sh +264 -0
  25. package/bin/jdi-update.ps1 +215 -0
  26. package/bin/jdi-update.sh +209 -0
  27. package/bin/jdi.js +460 -0
  28. package/bin/lib/jdi-monitor.ps1 +66 -0
  29. package/bin/lib/jdi-monitor.sh +74 -0
  30. package/bin/lib/jdi-truncate.ps1 +96 -0
  31. package/bin/lib/jdi-truncate.sh +99 -0
  32. package/bin/lib/ui.js +197 -0
  33. package/core/agents/jdi-adopter.md +465 -0
  34. package/core/agents/jdi-architect.md +894 -0
  35. package/core/agents/jdi-asker.md +153 -0
  36. package/core/agents/jdi-bootstrap.md +247 -0
  37. package/core/agents/jdi-planner.md +254 -0
  38. package/core/agents/jdi-researcher.md +303 -0
  39. package/core/commands/jdi-adopt.md +155 -0
  40. package/core/commands/jdi-bootstrap.md +81 -0
  41. package/core/commands/jdi-create.md +80 -0
  42. package/core/commands/jdi-discuss.md +80 -0
  43. package/core/commands/jdi-do.md +200 -0
  44. package/core/commands/jdi-loop.md +315 -0
  45. package/core/commands/jdi-new.md +131 -0
  46. package/core/commands/jdi-plan.md +73 -0
  47. package/core/commands/jdi-ship.md +146 -0
  48. package/core/commands/jdi-verify.md +159 -0
  49. package/core/skills/clean-code/SKILL.md +261 -0
  50. package/core/skills/dry/SKILL.md +150 -0
  51. package/core/skills/frontend-rules/SKILL.md +386 -0
  52. package/core/skills/frontend-validator/SKILL.md +567 -0
  53. package/core/skills/kiss/SKILL.md +178 -0
  54. package/core/skills/solid/SKILL.md +281 -0
  55. package/core/skills/yagni/SKILL.md +207 -0
  56. package/core/templates/agent.md +72 -0
  57. package/core/templates/doer-specialist.md +216 -0
  58. package/core/templates/reviewer-specialist.md +405 -0
  59. package/core/templates/skill.md +66 -0
  60. package/package.json +70 -0
  61. package/runtimes/antigravity/agents.md +74 -0
  62. package/runtimes/antigravity/skills/clean-code/SKILL.md +252 -0
  63. package/runtimes/antigravity/skills/dry/SKILL.md +141 -0
  64. package/runtimes/antigravity/skills/frontend-rules/SKILL.md +376 -0
  65. package/runtimes/antigravity/skills/frontend-validator/SKILL.md +559 -0
  66. package/runtimes/antigravity/skills/jdi-adopt/SKILL.md +155 -0
  67. package/runtimes/antigravity/skills/jdi-adopter/SKILL.md +436 -0
  68. package/runtimes/antigravity/skills/jdi-architect/SKILL.md +872 -0
  69. package/runtimes/antigravity/skills/jdi-asker/SKILL.md +125 -0
  70. package/runtimes/antigravity/skills/jdi-asker/references/context-template.md +34 -0
  71. package/runtimes/antigravity/skills/jdi-asker/references/decision-format.md +19 -0
  72. package/runtimes/antigravity/skills/jdi-asker/scripts/find_phase_dir.sh +25 -0
  73. package/runtimes/antigravity/skills/jdi-bootstrap/SKILL.md +81 -0
  74. package/runtimes/antigravity/skills/jdi-create/SKILL.md +80 -0
  75. package/runtimes/antigravity/skills/jdi-discuss/SKILL.md +80 -0
  76. package/runtimes/antigravity/skills/jdi-discuss/scripts/run_command.sh +62 -0
  77. package/runtimes/antigravity/skills/jdi-do/SKILL.md +200 -0
  78. package/runtimes/antigravity/skills/jdi-loop/SKILL.md +315 -0
  79. package/runtimes/antigravity/skills/jdi-new/SKILL.md +131 -0
  80. package/runtimes/antigravity/skills/jdi-plan/SKILL.md +73 -0
  81. package/runtimes/antigravity/skills/jdi-planner/SKILL.md +225 -0
  82. package/runtimes/antigravity/skills/jdi-researcher/SKILL.md +274 -0
  83. package/runtimes/antigravity/skills/jdi-ship/SKILL.md +146 -0
  84. package/runtimes/antigravity/skills/jdi-verify/SKILL.md +159 -0
  85. package/runtimes/antigravity/skills/kiss/SKILL.md +169 -0
  86. package/runtimes/antigravity/skills/solid/SKILL.md +272 -0
  87. package/runtimes/antigravity/skills/yagni/SKILL.md +198 -0
  88. package/runtimes/claude/CLAUDE.md +91 -0
  89. package/runtimes/claude/agents/jdi-adopter.md +430 -0
  90. package/runtimes/claude/agents/jdi-architect.md +864 -0
  91. package/runtimes/claude/agents/jdi-asker.md +119 -0
  92. package/runtimes/claude/agents/jdi-bootstrap.md +213 -0
  93. package/runtimes/claude/agents/jdi-planner.md +221 -0
  94. package/runtimes/claude/agents/jdi-researcher.md +269 -0
  95. package/runtimes/claude/commands/jdi-adopt.md +155 -0
  96. package/runtimes/claude/commands/jdi-bootstrap.md +81 -0
  97. package/runtimes/claude/commands/jdi-create.md +80 -0
  98. package/runtimes/claude/commands/jdi-discuss.md +80 -0
  99. package/runtimes/claude/commands/jdi-do.md +200 -0
  100. package/runtimes/claude/commands/jdi-loop.md +315 -0
  101. package/runtimes/claude/commands/jdi-new.md +131 -0
  102. package/runtimes/claude/commands/jdi-plan.md +73 -0
  103. package/runtimes/claude/commands/jdi-ship.md +146 -0
  104. package/runtimes/claude/commands/jdi-verify.md +159 -0
  105. package/runtimes/claude/settings.example.json +132 -0
  106. package/runtimes/claude/skills/clean-code/SKILL.md +247 -0
  107. package/runtimes/claude/skills/dry/SKILL.md +136 -0
  108. package/runtimes/claude/skills/frontend-rules/SKILL.md +369 -0
  109. package/runtimes/claude/skills/frontend-validator/SKILL.md +553 -0
  110. package/runtimes/claude/skills/kiss/SKILL.md +164 -0
  111. package/runtimes/claude/skills/solid/SKILL.md +267 -0
  112. package/runtimes/claude/skills/yagni/SKILL.md +193 -0
  113. package/runtimes/copilot/agents/jdi-adopter.agent.md +430 -0
  114. package/runtimes/copilot/agents/jdi-architect.agent.md +864 -0
  115. package/runtimes/copilot/agents/jdi-asker.agent.md +119 -0
  116. package/runtimes/copilot/agents/jdi-bootstrap.agent.md +213 -0
  117. package/runtimes/copilot/agents/jdi-planner.agent.md +221 -0
  118. package/runtimes/copilot/agents/jdi-researcher.agent.md +269 -0
  119. package/runtimes/copilot/copilot-instructions.md +80 -0
  120. package/runtimes/copilot/prompts/jdi-adopt.prompt.md +155 -0
  121. package/runtimes/copilot/prompts/jdi-bootstrap.prompt.md +81 -0
  122. package/runtimes/copilot/prompts/jdi-create.prompt.md +80 -0
  123. package/runtimes/copilot/prompts/jdi-discuss.prompt.md +80 -0
  124. package/runtimes/copilot/prompts/jdi-do.prompt.md +200 -0
  125. package/runtimes/copilot/prompts/jdi-loop.prompt.md +315 -0
  126. package/runtimes/copilot/prompts/jdi-new.prompt.md +131 -0
  127. package/runtimes/copilot/prompts/jdi-plan.prompt.md +73 -0
  128. package/runtimes/copilot/prompts/jdi-ship.prompt.md +146 -0
  129. package/runtimes/copilot/prompts/jdi-verify.prompt.md +159 -0
  130. package/runtimes/opencode/AGENTS.md +87 -0
  131. package/runtimes/opencode/agents/jdi-adopter.md +434 -0
  132. package/runtimes/opencode/agents/jdi-architect.md +861 -0
  133. package/runtimes/opencode/agents/jdi-asker.md +123 -0
  134. package/runtimes/opencode/agents/jdi-bootstrap.md +217 -0
  135. package/runtimes/opencode/agents/jdi-planner.md +225 -0
  136. package/runtimes/opencode/agents/jdi-researcher.md +273 -0
  137. package/runtimes/opencode/commands/jdi-adopt.md +155 -0
  138. package/runtimes/opencode/commands/jdi-bootstrap.md +81 -0
  139. package/runtimes/opencode/commands/jdi-create.md +80 -0
  140. package/runtimes/opencode/commands/jdi-discuss.md +80 -0
  141. package/runtimes/opencode/commands/jdi-do.md +200 -0
  142. package/runtimes/opencode/commands/jdi-loop.md +315 -0
  143. package/runtimes/opencode/commands/jdi-new.md +131 -0
  144. package/runtimes/opencode/commands/jdi-plan.md +73 -0
  145. package/runtimes/opencode/commands/jdi-ship.md +146 -0
  146. package/runtimes/opencode/commands/jdi-verify.md +159 -0
  147. package/runtimes/opencode/opencode.example.jsonc +169 -0
  148. package/runtimes/opencode/skills/clean-code/SKILL.md +247 -0
  149. package/runtimes/opencode/skills/dry/SKILL.md +136 -0
  150. package/runtimes/opencode/skills/frontend-rules/SKILL.md +369 -0
  151. package/runtimes/opencode/skills/frontend-validator/SKILL.md +553 -0
  152. package/runtimes/opencode/skills/kiss/SKILL.md +164 -0
  153. package/runtimes/opencode/skills/solid/SKILL.md +267 -0
  154. package/runtimes/opencode/skills/yagni/SKILL.md +193 -0
  155. package/templates-jdi-folder/config.json +18 -0
  156. package/templates-jdi-folder/registry.md +31 -0
  157. package/templates-jdi-folder/reviewers.md +33 -0
  158. package/templates-jdi-folder/skills-registry.md +32 -0
  159. package/templates-jdi-folder/specialists.md +39 -0
package/bin/jdi.js ADDED
@@ -0,0 +1,460 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { spawn, spawnSync } = require('child_process');
7
+ const ui = require('./lib/ui');
8
+ const { c, sym } = ui;
9
+
10
+ const VERSION = require('../package.json').version;
11
+ const PKG_ROOT = path.resolve(__dirname, '..');
12
+ const isWindows = process.platform === 'win32';
13
+
14
+ const VALID_RUNTIMES = ['claude', 'copilot', 'antigravity', 'opencode', 'all'];
15
+ const VALID_SCOPES = ['user', 'project'];
16
+
17
+ // =================================================================
18
+ // Argument parsing — minimal, no deps
19
+ // =================================================================
20
+
21
+ function parseArgs(argv) {
22
+ const args = argv.slice(2);
23
+ if (args.length === 0) return { cmd: 'help' };
24
+
25
+ const cmd = args[0];
26
+ const rest = args.slice(1);
27
+ const flags = {};
28
+ const positional = [];
29
+
30
+ for (let i = 0; i < rest.length; i++) {
31
+ const a = rest[i];
32
+ if (a === '--scope' || a === '-s') {
33
+ flags.scope = rest[++i];
34
+ } else if (a === '--verbose' || a === '-v') {
35
+ flags.verbose = true;
36
+ } else if (a === '--help' || a === '-h') {
37
+ flags.help = true;
38
+ } else if (a === '--version') {
39
+ flags.version = true;
40
+ } else if (a === '--no-color') {
41
+ flags.noColor = true;
42
+ } else if (a.startsWith('--')) {
43
+ const [k, v] = a.slice(2).split('=');
44
+ flags[k] = v === undefined ? true : v;
45
+ } else {
46
+ positional.push(a);
47
+ }
48
+ }
49
+
50
+ return { cmd, positional, flags };
51
+ }
52
+
53
+ // =================================================================
54
+ // Spawn helpers — delegate to .sh / .ps1
55
+ // =================================================================
56
+
57
+ function getScriptPath(name) {
58
+ const ext = isWindows ? '.ps1' : '.sh';
59
+ return path.join(PKG_ROOT, 'bin', `${name}${ext}`);
60
+ }
61
+
62
+ function runShellScript(scriptName, scriptArgs = []) {
63
+ const scriptPath = getScriptPath(scriptName);
64
+
65
+ if (!fs.existsSync(scriptPath)) {
66
+ ui.fail(`Script nao encontrado: ${scriptPath}`);
67
+ return { code: 1 };
68
+ }
69
+
70
+ let cmd, args;
71
+ if (isWindows) {
72
+ cmd = 'powershell.exe';
73
+ args = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, ...scriptArgs];
74
+ } else {
75
+ cmd = 'bash';
76
+ args = [scriptPath, ...scriptArgs];
77
+ }
78
+
79
+ const result = spawnSync(cmd, args, {
80
+ stdio: 'inherit',
81
+ cwd: process.cwd(),
82
+ });
83
+
84
+ return { code: result.status ?? 0 };
85
+ }
86
+
87
+ // =================================================================
88
+ // Validation helpers
89
+ // =================================================================
90
+
91
+ function ensureRuntime(runtime) {
92
+ if (!runtime) {
93
+ ui.fail('Runtime obrigatorio.');
94
+ console.log('');
95
+ console.log(` Uso: ${c.cyan}jdi install <runtime> [--scope user|project]${c.reset}`);
96
+ console.log(` Runtimes: ${VALID_RUNTIMES.join(', ')}`);
97
+ console.log('');
98
+ process.exit(1);
99
+ }
100
+ if (!VALID_RUNTIMES.includes(runtime)) {
101
+ ui.fail(`Runtime invalido: ${runtime}`);
102
+ console.log(` Validos: ${VALID_RUNTIMES.join(', ')}`);
103
+ process.exit(1);
104
+ }
105
+ }
106
+
107
+ function ensureScope(scope) {
108
+ if (scope && !VALID_SCOPES.includes(scope)) {
109
+ ui.fail(`Scope invalido: ${scope}`);
110
+ console.log(` Validos: ${VALID_SCOPES.join(', ')}`);
111
+ process.exit(1);
112
+ }
113
+ }
114
+
115
+ // =================================================================
116
+ // Commands
117
+ // =================================================================
118
+
119
+ function cmdInstall({ positional, flags }) {
120
+ const runtime = positional[0];
121
+ const scope = flags.scope || 'project';
122
+
123
+ ensureRuntime(runtime);
124
+ ensureScope(scope);
125
+
126
+ ui.banner();
127
+
128
+ ui.header(`Instalando JDI para ${c.bold}${runtime}${c.reset}`);
129
+ ui.info(`Diretorio: ${c.dim}${process.cwd()}${c.reset}`);
130
+ ui.info(`Scope: ${c.dim}${scope}${c.reset}`);
131
+ ui.info(`Plataforma: ${c.dim}${process.platform} (${isWindows ? 'PowerShell' : 'bash'})${c.reset}`);
132
+ console.log('');
133
+
134
+ const args = isWindows
135
+ ? ['-Runtime', runtime, '-Scope', scope]
136
+ : [runtime, '--scope', scope];
137
+
138
+ const sp = ui.spinner(`Instalando adapters em ${runtime}...`);
139
+ sp.stop();
140
+
141
+ const { code } = runShellScript('jdi-install', args);
142
+
143
+ if (code === 0) {
144
+ ui.successSummary('JDI instalado com sucesso', [
145
+ `${sym.success} Runtime: ${c.bold}${runtime}${c.reset}`,
146
+ `${sym.success} Scope: ${c.bold}${scope}${c.reset}`,
147
+ `${sym.success} Diretorio: ${c.dim}${process.cwd()}${c.reset}`,
148
+ ]);
149
+
150
+ const nextStepList = [
151
+ `Abre teu runtime (${runtime}) no diretorio do projeto`,
152
+ `Roda ${c.cyan}/jdi-new "<descricao do projeto>"${c.reset} pra inicializar`,
153
+ `Depois ${c.cyan}/jdi-bootstrap${c.reset} pra criar specialists per-project`,
154
+ `Comando ${c.cyan}npx jdi-cli doctor${c.reset} pra diagnostico`,
155
+ ];
156
+ ui.nextSteps(nextStepList);
157
+ } else {
158
+ ui.errorSummary('Instalacao falhou', [
159
+ `${sym.error} Exit code: ${code}`,
160
+ `${sym.info} Tente ${c.cyan}npx jdi-cli doctor${c.reset} pra diagnostico`,
161
+ ]);
162
+ process.exit(code);
163
+ }
164
+ }
165
+
166
+ function cmdBuild({ flags }) {
167
+ ui.banner();
168
+
169
+ ui.header('Building JDI runtimes');
170
+ ui.info(`Source: ${c.dim}${PKG_ROOT}/core/${c.reset}`);
171
+ ui.info(`Output: ${c.dim}${PKG_ROOT}/runtimes/${c.reset}`);
172
+ console.log('');
173
+
174
+ const { code } = runShellScript('jdi-build');
175
+
176
+ if (code === 0) {
177
+ ui.successSummary('Build completo', [
178
+ `${sym.success} 4 runtimes gerados (claude, copilot, antigravity, opencode)`,
179
+ `${sym.success} Adapters em ${c.dim}runtimes/${c.reset}`,
180
+ ]);
181
+ ui.nextSteps([
182
+ `Instala em projeto: ${c.cyan}npx jdi-cli install <runtime>${c.reset}`,
183
+ `Diagnostico: ${c.cyan}npx jdi-cli doctor${c.reset}`,
184
+ ]);
185
+ } else {
186
+ ui.errorSummary('Build falhou', [`${sym.error} Exit code: ${code}`]);
187
+ process.exit(code);
188
+ }
189
+ }
190
+
191
+ function cmdUpdate({ flags }) {
192
+ ui.banner();
193
+
194
+ ui.header('JDI Update');
195
+ ui.info(`Diretorio: ${c.dim}${process.cwd()}${c.reset}`);
196
+ console.log('');
197
+
198
+ const args = [];
199
+ if (isWindows) {
200
+ if (flags['force-specialists']) args.push('-ForceSpecialists');
201
+ if (flags['skip-specialists']) args.push('-SkipSpecialists');
202
+ if (flags['dry-run']) args.push('-DryRun');
203
+ } else {
204
+ if (flags['force-specialists']) args.push('--force-specialists');
205
+ if (flags['skip-specialists']) args.push('--skip-specialists');
206
+ if (flags['dry-run']) args.push('--dry-run');
207
+ }
208
+
209
+ const { code } = runShellScript('jdi-update', args);
210
+
211
+ if (code !== 0) {
212
+ process.exit(code);
213
+ }
214
+ }
215
+
216
+ function cmdUninstall({ positional, flags }) {
217
+ ui.banner();
218
+
219
+ ui.header('JDI Uninstall');
220
+ ui.info(`Diretorio: ${c.dim}${process.cwd()}${c.reset}`);
221
+ console.log('');
222
+
223
+ const runtime = positional[0] || 'all';
224
+ ensureRuntime(runtime);
225
+
226
+ const args = [];
227
+ if (isWindows) {
228
+ args.push('-Runtime', runtime);
229
+ if (flags.scope) args.push('-Scope', flags.scope);
230
+ if (flags.purge) args.push('-Purge');
231
+ if (flags.yes) args.push('-Yes');
232
+ if (flags['dry-run']) args.push('-DryRun');
233
+ } else {
234
+ args.push('--runtime', runtime);
235
+ if (flags.scope) args.push('--scope', flags.scope);
236
+ if (flags.purge) args.push('--purge');
237
+ if (flags.yes) args.push('--yes');
238
+ if (flags['dry-run']) args.push('--dry-run');
239
+ }
240
+
241
+ const { code } = runShellScript('jdi-uninstall', args);
242
+
243
+ if (code !== 0) {
244
+ process.exit(code);
245
+ }
246
+ }
247
+
248
+ function cmdInstallPlaywright({ flags }) {
249
+ ui.banner();
250
+
251
+ ui.header('JDI: Install Playwright + MCP');
252
+ ui.info(`Directory: ${c.dim}${process.cwd()}${c.reset}`);
253
+ console.log('');
254
+
255
+ const args = [];
256
+ if (isWindows) {
257
+ if (flags['skip-browser']) args.push('-SkipBrowser');
258
+ if (flags['skip-mcp']) args.push('-SkipMcp');
259
+ if (flags.runtime) args.push('-Runtime', flags.runtime);
260
+ } else {
261
+ if (flags['skip-browser']) args.push('--skip-browser');
262
+ if (flags['skip-mcp']) args.push('--skip-mcp');
263
+ if (flags.runtime) args.push('--runtime', flags.runtime);
264
+ }
265
+
266
+ const { code } = runShellScript('jdi-install-playwright', args);
267
+
268
+ if (code === 0) {
269
+ ui.successSummary('Playwright + MCP ready', [
270
+ `${sym.success} @playwright/test installed`,
271
+ `${sym.success} chromium browser ${flags['skip-browser'] ? 'skipped' : 'installed'}`,
272
+ `${sym.success} MCP config ${flags['skip-mcp'] ? 'skipped' : 'injected (where runtime present)'}`,
273
+ ]);
274
+ ui.nextSteps([
275
+ `Restart your runtime to pick up MCP changes`,
276
+ `Claude Code: ${c.cyan}/mcp${c.reset} to verify`,
277
+ `OpenCode: ${c.cyan}opencode reload${c.reset}`,
278
+ ]);
279
+ } else {
280
+ ui.errorSummary('Playwright install failed', [`${sym.error} Exit code: ${code}`]);
281
+ process.exit(code);
282
+ }
283
+ }
284
+
285
+ function cmdInstallCaveman({ flags }) {
286
+ ui.banner();
287
+
288
+ ui.header('JDI: Install Caveman plugin');
289
+ ui.info(`Directory: ${c.dim}${process.cwd()}${c.reset}`);
290
+ console.log('');
291
+
292
+ const args = [];
293
+ if (isWindows) {
294
+ if (flags.repo) args.push('-Repo', flags.repo);
295
+ if (flags.scope) args.push('-Scope', flags.scope);
296
+ if (flags.force) args.push('-Force');
297
+ } else {
298
+ if (flags.repo) args.push('--repo', flags.repo);
299
+ if (flags.scope) args.push('--scope', flags.scope);
300
+ if (flags.force) args.push('--force');
301
+ }
302
+
303
+ const { code } = runShellScript('jdi-install-caveman', args);
304
+
305
+ if (code === 0) {
306
+ ui.successSummary('Caveman ready', [
307
+ `${sym.success} Plugin cloned`,
308
+ `${sym.info} Restart Claude Code to load`,
309
+ ]);
310
+ ui.nextSteps([
311
+ `Verify: ${c.cyan}/caveman-help${c.reset}`,
312
+ `Toggle mode: ${c.cyan}/caveman lite|full|ultra${c.reset}`,
313
+ ]);
314
+ } else {
315
+ ui.errorSummary('Caveman install failed', [`${sym.error} Exit code: ${code}`]);
316
+ process.exit(code);
317
+ }
318
+ }
319
+
320
+ function cmdDoctor({ flags }) {
321
+ ui.banner();
322
+
323
+ ui.header('JDI Doctor');
324
+ ui.info(`Diretorio atual: ${c.dim}${process.cwd()}${c.reset}`);
325
+ console.log('');
326
+
327
+ const args = flags.verbose ? (isWindows ? ['-Verbose'] : ['--verbose']) : [];
328
+ const { code } = runShellScript('jdi-doctor', args);
329
+
330
+ if (code !== 0) {
331
+ process.exit(code);
332
+ }
333
+ }
334
+
335
+ function cmdHelp() {
336
+ ui.banner();
337
+
338
+ console.log(`${c.bold}Uso:${c.reset}`);
339
+ console.log(` ${c.cyan}npx jdi-cli <comando> [opcoes]${c.reset}`);
340
+ console.log('');
341
+
342
+ console.log(`${c.bold}Comandos:${c.reset}`);
343
+ console.log(` ${c.cyan}install${c.reset} ${c.gray}<runtime>${c.reset} Instala JDI no projeto atual`);
344
+ console.log(` ${c.cyan}update${c.reset} Atualiza JDI ja instalado (preserva state)`);
345
+ console.log(` ${c.cyan}uninstall${c.reset} ${c.gray}[runtime]${c.reset} Remove JDI do projeto (preserva .jdi/ por default)`);
346
+ console.log(` ${c.cyan}build${c.reset} Re-builda runtimes/ a partir de core/`);
347
+ console.log(` ${c.cyan}doctor${c.reset} Diagnostico do projeto + JDI`);
348
+ console.log(` ${c.cyan}install-playwright${c.reset} Instala @playwright/test + chromium + MCP config`);
349
+ console.log(` ${c.cyan}install-caveman${c.reset} Instala plugin caveman (modo ultra-compresso)`);
350
+ console.log(` ${c.cyan}help${c.reset} Mostra esta ajuda`);
351
+ console.log(` ${c.cyan}--version${c.reset} Mostra versao`);
352
+ console.log('');
353
+
354
+ console.log(`${c.bold}Runtimes (install):${c.reset}`);
355
+ console.log(` ${c.cyan}claude${c.reset} Claude Code`);
356
+ console.log(` ${c.cyan}copilot${c.reset} GitHub Copilot`);
357
+ console.log(` ${c.cyan}antigravity${c.reset} Google Antigravity`);
358
+ console.log(` ${c.cyan}opencode${c.reset} OpenCode`);
359
+ console.log(` ${c.cyan}all${c.reset} Todos os 4`);
360
+ console.log('');
361
+
362
+ console.log(`${c.bold}Opcoes:${c.reset}`);
363
+ console.log(` ${c.cyan}--scope${c.reset} ${c.gray}<user|project|both>${c.reset} Escopo (default install: project; default uninstall: both)`);
364
+ console.log(` ${c.cyan}--verbose${c.reset} Output detalhado (so doctor)`);
365
+ console.log(` ${c.cyan}--dry-run${c.reset} Mostra o que faria sem aplicar (update, uninstall)`);
366
+ console.log(` ${c.cyan}--purge${c.reset} Uninstall: remove tambem .jdi/ (DESTRUTIVO)`);
367
+ console.log(` ${c.cyan}--yes${c.reset} Uninstall: pula confirmacoes interativas`);
368
+ console.log(` ${c.cyan}--force-specialists${c.reset} Update: regenera specialists sem perguntar`);
369
+ console.log(` ${c.cyan}--skip-specialists${c.reset} Update: nao mexe em specialists`);
370
+ console.log(` ${c.cyan}--no-color${c.reset} Desabilita cores ANSI`);
371
+ console.log(` ${c.cyan}-h, --help${c.reset} Esta ajuda`);
372
+ console.log('');
373
+
374
+ console.log(`${c.bold}Exemplos:${c.reset}`);
375
+ console.log(` ${c.dim}# Instalacao no projeto atual${c.reset}`);
376
+ console.log(` ${c.cyan}npx jdi-cli@latest install opencode${c.reset}`);
377
+ console.log('');
378
+ console.log(` ${c.dim}# Atualizar projeto ja instalado pra versao mais recente${c.reset}`);
379
+ console.log(` ${c.cyan}npx jdi-cli@latest update${c.reset}`);
380
+ console.log('');
381
+ console.log(` ${c.dim}# Preview do que update faria${c.reset}`);
382
+ console.log(` ${c.cyan}npx jdi-cli@latest update --dry-run${c.reset}`);
383
+ console.log('');
384
+ console.log(` ${c.dim}# Desinstalar (preserva .jdi/ state)${c.reset}`);
385
+ console.log(` ${c.cyan}npx jdi-cli@latest uninstall${c.reset}`);
386
+ console.log('');
387
+ console.log(` ${c.dim}# Desinstalar tudo, incluindo state files${c.reset}`);
388
+ console.log(` ${c.cyan}npx jdi-cli@latest uninstall --purge --yes${c.reset}`);
389
+ console.log('');
390
+ console.log(` ${c.dim}# Diagnostico${c.reset}`);
391
+ console.log(` ${c.cyan}npx jdi-cli@latest doctor${c.reset}`);
392
+ console.log('');
393
+
394
+ console.log(`${c.bold}Saiba mais:${c.reset} ${c.cyan}https://github.com/<owner>/jdi${c.reset}`);
395
+ console.log('');
396
+ }
397
+
398
+ function cmdVersion() {
399
+ console.log(`jdi-cli ${c.bold}v${VERSION}${c.reset}`);
400
+ }
401
+
402
+ // =================================================================
403
+ // Main dispatcher
404
+ // =================================================================
405
+
406
+ function main() {
407
+ const parsed = parseArgs(process.argv);
408
+
409
+ if (parsed.flags && parsed.flags.noColor) {
410
+ process.env.NO_COLOR = '1';
411
+ }
412
+
413
+ if (parsed.flags && parsed.flags.version) {
414
+ cmdVersion();
415
+ return;
416
+ }
417
+
418
+ switch (parsed.cmd) {
419
+ case 'install':
420
+ cmdInstall(parsed);
421
+ break;
422
+ case 'update':
423
+ case 'upgrade':
424
+ cmdUpdate(parsed);
425
+ break;
426
+ case 'uninstall':
427
+ case 'remove':
428
+ cmdUninstall(parsed);
429
+ break;
430
+ case 'build':
431
+ cmdBuild(parsed);
432
+ break;
433
+ case 'install-playwright':
434
+ case 'playwright':
435
+ cmdInstallPlaywright(parsed);
436
+ break;
437
+ case 'install-caveman':
438
+ case 'caveman':
439
+ cmdInstallCaveman(parsed);
440
+ break;
441
+ case 'doctor':
442
+ cmdDoctor(parsed);
443
+ break;
444
+ case 'help':
445
+ case '--help':
446
+ case '-h':
447
+ cmdHelp();
448
+ break;
449
+ case '--version':
450
+ case '-V':
451
+ cmdVersion();
452
+ break;
453
+ default:
454
+ ui.fail(`Comando desconhecido: ${parsed.cmd}`);
455
+ console.log(` Use ${c.cyan}npx jdi-cli help${c.reset} pra ver comandos disponiveis.`);
456
+ process.exit(1);
457
+ }
458
+ }
459
+
460
+ main();
@@ -0,0 +1,66 @@
1
+ # jdi-monitor.ps1 — context budget monitor (heuristica)
2
+ #
3
+ # Uso:
4
+ # pwsh -File jdi-monitor.ps1 -Paths @("a.md","b.md")
5
+ #
6
+ # Estima tokens consumidos por leitura inline dos paths informados
7
+ # (heuristica chars/4 = tokens). Le .jdi/config.json pra resolver
8
+ # context_window + thresholds. Imprime status pra stderr e sai 0.
9
+ #
10
+ # Status:
11
+ # PEAK 0-30% ok, full operations
12
+ # GOOD 30-60% ok, prefere frontmatter
13
+ # WARN 60-70% context aquecendo, considere checkpoint
14
+ # CRITICAL 70%+ fracture zone — sugere /jdi-thread
15
+
16
+ param(
17
+ [string[]]$Paths = @()
18
+ )
19
+
20
+ $ErrorActionPreference = "Stop"
21
+
22
+ # Defaults
23
+ $ContextWindow = 200000
24
+ $WarnPct = 60
25
+ $CriticalPct = 70
26
+
27
+ if (Test-Path -LiteralPath ".jdi/config.json") {
28
+ try {
29
+ $cfg = Get-Content -LiteralPath ".jdi/config.json" -Raw -Encoding UTF8 | ConvertFrom-Json
30
+ if ($cfg.context_window) { $ContextWindow = [int]$cfg.context_window }
31
+ if ($cfg.thresholds) {
32
+ if ($cfg.thresholds.warn_pct) { $WarnPct = [int]$cfg.thresholds.warn_pct }
33
+ if ($cfg.thresholds.critical_pct) { $CriticalPct = [int]$cfg.thresholds.critical_pct }
34
+ }
35
+ } catch {
36
+ # config invalido — usa defaults
37
+ }
38
+ }
39
+
40
+ $totalChars = 0
41
+ foreach ($p in $Paths) {
42
+ if (Test-Path -LiteralPath $p -PathType Leaf) {
43
+ $totalChars += (Get-Item -LiteralPath $p).Length
44
+ }
45
+ }
46
+
47
+ $tokens = [int]([math]::Floor($totalChars / 4))
48
+ $pct = if ($ContextWindow -gt 0) { [int]([math]::Floor($tokens * 100 / $ContextWindow)) } else { 0 }
49
+
50
+ $state = "PEAK"
51
+ $hint = ""
52
+ if ($pct -ge $CriticalPct) {
53
+ $state = "CRITICAL"
54
+ $hint = "fracture zone — considere /jdi-thread (proxima phase em sessao nova)"
55
+ } elseif ($pct -ge $WarnPct) {
56
+ $state = "WARN"
57
+ $hint = "context aquecendo — checkpoint recomendado"
58
+ } elseif ($pct -ge 30) {
59
+ $state = "GOOD"
60
+ }
61
+
62
+ $msg = "[jdi-monitor] $state ${pct}% (~${tokens} tokens / ${ContextWindow})"
63
+ if ($hint) { $msg = "$msg. $hint" }
64
+
65
+ [Console]::Error.WriteLine($msg)
66
+ exit 0
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env bash
2
+ # jdi-monitor.sh — context budget monitor (heuristica)
3
+ #
4
+ # Uso:
5
+ # jdi-monitor.sh [path1 path2 ...]
6
+ #
7
+ # Estima tokens consumidos por leitura inline dos paths informados
8
+ # (heuristica chars/4 = tokens). Le .jdi/config.json pra resolver
9
+ # context_window + thresholds. Imprime status pra stderr e sai 0.
10
+ #
11
+ # Status:
12
+ # PEAK 0-30% ok, full operations
13
+ # GOOD 30-60% ok, prefere frontmatter
14
+ # WARN 60-70% context aquecendo, considere checkpoint
15
+ # CRITICAL 70%+ fracture zone — sugere /jdi-thread
16
+ #
17
+ # Sai 0 sempre (nao bloqueia). Saida via stderr nao polui pipe.
18
+
19
+ set -euo pipefail
20
+
21
+ CONFIG=".jdi/config.json"
22
+
23
+ # Defaults se config ausente
24
+ CONTEXT_WINDOW=200000
25
+ WARN_PCT=60
26
+ CRITICAL_PCT=70
27
+
28
+ if [ -f "$CONFIG" ]; then
29
+ if command -v jq >/dev/null 2>&1; then
30
+ CONTEXT_WINDOW=$(jq -r '.context_window // 200000' "$CONFIG")
31
+ WARN_PCT=$(jq -r '.thresholds.warn_pct // 60' "$CONFIG")
32
+ CRITICAL_PCT=$(jq -r '.thresholds.critical_pct // 70' "$CONFIG")
33
+ else
34
+ # Fallback grep — funciona pro JSON simples do JDI
35
+ CONTEXT_WINDOW=$(grep -oE '"context_window":[[:space:]]*[0-9]+' "$CONFIG" | head -1 | grep -oE '[0-9]+' || echo 200000)
36
+ WARN_PCT=$(grep -oE '"warn_pct":[[:space:]]*[0-9]+' "$CONFIG" | head -1 | grep -oE '[0-9]+' || echo 60)
37
+ CRITICAL_PCT=$(grep -oE '"critical_pct":[[:space:]]*[0-9]+' "$CONFIG" | head -1 | grep -oE '[0-9]+' || echo 70)
38
+ fi
39
+ fi
40
+
41
+ # Soma chars dos paths informados
42
+ TOTAL_CHARS=0
43
+ for p in "$@"; do
44
+ if [ -f "$p" ]; then
45
+ SZ=$(wc -c < "$p" | tr -d ' ')
46
+ TOTAL_CHARS=$((TOTAL_CHARS + SZ))
47
+ fi
48
+ done
49
+
50
+ # Heuristica: 4 chars ~ 1 token
51
+ TOKENS=$((TOTAL_CHARS / 4))
52
+ PCT=$((TOKENS * 100 / CONTEXT_WINDOW))
53
+
54
+ if [ "$PCT" -ge "$CRITICAL_PCT" ]; then
55
+ STATE="CRITICAL"
56
+ HINT="fracture zone — considere /jdi-thread (proxima phase em sessao nova)"
57
+ elif [ "$PCT" -ge "$WARN_PCT" ]; then
58
+ STATE="WARN"
59
+ HINT="context aquecendo — checkpoint recomendado"
60
+ elif [ "$PCT" -ge 30 ]; then
61
+ STATE="GOOD"
62
+ HINT=""
63
+ else
64
+ STATE="PEAK"
65
+ HINT=""
66
+ fi
67
+
68
+ if [ -n "$HINT" ]; then
69
+ echo "[jdi-monitor] $STATE ${PCT}% (~${TOKENS} tokens / ${CONTEXT_WINDOW}). $HINT" >&2
70
+ else
71
+ echo "[jdi-monitor] $STATE ${PCT}% (~${TOKENS} tokens / ${CONTEXT_WINDOW})" >&2
72
+ fi
73
+
74
+ exit 0
@@ -0,0 +1,96 @@
1
+ # jdi-truncate.ps1 — markdown-aware truncation pra context budget
2
+ #
3
+ # Uso:
4
+ # pwsh -File jdi-truncate.ps1 -Path <path> [-Budget 8192]
5
+ #
6
+ # Estrategia:
7
+ # - Preserva YAML frontmatter inteiro
8
+ # - Preserva TODAS as linhas de heading (#, ##, ...)
9
+ # - Preserva 1a linha nao-vazia de cada secao
10
+ # - Resto vira "[... N lines omitted]"
11
+ # - Footer aponta pro arquivo original
12
+ #
13
+ # Se file <= budget, ecoa inteiro. Output sempre pra stdout.
14
+
15
+ param(
16
+ [Parameter(Mandatory = $true)]
17
+ [string]$Path,
18
+
19
+ [int]$Budget = 8192
20
+ )
21
+
22
+ $ErrorActionPreference = "Stop"
23
+
24
+ if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
25
+ Write-Error "arquivo nao encontrado: $Path"
26
+ exit 1
27
+ }
28
+
29
+ $content = Get-Content -LiteralPath $Path -Raw -Encoding UTF8
30
+ if ($null -eq $content) { $content = "" }
31
+
32
+ if ($content.Length -le $Budget) {
33
+ Write-Output $content
34
+ exit 0
35
+ }
36
+
37
+ $lines = $content -split "`r?`n"
38
+ $inFrontmatter = $false
39
+ $paragraphKept = $false
40
+ $omitted = 0
41
+ $out = New-Object System.Collections.Generic.List[string]
42
+
43
+ for ($i = 0; $i -lt $lines.Length; $i++) {
44
+ $line = $lines[$i]
45
+
46
+ # Frontmatter (so se comecar na linha 1 = index 0)
47
+ if ($i -eq 0 -and $line -eq "---") {
48
+ $inFrontmatter = $true
49
+ $out.Add($line)
50
+ continue
51
+ }
52
+ if ($inFrontmatter) {
53
+ $out.Add($line)
54
+ if ($line -eq "---") {
55
+ $inFrontmatter = $false
56
+ }
57
+ continue
58
+ }
59
+
60
+ # Heading — sempre preserva
61
+ if ($line -match '^#{1,6}\s') {
62
+ if ($omitted -gt 0) {
63
+ $out.Add("[... $omitted lines omitted]")
64
+ $omitted = 0
65
+ }
66
+ $out.Add($line)
67
+ $paragraphKept = $false
68
+ continue
69
+ }
70
+
71
+ # Linha vazia
72
+ if ($line -match '^\s*$') {
73
+ if (-not $paragraphKept) {
74
+ $out.Add($line)
75
+ } else {
76
+ $omitted++
77
+ }
78
+ continue
79
+ }
80
+
81
+ # Conteudo
82
+ if (-not $paragraphKept) {
83
+ $out.Add($line)
84
+ $paragraphKept = $true
85
+ } else {
86
+ $omitted++
87
+ }
88
+ }
89
+
90
+ if ($omitted -gt 0) {
91
+ $out.Add("[... $omitted lines omitted]")
92
+ }
93
+ $out.Add("")
94
+ $out.Add("[Truncated by jdi-truncate. Read $Path for full content]")
95
+
96
+ Write-Output ($out -join "`n")