javi-forge 0.1.0 → 1.0.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.
- package/.releaserc +2 -1
- package/README.md +143 -31
- package/ai-config/commands/workflows/diagnose.md +70 -0
- package/ai-config/commands/workflows/discover.md +86 -0
- package/dist/commands/doctor.js +24 -1
- package/dist/commands/init.js +48 -1
- package/dist/commands/llmstxt.d.ts +9 -0
- package/dist/commands/llmstxt.js +93 -0
- package/dist/commands/llmstxt.test.d.ts +2 -0
- package/dist/commands/plugin.d.ts +24 -0
- package/dist/commands/plugin.js +78 -0
- package/dist/commands/plugin.test.d.ts +2 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.js +8 -0
- package/dist/index.js +33 -4
- package/dist/lib/plugin.d.ts +39 -0
- package/dist/lib/plugin.js +228 -0
- package/dist/lib/plugin.test.d.ts +2 -0
- package/dist/types/index.d.ts +42 -0
- package/dist/ui/App.d.ts +2 -1
- package/dist/ui/App.js +2 -1
- package/dist/ui/LlmsTxt.d.ts +8 -0
- package/dist/ui/LlmsTxt.js +48 -0
- package/dist/ui/Plugin.d.ts +9 -0
- package/dist/ui/Plugin.js +96 -0
- package/modules/obsidian-brain/README.md +32 -0
- package/modules/obsidian-brain/core/templates/braindump.md +15 -0
- package/modules/obsidian-brain/core/templates/consolidation.md +42 -0
- package/modules/obsidian-brain/core/templates/daily-note.md +18 -0
- package/modules/obsidian-brain/core/templates/resource-capture.md +14 -0
- package/modules/obsidian-brain/developer/templates/adr.md +40 -0
- package/modules/obsidian-brain/developer/templates/coding-session.md +24 -0
- package/modules/obsidian-brain/developer/templates/debug-journal.md +22 -0
- package/modules/obsidian-brain/developer/templates/sdd-feedback.md +27 -0
- package/modules/obsidian-brain/developer/templates/tech-debt.md +20 -0
- package/modules/obsidian-brain/pm-lead/templates/daily-brief.md +25 -0
- package/modules/obsidian-brain/pm-lead/templates/meeting-notes.md +24 -0
- package/modules/obsidian-brain/pm-lead/templates/risk-registry.md +12 -0
- package/modules/obsidian-brain/pm-lead/templates/sprint-review.md +27 -0
- package/modules/obsidian-brain/pm-lead/templates/stakeholder-update.md +24 -0
- package/modules/obsidian-brain/pm-lead/templates/team-intelligence.md +19 -0
- package/modules/obsidian-brain/pm-lead/templates/weekly-brief.md +29 -0
- package/package.json +1 -1
- package/schemas/plugin.schema.json +62 -0
- package/ai-config/skills/docs/api-documentation/SKILL.md +0 -293
- package/ai-config/skills/docs/docs-spring/SKILL.md +0 -377
- package/ai-config/skills/docs/mustache-templates/SKILL.md +0 -190
- package/ai-config/skills/docs/technical-docs/SKILL.md +0 -447
- package/dist/commands/analyze.d.ts.map +0 -1
- package/dist/commands/analyze.js.map +0 -1
- package/dist/commands/analyze.test.d.ts.map +0 -1
- package/dist/commands/analyze.test.js +0 -145
- package/dist/commands/analyze.test.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/doctor.test.d.ts.map +0 -1
- package/dist/commands/doctor.test.js +0 -200
- package/dist/commands/doctor.test.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/init.test.d.ts.map +0 -1
- package/dist/commands/init.test.js +0 -271
- package/dist/commands/init.test.js.map +0 -1
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/e2e/aggressive.e2e.test.d.ts.map +0 -1
- package/dist/e2e/aggressive.e2e.test.js +0 -350
- package/dist/e2e/aggressive.e2e.test.js.map +0 -1
- package/dist/e2e/commands.e2e.test.d.ts.map +0 -1
- package/dist/e2e/commands.e2e.test.js +0 -213
- package/dist/e2e/commands.e2e.test.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/common.d.ts.map +0 -1
- package/dist/lib/common.js.map +0 -1
- package/dist/lib/common.test.d.ts.map +0 -1
- package/dist/lib/common.test.js +0 -316
- package/dist/lib/common.test.js.map +0 -1
- package/dist/lib/frontmatter.d.ts.map +0 -1
- package/dist/lib/frontmatter.js.map +0 -1
- package/dist/lib/frontmatter.test.d.ts.map +0 -1
- package/dist/lib/frontmatter.test.js +0 -257
- package/dist/lib/frontmatter.test.js.map +0 -1
- package/dist/lib/template.d.ts.map +0 -1
- package/dist/lib/template.js.map +0 -1
- package/dist/lib/template.test.d.ts.map +0 -1
- package/dist/lib/template.test.js +0 -201
- package/dist/lib/template.test.js.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js.map +0 -1
- package/dist/ui/AnalyzeUI.d.ts.map +0 -1
- package/dist/ui/AnalyzeUI.js.map +0 -1
- package/dist/ui/App.d.ts.map +0 -1
- package/dist/ui/App.js.map +0 -1
- package/dist/ui/CIContext.d.ts.map +0 -1
- package/dist/ui/CIContext.js.map +0 -1
- package/dist/ui/CISelector.d.ts.map +0 -1
- package/dist/ui/CISelector.js.map +0 -1
- package/dist/ui/Doctor.d.ts.map +0 -1
- package/dist/ui/Doctor.js.map +0 -1
- package/dist/ui/Header.d.ts.map +0 -1
- package/dist/ui/Header.js.map +0 -1
- package/dist/ui/MemorySelector.d.ts.map +0 -1
- package/dist/ui/MemorySelector.js.map +0 -1
- package/dist/ui/NameInput.d.ts.map +0 -1
- package/dist/ui/NameInput.js.map +0 -1
- package/dist/ui/OptionSelector.d.ts.map +0 -1
- package/dist/ui/OptionSelector.js.map +0 -1
- package/dist/ui/Progress.d.ts.map +0 -1
- package/dist/ui/Progress.js.map +0 -1
- package/dist/ui/StackSelector.d.ts.map +0 -1
- package/dist/ui/StackSelector.js.map +0 -1
- package/dist/ui/Summary.d.ts.map +0 -1
- package/dist/ui/Summary.js.map +0 -1
- package/dist/ui/SyncUI.d.ts.map +0 -1
- package/dist/ui/SyncUI.js.map +0 -1
- package/dist/ui/Welcome.d.ts.map +0 -1
- package/dist/ui/Welcome.js.map +0 -1
- package/dist/ui/theme.d.ts.map +0 -1
- package/dist/ui/theme.js.map +0 -1
- package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +0 -25
- package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +0 -29
- package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +0 -18
- package/src/commands/analyze.test.ts +0 -145
- package/src/commands/analyze.ts +0 -69
- package/src/commands/doctor.test.ts +0 -208
- package/src/commands/doctor.ts +0 -163
- package/src/commands/init.test.ts +0 -298
- package/src/commands/init.ts +0 -285
- package/src/constants.ts +0 -69
- package/src/e2e/aggressive.e2e.test.ts +0 -557
- package/src/e2e/commands.e2e.test.ts +0 -298
- package/src/index.tsx +0 -106
- package/src/lib/common.test.ts +0 -318
- package/src/lib/common.ts +0 -127
- package/src/lib/frontmatter.test.ts +0 -291
- package/src/lib/frontmatter.ts +0 -77
- package/src/lib/template.test.ts +0 -226
- package/src/lib/template.ts +0 -99
- package/src/types/index.ts +0 -53
- package/src/ui/AnalyzeUI.tsx +0 -133
- package/src/ui/App.tsx +0 -175
- package/src/ui/CIContext.tsx +0 -25
- package/src/ui/CISelector.tsx +0 -72
- package/src/ui/Doctor.tsx +0 -122
- package/src/ui/Header.tsx +0 -48
- package/src/ui/MemorySelector.tsx +0 -73
- package/src/ui/NameInput.tsx +0 -82
- package/src/ui/OptionSelector.tsx +0 -100
- package/src/ui/Progress.tsx +0 -88
- package/src/ui/StackSelector.tsx +0 -101
- package/src/ui/Summary.tsx +0 -134
- package/src/ui/Welcome.tsx +0 -54
- package/src/ui/theme.ts +0 -10
- package/stryker.config.json +0 -19
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -16
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E tests for javi-forge CLI commands.
|
|
3
|
-
*
|
|
4
|
-
* These tests execute the REAL compiled CLI as a subprocess but ONLY test
|
|
5
|
-
* dry-run behavior — no real filesystem modifications are made.
|
|
6
|
-
*
|
|
7
|
-
* Prerequisites: `pnpm build` must be run before these tests.
|
|
8
|
-
*/
|
|
9
|
-
import { execFile } from 'child_process'
|
|
10
|
-
import { promisify } from 'util'
|
|
11
|
-
import path from 'path'
|
|
12
|
-
import os from 'os'
|
|
13
|
-
import fs from 'fs-extra'
|
|
14
|
-
import crypto from 'crypto'
|
|
15
|
-
import { describe, it, expect, afterEach } from 'vitest'
|
|
16
|
-
|
|
17
|
-
const execFileAsync = promisify(execFile)
|
|
18
|
-
const CLI_PATH = path.resolve(__dirname, '../../dist/index.js')
|
|
19
|
-
|
|
20
|
-
// ── Helpers ──────────────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
const sandboxes: string[] = []
|
|
23
|
-
|
|
24
|
-
async function createSandbox(): Promise<string> {
|
|
25
|
-
const dir = path.join(os.tmpdir(), `javi-forge-e2e-${crypto.randomUUID()}`)
|
|
26
|
-
await fs.ensureDir(dir)
|
|
27
|
-
sandboxes.push(dir)
|
|
28
|
-
return dir
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
afterEach(async () => {
|
|
32
|
-
for (const dir of sandboxes) {
|
|
33
|
-
await fs.remove(dir).catch(() => {})
|
|
34
|
-
}
|
|
35
|
-
sandboxes.length = 0
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
async function runCLI(
|
|
39
|
-
args: string[],
|
|
40
|
-
cwd?: string,
|
|
41
|
-
timeout = 30_000
|
|
42
|
-
): Promise<{ stdout: string; stderr: string; exitCode: number }> {
|
|
43
|
-
try {
|
|
44
|
-
const { stdout, stderr } = await execFileAsync('node', [CLI_PATH, ...args], {
|
|
45
|
-
timeout,
|
|
46
|
-
cwd: cwd ?? process.cwd(),
|
|
47
|
-
env: { ...process.env, FORCE_COLOR: '0', CI: '1' },
|
|
48
|
-
})
|
|
49
|
-
return { stdout, stderr, exitCode: 0 }
|
|
50
|
-
} catch (e: any) {
|
|
51
|
-
return {
|
|
52
|
-
stdout: e.stdout ?? '',
|
|
53
|
-
stderr: e.stderr ?? '',
|
|
54
|
-
exitCode: e.code ?? 1,
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ── --help ──────────────────────────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
describe('javi-forge --help', () => {
|
|
62
|
-
it('shows usage with all commands listed', async () => {
|
|
63
|
-
const { stdout, exitCode } = await runCLI(['--help'])
|
|
64
|
-
|
|
65
|
-
expect(exitCode).toBe(0)
|
|
66
|
-
expect(stdout).toContain('javi-forge')
|
|
67
|
-
expect(stdout).toContain('init')
|
|
68
|
-
expect(stdout).toContain('analyze')
|
|
69
|
-
expect(stdout).toContain('doctor')
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
it('shows all option flags', async () => {
|
|
73
|
-
const { stdout } = await runCLI(['--help'])
|
|
74
|
-
|
|
75
|
-
expect(stdout).toContain('--dry-run')
|
|
76
|
-
expect(stdout).toContain('--stack')
|
|
77
|
-
expect(stdout).toContain('--ci')
|
|
78
|
-
expect(stdout).toContain('--memory')
|
|
79
|
-
expect(stdout).toContain('--project-name')
|
|
80
|
-
expect(stdout).toContain('--ghagga')
|
|
81
|
-
expect(stdout).toContain('--batch')
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// ── init --dry-run ──────────────────────────────────────────────────────────
|
|
86
|
-
|
|
87
|
-
describe('javi-forge init --dry-run', () => {
|
|
88
|
-
it('shows plan with all required flags (node + github)', async () => {
|
|
89
|
-
const sandbox = await createSandbox()
|
|
90
|
-
const { stdout, exitCode } = await runCLI(
|
|
91
|
-
['init', '--dry-run', '--project-name', 'test-app', '--stack', 'node', '--ci', 'github', '--memory', 'engram'],
|
|
92
|
-
sandbox
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
expect(exitCode).toBe(0)
|
|
96
|
-
expect(stdout).toContain('DRY RUN')
|
|
97
|
-
expect(stdout).toContain('Dry run complete')
|
|
98
|
-
expect(stdout).toContain('test-app')
|
|
99
|
-
expect(stdout).toContain('No changes were made')
|
|
100
|
-
expect(stdout).toContain('steps completed')
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
it('does not create files in cwd during dry-run', async () => {
|
|
104
|
-
const sandbox = await createSandbox()
|
|
105
|
-
await runCLI(
|
|
106
|
-
['init', '--dry-run', '--project-name', 'test-app', '--stack', 'node', '--ci', 'github', '--memory', 'engram'],
|
|
107
|
-
sandbox
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
// Sandbox should still be empty — dry-run writes nothing
|
|
111
|
-
const entries = await fs.readdir(sandbox)
|
|
112
|
-
expect(entries).toHaveLength(0)
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it('shows Python stack in output', async () => {
|
|
116
|
-
const sandbox = await createSandbox()
|
|
117
|
-
const { stdout, exitCode } = await runCLI(
|
|
118
|
-
['init', '--dry-run', '--project-name', 'pyapp', '--stack', 'python', '--ci', 'github', '--memory', 'engram'],
|
|
119
|
-
sandbox
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
expect(exitCode).toBe(0)
|
|
123
|
-
expect(stdout).toContain('python')
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
it('selects GitLab CI templates', async () => {
|
|
127
|
-
const sandbox = await createSandbox()
|
|
128
|
-
const { stdout, exitCode } = await runCLI(
|
|
129
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'gitlab', '--memory', 'engram'],
|
|
130
|
-
sandbox
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
expect(exitCode).toBe(0)
|
|
134
|
-
expect(stdout).toContain('gitlab')
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('selects Woodpecker CI templates', async () => {
|
|
138
|
-
const sandbox = await createSandbox()
|
|
139
|
-
const { stdout, exitCode } = await runCLI(
|
|
140
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'woodpecker', '--memory', 'engram'],
|
|
141
|
-
sandbox
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
expect(exitCode).toBe(0)
|
|
145
|
-
expect(stdout).toContain('woodpecker')
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('references obsidian-brain when selected as memory module', async () => {
|
|
149
|
-
const sandbox = await createSandbox()
|
|
150
|
-
const { stdout, exitCode } = await runCLI(
|
|
151
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'github', '--memory', 'obsidian-brain'],
|
|
152
|
-
sandbox
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
expect(exitCode).toBe(0)
|
|
156
|
-
expect(stdout).toContain('obsidian-brain')
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
it('skips memory step when --memory none is used', async () => {
|
|
160
|
-
const sandbox = await createSandbox()
|
|
161
|
-
const { stdout, exitCode } = await runCLI(
|
|
162
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'github', '--memory', 'none'],
|
|
163
|
-
sandbox
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
expect(exitCode).toBe(0)
|
|
167
|
-
// With memory=none, one more step is skipped (memory module install)
|
|
168
|
-
expect(stdout).toContain('skipped')
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
it('shows ghagga step as done when --ghagga flag is used', async () => {
|
|
172
|
-
const sandbox = await createSandbox()
|
|
173
|
-
const { stdout, exitCode } = await runCLI(
|
|
174
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'github', '--memory', 'engram', '--ghagga'],
|
|
175
|
-
sandbox
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
expect(exitCode).toBe(0)
|
|
179
|
-
// GHAGGA step should be completed (not skipped)
|
|
180
|
-
expect(stdout).toContain('Install GHAGGA review system')
|
|
181
|
-
expect(stdout).not.toContain('GHAGGA review system not selected')
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
it('shows ghagga step as skipped without --ghagga flag', async () => {
|
|
185
|
-
const sandbox = await createSandbox()
|
|
186
|
-
const { stdout, exitCode } = await runCLI(
|
|
187
|
-
['init', '--dry-run', '--project-name', 'app', '--stack', 'node', '--ci', 'github', '--memory', 'engram'],
|
|
188
|
-
sandbox
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
expect(exitCode).toBe(0)
|
|
192
|
-
// GHAGGA step should be skipped
|
|
193
|
-
expect(stdout).toContain('GHAGGA review system')
|
|
194
|
-
expect(stdout).toContain('not selected')
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('exits with code 0 even with all options', async () => {
|
|
198
|
-
const sandbox = await createSandbox()
|
|
199
|
-
const { exitCode } = await runCLI(
|
|
200
|
-
['init', '--dry-run', '--project-name', 'full-app', '--stack', 'go', '--ci', 'github', '--memory', 'engram', '--ghagga'],
|
|
201
|
-
sandbox
|
|
202
|
-
)
|
|
203
|
-
|
|
204
|
-
expect(exitCode).toBe(0)
|
|
205
|
-
})
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
// ── analyze ─────────────────────────────────────────────────────────────────
|
|
209
|
-
|
|
210
|
-
describe('javi-forge analyze', () => {
|
|
211
|
-
it('analyze --dry-run completes', async () => {
|
|
212
|
-
const { stdout, exitCode } = await runCLI(['analyze', '--dry-run'])
|
|
213
|
-
|
|
214
|
-
expect(exitCode).toBe(0)
|
|
215
|
-
// Should mention either analysis results or that repoforge is not found
|
|
216
|
-
expect(stdout.length).toBeGreaterThan(0)
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it('analyze --dry-run in empty dir shows appropriate message', async () => {
|
|
220
|
-
const sandbox = await createSandbox()
|
|
221
|
-
const { stdout, exitCode } = await runCLI(['analyze', '--dry-run'], sandbox)
|
|
222
|
-
|
|
223
|
-
expect(exitCode).toBe(0)
|
|
224
|
-
// Output should contain something about analysis — either results or repoforge status
|
|
225
|
-
const combined = stdout.toLowerCase()
|
|
226
|
-
expect(
|
|
227
|
-
combined.includes('analysis') ||
|
|
228
|
-
combined.includes('analyze') ||
|
|
229
|
-
combined.includes('repoforge') ||
|
|
230
|
-
combined.includes('complete') ||
|
|
231
|
-
combined.includes('dry run')
|
|
232
|
-
).toBe(true)
|
|
233
|
-
})
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
// ── doctor ──────────────────────────────────────────────────────────────────
|
|
237
|
-
|
|
238
|
-
describe('javi-forge doctor', () => {
|
|
239
|
-
it('runs without crashing and shows check results', async () => {
|
|
240
|
-
const { stdout, exitCode } = await runCLI(['doctor'])
|
|
241
|
-
|
|
242
|
-
expect(exitCode).toBe(0)
|
|
243
|
-
// Doctor output contains status icons (✓ ok, ✗ fail, – skip)
|
|
244
|
-
const hasStatusIndicators =
|
|
245
|
-
stdout.includes('\u2713') || // ✓
|
|
246
|
-
stdout.includes('\u2717') || // ✗
|
|
247
|
-
stdout.includes('\u2013') || // –
|
|
248
|
-
stdout.includes('ok') ||
|
|
249
|
-
stdout.includes('fail') ||
|
|
250
|
-
stdout.includes('skip')
|
|
251
|
-
expect(hasStatusIndicators).toBe(true)
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
it('shows health score', async () => {
|
|
255
|
-
const { stdout, exitCode } = await runCLI(['doctor'])
|
|
256
|
-
|
|
257
|
-
expect(exitCode).toBe(0)
|
|
258
|
-
expect(stdout).toContain('Health:')
|
|
259
|
-
expect(stdout).toMatch(/\d+\/\d+ checks passed/)
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
it('checks system tools (git, node)', async () => {
|
|
263
|
-
const { stdout, exitCode } = await runCLI(['doctor'])
|
|
264
|
-
|
|
265
|
-
expect(exitCode).toBe(0)
|
|
266
|
-
expect(stdout).toContain('System Tools')
|
|
267
|
-
expect(stdout).toContain('Git')
|
|
268
|
-
expect(stdout).toContain('Node.js')
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
it('shows framework structure section', async () => {
|
|
272
|
-
const { stdout, exitCode } = await runCLI(['doctor'])
|
|
273
|
-
|
|
274
|
-
expect(exitCode).toBe(0)
|
|
275
|
-
expect(stdout).toContain('Framework Structure')
|
|
276
|
-
expect(stdout).toContain('templates/')
|
|
277
|
-
expect(stdout).toContain('modules/')
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
it('in empty dir shows no stack detected', async () => {
|
|
281
|
-
const sandbox = await createSandbox()
|
|
282
|
-
const { stdout, exitCode } = await runCLI(['doctor'], sandbox)
|
|
283
|
-
|
|
284
|
-
expect(exitCode).toBe(0)
|
|
285
|
-
expect(stdout).toContain('Stack Detection')
|
|
286
|
-
// In empty dir, no stack is recognizable
|
|
287
|
-
expect(stdout).toContain('no recognizable project files')
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('shows installed modules section', async () => {
|
|
291
|
-
const { stdout, exitCode } = await runCLI(['doctor'])
|
|
292
|
-
|
|
293
|
-
expect(exitCode).toBe(0)
|
|
294
|
-
expect(stdout).toContain('Installed Modules')
|
|
295
|
-
expect(stdout).toContain('engram')
|
|
296
|
-
expect(stdout).toContain('ghagga')
|
|
297
|
-
})
|
|
298
|
-
})
|
package/src/index.tsx
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import React from 'react'
|
|
3
|
-
import { render } from 'ink'
|
|
4
|
-
import meow from 'meow'
|
|
5
|
-
import App from './ui/App.js'
|
|
6
|
-
import Doctor from './ui/Doctor.js'
|
|
7
|
-
import AnalyzeUI from './ui/AnalyzeUI.js'
|
|
8
|
-
import { CIProvider as CIContextProvider } from './ui/CIContext.js'
|
|
9
|
-
import type { Stack, CIProvider, MemoryOption } from './types/index.js'
|
|
10
|
-
|
|
11
|
-
const cli = meow(`
|
|
12
|
-
Usage
|
|
13
|
-
$ javi-forge [command] [options]
|
|
14
|
-
|
|
15
|
-
Commands
|
|
16
|
-
init Bootstrap a new project (default)
|
|
17
|
-
analyze Run repoforge skills analysis
|
|
18
|
-
doctor Show health report
|
|
19
|
-
|
|
20
|
-
Options
|
|
21
|
-
--dry-run Preview changes without writing files
|
|
22
|
-
--stack Project stack (node, python, go, rust, java-gradle, java-maven, elixir)
|
|
23
|
-
--ci CI provider (github, gitlab, woodpecker)
|
|
24
|
-
--memory Memory module (engram, obsidian-brain, memory-simple, none)
|
|
25
|
-
--project-name Project name (skips name prompt)
|
|
26
|
-
--ghagga Enable GHAGGA review system
|
|
27
|
-
--batch Non-interactive mode (auto-proceed, no keyboard input)
|
|
28
|
-
--version Show version
|
|
29
|
-
--help Show this help
|
|
30
|
-
|
|
31
|
-
Examples
|
|
32
|
-
$ javi-forge
|
|
33
|
-
$ javi-forge init --dry-run
|
|
34
|
-
$ javi-forge init --stack node --ci github
|
|
35
|
-
$ javi-forge init --dry-run --project-name app --stack node --ci github --batch
|
|
36
|
-
$ javi-forge analyze
|
|
37
|
-
$ javi-forge analyze --dry-run
|
|
38
|
-
$ javi-forge doctor
|
|
39
|
-
`, {
|
|
40
|
-
importMeta: import.meta,
|
|
41
|
-
flags: {
|
|
42
|
-
dryRun: { type: 'boolean', default: false },
|
|
43
|
-
stack: { type: 'string', default: '' },
|
|
44
|
-
ci: { type: 'string', default: '' },
|
|
45
|
-
memory: { type: 'string', default: '' },
|
|
46
|
-
projectName: { type: 'string', default: '' },
|
|
47
|
-
ghagga: { type: 'boolean', default: false },
|
|
48
|
-
batch: { type: 'boolean', default: false },
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
const subcommand = cli.input[0] ?? 'init'
|
|
53
|
-
|
|
54
|
-
const VALID_STACKS = ['node', 'python', 'go', 'rust', 'java-gradle', 'java-maven', 'elixir']
|
|
55
|
-
const VALID_CI = ['github', 'gitlab', 'woodpecker']
|
|
56
|
-
const VALID_MEMORY = ['engram', 'obsidian-brain', 'memory-simple', 'none']
|
|
57
|
-
|
|
58
|
-
const isCI = cli.flags.batch || process.env['CI'] === '1' || process.env['CI'] === 'true'
|
|
59
|
-
|
|
60
|
-
switch (subcommand) {
|
|
61
|
-
case 'doctor': {
|
|
62
|
-
render(
|
|
63
|
-
<CIContextProvider isCI={isCI}>
|
|
64
|
-
<Doctor />
|
|
65
|
-
</CIContextProvider>
|
|
66
|
-
)
|
|
67
|
-
break
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
case 'analyze': {
|
|
71
|
-
render(
|
|
72
|
-
<CIContextProvider isCI={isCI}>
|
|
73
|
-
<AnalyzeUI dryRun={cli.flags.dryRun} />
|
|
74
|
-
</CIContextProvider>
|
|
75
|
-
)
|
|
76
|
-
break
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
case 'init':
|
|
80
|
-
default: {
|
|
81
|
-
const presetStack = VALID_STACKS.includes(cli.flags.stack)
|
|
82
|
-
? cli.flags.stack as Stack
|
|
83
|
-
: undefined
|
|
84
|
-
const presetCI = VALID_CI.includes(cli.flags.ci)
|
|
85
|
-
? cli.flags.ci as CIProvider
|
|
86
|
-
: undefined
|
|
87
|
-
const presetMemory = VALID_MEMORY.includes(cli.flags.memory)
|
|
88
|
-
? cli.flags.memory as MemoryOption
|
|
89
|
-
: undefined
|
|
90
|
-
const presetName = cli.flags.projectName || undefined
|
|
91
|
-
|
|
92
|
-
render(
|
|
93
|
-
<CIContextProvider isCI={isCI}>
|
|
94
|
-
<App
|
|
95
|
-
dryRun={cli.flags.dryRun}
|
|
96
|
-
presetStack={presetStack}
|
|
97
|
-
presetCI={presetCI}
|
|
98
|
-
presetMemory={presetMemory}
|
|
99
|
-
presetName={presetName}
|
|
100
|
-
presetGhagga={cli.flags.ghagga}
|
|
101
|
-
/>
|
|
102
|
-
</CIContextProvider>
|
|
103
|
-
)
|
|
104
|
-
break
|
|
105
|
-
}
|
|
106
|
-
}
|