prjct-cli 0.31.0 → 0.34.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/CHANGELOG.md +183 -0
- package/CLAUDE.md +41 -0
- package/core/__tests__/agentic/memory-system.test.ts +2 -2
- package/core/__tests__/types/fs.test.ts +125 -0
- package/core/agentic/agent-router.ts +16 -4
- package/core/agentic/chain-of-thought.ts +4 -12
- package/core/agentic/command-executor.ts +10 -11
- package/core/agentic/context-builder.ts +24 -10
- package/core/agentic/ground-truth.ts +139 -55
- package/core/agentic/prompt-builder.ts +20 -7
- package/core/agentic/smart-context.ts +1 -1
- package/core/agentic/template-loader.ts +1 -1
- package/core/agentic/tool-registry.ts +4 -2
- package/core/bus/bus.ts +1 -1
- package/core/commands/cleanup.ts +24 -8
- package/core/commands/planning.ts +4 -2
- package/core/commands/setup.ts +4 -4
- package/core/commands/shipping.ts +34 -8
- package/core/commands/snapshots.ts +27 -13
- package/core/context/generator.ts +9 -5
- package/core/domain/agent-generator.ts +1 -1
- package/core/domain/agent-loader.ts +1 -1
- package/core/domain/analyzer.ts +76 -31
- package/core/domain/context-estimator.ts +1 -1
- package/core/domain/snapshot-manager.ts +55 -21
- package/core/domain/task-stack.ts +16 -7
- package/core/infrastructure/author-detector.ts +1 -1
- package/core/infrastructure/claude-agent.ts +12 -8
- package/core/infrastructure/command-installer.ts +42 -21
- package/core/infrastructure/editors-config.ts +1 -1
- package/core/infrastructure/path-manager.ts +27 -2
- package/core/infrastructure/permission-manager.ts +1 -1
- package/core/infrastructure/setup.ts +31 -13
- package/core/infrastructure/update-checker.ts +5 -5
- package/core/integrations/jira/client.ts +91 -30
- package/core/integrations/jira/index.ts +29 -5
- package/core/integrations/jira/mcp-adapter.ts +451 -0
- package/core/integrations/linear/client.ts +23 -3
- package/core/plugin/loader.ts +16 -6
- package/core/plugin/registry.ts +16 -6
- package/core/server/routes-extended.ts +13 -6
- package/core/server/routes.ts +15 -5
- package/core/server/sse.ts +4 -3
- package/core/services/agent-service.ts +4 -2
- package/core/services/memory-service.ts +16 -5
- package/core/services/project-service.ts +11 -2
- package/core/services/skill-service.ts +4 -3
- package/core/session/compaction.ts +4 -5
- package/core/session/metrics.ts +11 -4
- package/core/session/task-session-manager.ts +27 -9
- package/core/storage/storage-manager.ts +12 -5
- package/core/storage/storage.ts +26 -10
- package/core/sync/auth-config.ts +2 -2
- package/core/sync/oauth-handler.ts +1 -1
- package/core/sync/sync-client.ts +4 -2
- package/core/sync/sync-manager.ts +1 -1
- package/core/types/agentic.ts +8 -18
- package/core/types/config.ts +1 -1
- package/core/types/index.ts +3 -2
- package/core/types/integrations.ts +4 -48
- package/core/types/storage.ts +0 -8
- package/core/types/task.ts +0 -4
- package/core/utils/file-helper.ts +10 -4
- package/core/utils/jsonl-helper.ts +4 -4
- package/core/utils/keychain.ts +130 -0
- package/core/utils/logger.ts +27 -25
- package/core/utils/runtime.ts +1 -1
- package/core/utils/session-helper.ts +4 -4
- package/core/utils/version.ts +1 -1
- package/package.json +1 -1
- package/packages/shared/src/utils.ts +1 -1
- package/scripts/postinstall.js +26 -2
- package/templates/agentic/orchestrator.md +303 -0
- package/templates/commands/bug.md +2 -0
- package/templates/commands/enrich.md +601 -195
- package/templates/commands/github.md +287 -0
- package/templates/commands/init.md +45 -26
- package/templates/commands/jira.md +198 -258
- package/templates/commands/linear.md +186 -172
- package/templates/commands/monday.md +232 -0
- package/templates/commands/p.md +57 -10
- package/templates/commands/setup.md +4 -1
- package/templates/commands/sync.md +133 -97
- package/templates/commands/task.md +12 -0
- package/templates/config/skill-mappings.json +95 -63
- package/templates/mcp-config.json +42 -39
- package/core/integrations/notion/client.ts +0 -413
- package/core/integrations/notion/index.ts +0 -46
- package/core/integrations/notion/setup.ts +0 -235
- package/core/integrations/notion/sync.ts +0 -818
- package/core/integrations/notion/templates.ts +0 -246
- package/core/plugin/builtin/notion.ts +0 -178
- package/dist/bin/prjct.mjs +0 -13581
- package/dist/core/infrastructure/command-installer.js +0 -473
- package/dist/core/infrastructure/editors-config.js +0 -157
- package/dist/core/infrastructure/setup.js +0 -893
- package/dist/core/utils/version.js +0 -142
- package/packages/shared/.turbo/turbo-build.log +0 -14
- package/packages/shared/dist/index.d.ts +0 -10
- package/packages/shared/dist/index.d.ts.map +0 -1
- package/packages/shared/dist/index.js +0 -4196
- package/packages/shared/dist/schemas.d.ts +0 -408
- package/packages/shared/dist/schemas.d.ts.map +0 -1
- package/packages/shared/dist/types.d.ts +0 -144
- package/packages/shared/dist/types.d.ts.map +0 -1
- package/packages/shared/dist/unified.d.ts +0 -139
- package/packages/shared/dist/unified.d.ts.map +0 -1
- package/packages/shared/dist/utils.d.ts +0 -60
- package/packages/shared/dist/utils.d.ts.map +0 -1
- package/templates/commands/ask.md +0 -128
- package/templates/commands/dashboard.md +0 -686
- package/templates/commands/feature.md +0 -46
- package/templates/commands/now.md +0 -53
- package/templates/commands/suggest.md +0 -116
- package/templates/global/docs/agents.md +0 -88
- package/templates/global/docs/architecture.md +0 -103
- package/templates/global/docs/commands.md +0 -96
- package/templates/global/docs/validation.md +0 -95
- package/templates/skills/notion-push.md +0 -116
- package/templates/skills/notion-setup.md +0 -199
- package/templates/skills/notion-sync.md +0 -290
|
@@ -17,6 +17,7 @@ import os from 'os'
|
|
|
17
17
|
import { execSync } from 'child_process'
|
|
18
18
|
|
|
19
19
|
import type { GroundTruthContext, VerificationResult, Verifier } from '../types'
|
|
20
|
+
import { isNotFoundError } from '../types/fs'
|
|
20
21
|
|
|
21
22
|
// =============================================================================
|
|
22
23
|
// Utilities
|
|
@@ -103,10 +104,14 @@ export async function verifyDone(context: GroundTruthContext): Promise<Verificat
|
|
|
103
104
|
actual.durationFormatted = formatDuration(actual.durationMs as number)
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
|
-
} catch {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (isNotFoundError(error)) {
|
|
109
|
+
actual.nowExists = false
|
|
110
|
+
warnings.push('now.md does not exist')
|
|
111
|
+
recommendations.push('Create a task with /p:now "task"')
|
|
112
|
+
} else {
|
|
113
|
+
throw error
|
|
114
|
+
}
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
// 2. Verify next.md for auto-start
|
|
@@ -116,9 +121,13 @@ export async function verifyDone(context: GroundTruthContext): Promise<Verificat
|
|
|
116
121
|
actual.nextExists = true
|
|
117
122
|
const tasks = nextContent.match(/- \[ \]/g) || []
|
|
118
123
|
actual.pendingTasks = tasks.length
|
|
119
|
-
} catch {
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (isNotFoundError(error)) {
|
|
126
|
+
actual.nextExists = false
|
|
127
|
+
actual.pendingTasks = 0
|
|
128
|
+
} else {
|
|
129
|
+
throw error
|
|
130
|
+
}
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
// 3. Verify metrics.md is writable
|
|
@@ -126,9 +135,13 @@ export async function verifyDone(context: GroundTruthContext): Promise<Verificat
|
|
|
126
135
|
try {
|
|
127
136
|
await fs.access(path.dirname(metricsPath), fs.constants.W_OK)
|
|
128
137
|
actual.metricsWritable = true
|
|
129
|
-
} catch {
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (isNotFoundError(error)) {
|
|
140
|
+
actual.metricsWritable = false
|
|
141
|
+
warnings.push('Cannot write to metrics directory')
|
|
142
|
+
} else {
|
|
143
|
+
throw error
|
|
144
|
+
}
|
|
132
145
|
}
|
|
133
146
|
|
|
134
147
|
return {
|
|
@@ -161,9 +174,9 @@ export async function verifyShip(context: GroundTruthContext): Promise<Verificat
|
|
|
161
174
|
warnings.push(`${actual.uncommittedFiles} uncommitted file(s)`)
|
|
162
175
|
recommendations.push('Commit changes before shipping')
|
|
163
176
|
}
|
|
164
|
-
} catch {
|
|
177
|
+
} catch (error) {
|
|
178
|
+
// Git errors (not a repo, git not installed) are not blockers
|
|
165
179
|
actual.gitAvailable = false
|
|
166
|
-
// Not a git repo or git not available - not a blocker
|
|
167
180
|
}
|
|
168
181
|
|
|
169
182
|
// 2. Check for package.json version (if exists)
|
|
@@ -173,8 +186,15 @@ export async function verifyShip(context: GroundTruthContext): Promise<Verificat
|
|
|
173
186
|
const pkg = JSON.parse(pkgContent)
|
|
174
187
|
actual.currentVersion = pkg.version
|
|
175
188
|
actual.hasPackageJson = true
|
|
176
|
-
} catch {
|
|
177
|
-
|
|
189
|
+
} catch (error) {
|
|
190
|
+
if (isNotFoundError(error)) {
|
|
191
|
+
actual.hasPackageJson = false
|
|
192
|
+
} else if (error instanceof SyntaxError) {
|
|
193
|
+
actual.hasPackageJson = false
|
|
194
|
+
warnings.push('package.json has invalid JSON')
|
|
195
|
+
} else {
|
|
196
|
+
throw error
|
|
197
|
+
}
|
|
178
198
|
}
|
|
179
199
|
|
|
180
200
|
// 3. Check shipped.md for duplicate feature names
|
|
@@ -193,8 +213,12 @@ export async function verifyShip(context: GroundTruthContext): Promise<Verificat
|
|
|
193
213
|
recommendations.push('Use a different feature name or skip /p:ship')
|
|
194
214
|
}
|
|
195
215
|
}
|
|
196
|
-
} catch {
|
|
197
|
-
|
|
216
|
+
} catch (error) {
|
|
217
|
+
if (isNotFoundError(error)) {
|
|
218
|
+
actual.shippedExists = false
|
|
219
|
+
} else {
|
|
220
|
+
throw error
|
|
221
|
+
}
|
|
198
222
|
}
|
|
199
223
|
|
|
200
224
|
// 4. Check for test failures (if test script exists)
|
|
@@ -205,8 +229,12 @@ export async function verifyShip(context: GroundTruthContext): Promise<Verificat
|
|
|
205
229
|
actual.hasTestScript = !!pkg.scripts?.test
|
|
206
230
|
// Note: We don't run tests here, just check if they exist
|
|
207
231
|
// Running tests is the user's responsibility
|
|
208
|
-
} catch {
|
|
209
|
-
|
|
232
|
+
} catch (error) {
|
|
233
|
+
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
234
|
+
actual.hasTestScript = false
|
|
235
|
+
} else {
|
|
236
|
+
throw error
|
|
237
|
+
}
|
|
210
238
|
}
|
|
211
239
|
}
|
|
212
240
|
|
|
@@ -240,9 +268,13 @@ export async function verifyFeature(context: GroundTruthContext): Promise<Verifi
|
|
|
240
268
|
warnings.push(`Queue nearly full (${actual.taskCount}/100 tasks)`)
|
|
241
269
|
recommendations.push('Complete some tasks before adding more')
|
|
242
270
|
}
|
|
243
|
-
} catch {
|
|
244
|
-
|
|
245
|
-
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (isNotFoundError(error)) {
|
|
273
|
+
actual.nextExists = false
|
|
274
|
+
actual.taskCount = 0
|
|
275
|
+
} else {
|
|
276
|
+
throw error
|
|
277
|
+
}
|
|
246
278
|
}
|
|
247
279
|
|
|
248
280
|
// 2. Check roadmap.md for duplicate features
|
|
@@ -259,8 +291,12 @@ export async function verifyFeature(context: GroundTruthContext): Promise<Verifi
|
|
|
259
291
|
recommendations.push('Check roadmap for duplicates with /p:roadmap')
|
|
260
292
|
}
|
|
261
293
|
}
|
|
262
|
-
} catch {
|
|
263
|
-
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if (isNotFoundError(error)) {
|
|
296
|
+
actual.roadmapExists = false
|
|
297
|
+
} else {
|
|
298
|
+
throw error
|
|
299
|
+
}
|
|
264
300
|
}
|
|
265
301
|
|
|
266
302
|
// 3. Check if there's an active task (should complete first?)
|
|
@@ -272,8 +308,12 @@ export async function verifyFeature(context: GroundTruthContext): Promise<Verifi
|
|
|
272
308
|
if (actual.hasActiveTask) {
|
|
273
309
|
recommendations.push('Consider completing current task first with /p:done')
|
|
274
310
|
}
|
|
275
|
-
} catch {
|
|
276
|
-
|
|
311
|
+
} catch (error) {
|
|
312
|
+
if (isNotFoundError(error)) {
|
|
313
|
+
actual.hasActiveTask = false
|
|
314
|
+
} else {
|
|
315
|
+
throw error
|
|
316
|
+
}
|
|
277
317
|
}
|
|
278
318
|
|
|
279
319
|
return {
|
|
@@ -311,9 +351,13 @@ export async function verifyNow(context: GroundTruthContext): Promise<Verificati
|
|
|
311
351
|
warnings.push(`Replacing existing task: "${taskPreview}..."`)
|
|
312
352
|
recommendations.push('Use /p:done first to track completion')
|
|
313
353
|
}
|
|
314
|
-
} catch {
|
|
315
|
-
|
|
316
|
-
|
|
354
|
+
} catch (error) {
|
|
355
|
+
if (isNotFoundError(error)) {
|
|
356
|
+
actual.nowExists = false
|
|
357
|
+
actual.hasActiveTask = false
|
|
358
|
+
} else {
|
|
359
|
+
throw error
|
|
360
|
+
}
|
|
317
361
|
}
|
|
318
362
|
|
|
319
363
|
// 2. Check next.md for available tasks
|
|
@@ -326,8 +370,12 @@ export async function verifyNow(context: GroundTruthContext): Promise<Verificati
|
|
|
326
370
|
if (!context.params.task && pendingTasks > 0) {
|
|
327
371
|
recommendations.push(`${pendingTasks} tasks available in queue`)
|
|
328
372
|
}
|
|
329
|
-
} catch {
|
|
330
|
-
|
|
373
|
+
} catch (error) {
|
|
374
|
+
if (isNotFoundError(error)) {
|
|
375
|
+
actual.pendingTasks = 0
|
|
376
|
+
} else {
|
|
377
|
+
throw error
|
|
378
|
+
}
|
|
331
379
|
}
|
|
332
380
|
|
|
333
381
|
return {
|
|
@@ -355,8 +403,15 @@ export async function verifyInit(context: GroundTruthContext): Promise<Verificat
|
|
|
355
403
|
actual.existingConfig = JSON.parse(configContent)
|
|
356
404
|
warnings.push('Project already initialized')
|
|
357
405
|
recommendations.push('Use /p:analyze to refresh analysis or delete .prjct/ to reinitialize')
|
|
358
|
-
} catch {
|
|
359
|
-
|
|
406
|
+
} catch (error) {
|
|
407
|
+
if (isNotFoundError(error)) {
|
|
408
|
+
actual.alreadyInitialized = false
|
|
409
|
+
} else if (error instanceof SyntaxError) {
|
|
410
|
+
actual.alreadyInitialized = false
|
|
411
|
+
warnings.push('Existing config has invalid JSON')
|
|
412
|
+
} else {
|
|
413
|
+
throw error
|
|
414
|
+
}
|
|
360
415
|
}
|
|
361
416
|
|
|
362
417
|
// 2. Check if global storage path is writable
|
|
@@ -364,13 +419,19 @@ export async function verifyInit(context: GroundTruthContext): Promise<Verificat
|
|
|
364
419
|
try {
|
|
365
420
|
await fs.access(globalPath, fs.constants.W_OK)
|
|
366
421
|
actual.globalPathWritable = true
|
|
367
|
-
} catch {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
422
|
+
} catch (error) {
|
|
423
|
+
if (isNotFoundError(error)) {
|
|
424
|
+
try {
|
|
425
|
+
// Try to create it
|
|
426
|
+
await fs.mkdir(globalPath, { recursive: true })
|
|
427
|
+
actual.globalPathWritable = true
|
|
428
|
+
actual.globalPathCreated = true
|
|
429
|
+
} catch (mkdirError) {
|
|
430
|
+
actual.globalPathWritable = false
|
|
431
|
+
warnings.push('Cannot write to ~/.prjct-cli')
|
|
432
|
+
recommendations.push('Check directory permissions')
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
374
435
|
actual.globalPathWritable = false
|
|
375
436
|
warnings.push('Cannot write to ~/.prjct-cli')
|
|
376
437
|
recommendations.push('Check directory permissions')
|
|
@@ -400,11 +461,20 @@ export async function verifySync(context: GroundTruthContext): Promise<Verificat
|
|
|
400
461
|
const configContent = await fs.readFile(configPath, 'utf-8')
|
|
401
462
|
actual.hasConfig = true
|
|
402
463
|
actual.config = JSON.parse(configContent)
|
|
403
|
-
} catch {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
464
|
+
} catch (error) {
|
|
465
|
+
if (isNotFoundError(error)) {
|
|
466
|
+
actual.hasConfig = false
|
|
467
|
+
warnings.push('Project not initialized')
|
|
468
|
+
recommendations.push('Run /p:init first')
|
|
469
|
+
return { verified: false, actual, warnings, recommendations }
|
|
470
|
+
} else if (error instanceof SyntaxError) {
|
|
471
|
+
actual.hasConfig = false
|
|
472
|
+
warnings.push('Config file has invalid JSON')
|
|
473
|
+
recommendations.push('Delete .prjct/ and run /p:init')
|
|
474
|
+
return { verified: false, actual, warnings, recommendations }
|
|
475
|
+
} else {
|
|
476
|
+
throw error
|
|
477
|
+
}
|
|
408
478
|
}
|
|
409
479
|
|
|
410
480
|
// 2. Check if global storage exists
|
|
@@ -413,10 +483,14 @@ export async function verifySync(context: GroundTruthContext): Promise<Verificat
|
|
|
413
483
|
try {
|
|
414
484
|
await fs.access(globalProjectPath)
|
|
415
485
|
actual.globalStorageExists = true
|
|
416
|
-
} catch {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
486
|
+
} catch (error) {
|
|
487
|
+
if (isNotFoundError(error)) {
|
|
488
|
+
actual.globalStorageExists = false
|
|
489
|
+
warnings.push('Global storage missing')
|
|
490
|
+
recommendations.push('Run /p:init to recreate')
|
|
491
|
+
} else {
|
|
492
|
+
throw error
|
|
493
|
+
}
|
|
420
494
|
}
|
|
421
495
|
|
|
422
496
|
return {
|
|
@@ -444,8 +518,11 @@ export async function verifyAnalyze(context: GroundTruthContext): Promise<Verifi
|
|
|
444
518
|
try {
|
|
445
519
|
await fs.access(path.join(context.projectPath, file))
|
|
446
520
|
;(actual.detectedFiles as string[]).push(file)
|
|
447
|
-
} catch {
|
|
448
|
-
//
|
|
521
|
+
} catch (error) {
|
|
522
|
+
// ENOENT expected - file doesn't exist
|
|
523
|
+
if (!isNotFoundError(error)) {
|
|
524
|
+
throw error
|
|
525
|
+
}
|
|
449
526
|
}
|
|
450
527
|
}
|
|
451
528
|
|
|
@@ -464,8 +541,11 @@ export async function verifyAnalyze(context: GroundTruthContext): Promise<Verifi
|
|
|
464
541
|
if (stat.isDirectory()) {
|
|
465
542
|
;(actual.detectedSrcDirs as string[]).push(dir)
|
|
466
543
|
}
|
|
467
|
-
} catch {
|
|
468
|
-
//
|
|
544
|
+
} catch (error) {
|
|
545
|
+
// ENOENT expected - directory doesn't exist
|
|
546
|
+
if (!isNotFoundError(error)) {
|
|
547
|
+
throw error
|
|
548
|
+
}
|
|
469
549
|
}
|
|
470
550
|
}
|
|
471
551
|
|
|
@@ -496,9 +576,13 @@ export async function verifySpec(context: GroundTruthContext): Promise<Verificat
|
|
|
496
576
|
const files = await fs.readdir(specsPath)
|
|
497
577
|
actual.existingSpecs = files.filter((f) => f.endsWith('.md'))
|
|
498
578
|
actual.specCount = (actual.existingSpecs as string[]).length
|
|
499
|
-
} catch {
|
|
500
|
-
|
|
501
|
-
|
|
579
|
+
} catch (error) {
|
|
580
|
+
if (isNotFoundError(error)) {
|
|
581
|
+
actual.specsExists = false
|
|
582
|
+
actual.specCount = 0
|
|
583
|
+
} else {
|
|
584
|
+
throw error
|
|
585
|
+
}
|
|
502
586
|
}
|
|
503
587
|
|
|
504
588
|
// 2. Check for duplicate spec name
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import fs from 'fs'
|
|
13
13
|
import path from 'path'
|
|
14
|
+
import { isNotFoundError } from '../types/fs'
|
|
14
15
|
import { stateStorage, queueStorage } from '../storage'
|
|
15
16
|
import { outcomeAnalyzer } from '../outcomes'
|
|
16
17
|
import type {
|
|
@@ -85,8 +86,11 @@ class PromptBuilder {
|
|
|
85
86
|
checklists[name] = content
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
} catch {
|
|
89
|
+
} catch (error) {
|
|
89
90
|
// Silent fail - checklists are optional enhancement
|
|
91
|
+
if (!isNotFoundError(error)) {
|
|
92
|
+
console.error(`Checklist loading warning: ${(error as Error).message}`)
|
|
93
|
+
}
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
this._checklistsCache = checklists
|
|
@@ -118,8 +122,11 @@ class PromptBuilder {
|
|
|
118
122
|
|
|
119
123
|
this._stateCache.set(projectId, { state, timestamp: Date.now() })
|
|
120
124
|
return state
|
|
121
|
-
} catch {
|
|
122
|
-
|
|
125
|
+
} catch (error) {
|
|
126
|
+
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
127
|
+
return null
|
|
128
|
+
}
|
|
129
|
+
throw error
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
|
|
@@ -175,8 +182,11 @@ class PromptBuilder {
|
|
|
175
182
|
}
|
|
176
183
|
parts.push('')
|
|
177
184
|
}
|
|
178
|
-
} catch {
|
|
179
|
-
// Outcomes not available yet
|
|
185
|
+
} catch (error) {
|
|
186
|
+
// Outcomes not available yet - expected for new projects
|
|
187
|
+
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
188
|
+
console.error(`Outcome detection warning: ${(error as Error).message}`)
|
|
189
|
+
}
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
parts.push('---')
|
|
@@ -214,8 +224,11 @@ class PromptBuilder {
|
|
|
214
224
|
if (fs.existsSync(routingPath)) {
|
|
215
225
|
this._checklistRoutingCache = fs.readFileSync(routingPath, 'utf-8')
|
|
216
226
|
}
|
|
217
|
-
} catch {
|
|
218
|
-
// Silent fail
|
|
227
|
+
} catch (error) {
|
|
228
|
+
// Silent fail - checklist routing is optional
|
|
229
|
+
if (!isNotFoundError(error)) {
|
|
230
|
+
console.error(`Checklist routing warning: ${(error as Error).message}`)
|
|
231
|
+
}
|
|
219
232
|
}
|
|
220
233
|
|
|
221
234
|
return this._checklistRoutingCache || null
|
|
@@ -65,7 +65,8 @@ const toolRegistry: ToolRegistryInterface = {
|
|
|
65
65
|
toolRegistry.register('Read', async (filePath: unknown): Promise<string | null> => {
|
|
66
66
|
try {
|
|
67
67
|
return await fs.readFile(filePath as string, 'utf-8')
|
|
68
|
-
} catch {
|
|
68
|
+
} catch (_error) {
|
|
69
|
+
// File not found or read error - return null (expected)
|
|
69
70
|
return null
|
|
70
71
|
}
|
|
71
72
|
})
|
|
@@ -75,7 +76,8 @@ toolRegistry.register('Write', async (filePath: unknown, content: unknown): Prom
|
|
|
75
76
|
try {
|
|
76
77
|
await fs.writeFile(filePath as string, content as string, 'utf-8')
|
|
77
78
|
return true
|
|
78
|
-
} catch {
|
|
79
|
+
} catch (_error) {
|
|
80
|
+
// Write error - return false (expected)
|
|
79
81
|
return false
|
|
80
82
|
}
|
|
81
83
|
})
|
package/core/bus/bus.ts
CHANGED
package/core/commands/cleanup.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import path from 'path'
|
|
8
8
|
|
|
9
|
+
import { isNotFoundError } from '../types/fs'
|
|
9
10
|
import type { CommandResult, CleanupOptions } from '../types'
|
|
10
11
|
import {
|
|
11
12
|
pathManager,
|
|
@@ -44,8 +45,11 @@ export async function cleanupMemory(projectPath: string): Promise<{
|
|
|
44
45
|
results.freedSpace += sizeMB
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
} catch {
|
|
48
|
-
//
|
|
48
|
+
} catch (error) {
|
|
49
|
+
// Skip file if not found, otherwise log unexpected errors
|
|
50
|
+
if (!isNotFoundError(error)) {
|
|
51
|
+
console.error(`Cleanup warning for ${filePath}: ${(error as Error).message}`)
|
|
52
|
+
}
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
|
|
@@ -100,8 +104,12 @@ export async function cleanup(
|
|
|
100
104
|
} else {
|
|
101
105
|
cleaned.push('Memory: No cleanup needed')
|
|
102
106
|
}
|
|
103
|
-
} catch {
|
|
104
|
-
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (isNotFoundError(error)) {
|
|
109
|
+
cleaned.push('Memory: No file found')
|
|
110
|
+
} else {
|
|
111
|
+
cleaned.push(`Memory: Error - ${(error as Error).message}`)
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
// Clean ideas using ideasStorage
|
|
@@ -112,8 +120,12 @@ export async function cleanup(
|
|
|
112
120
|
} else {
|
|
113
121
|
cleaned.push('Ideas: No cleanup needed')
|
|
114
122
|
}
|
|
115
|
-
} catch {
|
|
116
|
-
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (isNotFoundError(error)) {
|
|
125
|
+
cleaned.push('Ideas: No file found')
|
|
126
|
+
} else {
|
|
127
|
+
cleaned.push(`Ideas: Error - ${(error as Error).message}`)
|
|
128
|
+
}
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
// Check queue for completed tasks using queueStorage
|
|
@@ -128,8 +140,12 @@ export async function cleanup(
|
|
|
128
140
|
} else {
|
|
129
141
|
cleaned.push('Queue: No completed tasks')
|
|
130
142
|
}
|
|
131
|
-
} catch {
|
|
132
|
-
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (isNotFoundError(error)) {
|
|
145
|
+
cleaned.push('Queue: No file found')
|
|
146
|
+
} else {
|
|
147
|
+
cleaned.push(`Queue: Error - ${(error as Error).message}`)
|
|
148
|
+
}
|
|
133
149
|
}
|
|
134
150
|
|
|
135
151
|
await cleanupMemoryInternal(projectPath)
|
|
@@ -281,7 +281,8 @@ export class PlanningCommands extends PrjctCommandsBase {
|
|
|
281
281
|
let planContent: string
|
|
282
282
|
try {
|
|
283
283
|
planContent = await fileHelper.readFile(planPath)
|
|
284
|
-
} catch {
|
|
284
|
+
} catch (_error) {
|
|
285
|
+
// No plan file - expected for projects without architect mode
|
|
285
286
|
return {
|
|
286
287
|
success: false,
|
|
287
288
|
message:
|
|
@@ -465,7 +466,8 @@ Generated: ${new Date().toLocaleString()}
|
|
|
465
466
|
console.log('═'.repeat(50) + '\n')
|
|
466
467
|
|
|
467
468
|
return { success: true, specs }
|
|
468
|
-
} catch {
|
|
469
|
+
} catch (_error) {
|
|
470
|
+
// No specs directory - expected for new projects
|
|
469
471
|
out.warn('no specs directory')
|
|
470
472
|
return { success: true, specs: [] }
|
|
471
473
|
}
|
package/core/commands/setup.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import path from 'path'
|
|
6
6
|
import fs from 'fs'
|
|
7
|
-
import os from 'os'
|
|
8
7
|
import chalk from 'chalk'
|
|
9
8
|
|
|
10
9
|
import commandInstaller from '../infrastructure/command-installer'
|
|
10
|
+
import pathManager from '../infrastructure/path-manager'
|
|
11
11
|
import type { CommandResult, SetupOptions, MigrateOptions } from '../types'
|
|
12
12
|
import { PrjctCommandsBase } from './base'
|
|
13
13
|
import { VERSION } from '../utils/version'
|
|
@@ -126,8 +126,8 @@ export class SetupCommands extends PrjctCommandsBase {
|
|
|
126
126
|
*/
|
|
127
127
|
async installStatusLine(): Promise<{ success: boolean; error?: string }> {
|
|
128
128
|
try {
|
|
129
|
-
const claudeDir =
|
|
130
|
-
const settingsPath =
|
|
129
|
+
const claudeDir = pathManager.getClaudeDir()
|
|
130
|
+
const settingsPath = pathManager.getClaudeSettingsPath()
|
|
131
131
|
const statusLinePath = path.join(claudeDir, 'prjct-statusline.sh')
|
|
132
132
|
|
|
133
133
|
// Version is embedded at install time
|
|
@@ -194,7 +194,7 @@ echo "⚡ prjct"
|
|
|
194
194
|
if (fs.existsSync(settingsPath)) {
|
|
195
195
|
try {
|
|
196
196
|
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'))
|
|
197
|
-
} catch {
|
|
197
|
+
} catch (_error) {
|
|
198
198
|
// Invalid JSON, start fresh
|
|
199
199
|
}
|
|
200
200
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import path from 'path'
|
|
7
7
|
|
|
8
|
+
import { isNotFoundError } from '../types/fs'
|
|
8
9
|
import memorySystem from '../agentic/memory-system'
|
|
9
10
|
import type { CommandResult } from '../types'
|
|
10
11
|
import { detectProjectCommands } from '../utils/project-commands'
|
|
@@ -133,7 +134,11 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
133
134
|
|
|
134
135
|
const { exitCode } = await this._runWithExitCode(detected.lint.command)
|
|
135
136
|
return { success: exitCode === 0, message: exitCode === 0 ? 'passed' : 'failed' }
|
|
136
|
-
} catch {
|
|
137
|
+
} catch (error) {
|
|
138
|
+
// Lint detection/execution failed - skip gracefully
|
|
139
|
+
if (isNotFoundError(error)) {
|
|
140
|
+
return { success: true, message: 'skipped (lint not found)' }
|
|
141
|
+
}
|
|
137
142
|
return { success: true, message: 'skipped (lint detection failed)' }
|
|
138
143
|
}
|
|
139
144
|
}
|
|
@@ -148,7 +153,11 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
148
153
|
|
|
149
154
|
const { exitCode } = await this._runWithExitCode(detected.test.command)
|
|
150
155
|
return { success: exitCode === 0, message: exitCode === 0 ? 'passed' : 'failed' }
|
|
151
|
-
} catch {
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Test detection/execution failed - skip gracefully
|
|
158
|
+
if (isNotFoundError(error)) {
|
|
159
|
+
return { success: true, message: 'skipped (tests not found)' }
|
|
160
|
+
}
|
|
152
161
|
return { success: true, message: 'skipped (test detection failed)' }
|
|
153
162
|
}
|
|
154
163
|
}
|
|
@@ -168,8 +177,12 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
168
177
|
await fileHelper.writeJson(pkgPath, pkg)
|
|
169
178
|
}
|
|
170
179
|
return newVersion
|
|
171
|
-
} catch {
|
|
172
|
-
return
|
|
180
|
+
} catch (error) {
|
|
181
|
+
// No package.json or parse error - return default version
|
|
182
|
+
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
183
|
+
return '0.0.1'
|
|
184
|
+
}
|
|
185
|
+
throw error
|
|
173
186
|
}
|
|
174
187
|
}
|
|
175
188
|
|
|
@@ -185,8 +198,13 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
185
198
|
const updated = changelog.replace('# Changelog\n\n', `# Changelog\n\n${entry}`)
|
|
186
199
|
|
|
187
200
|
await fileHelper.writeFile(changelogPath, updated)
|
|
188
|
-
} catch {
|
|
189
|
-
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// CHANGELOG doesn't exist or can't be written - warn but continue
|
|
203
|
+
if (isNotFoundError(error)) {
|
|
204
|
+
console.error(' Warning: CHANGELOG.md not found')
|
|
205
|
+
} else {
|
|
206
|
+
console.error(' Warning: Could not update CHANGELOG')
|
|
207
|
+
}
|
|
190
208
|
}
|
|
191
209
|
}
|
|
192
210
|
|
|
@@ -202,7 +220,11 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
202
220
|
await toolRegistry.get('Bash')!(`git commit -m "${commitMsg.replace(/"/g, '\\"')}"`)
|
|
203
221
|
|
|
204
222
|
return { success: true, message: 'Committed' }
|
|
205
|
-
} catch {
|
|
223
|
+
} catch (error) {
|
|
224
|
+
// Git commit failed - likely no changes or not a repo
|
|
225
|
+
if (isNotFoundError(error)) {
|
|
226
|
+
return { success: false, message: 'Git not found' }
|
|
227
|
+
}
|
|
206
228
|
return { success: false, message: 'No changes to commit' }
|
|
207
229
|
}
|
|
208
230
|
}
|
|
@@ -214,7 +236,11 @@ export class ShippingCommands extends PrjctCommandsBase {
|
|
|
214
236
|
try {
|
|
215
237
|
await toolRegistry.get('Bash')!('git push')
|
|
216
238
|
return { success: true, message: 'Pushed to remote' }
|
|
217
|
-
} catch {
|
|
239
|
+
} catch (error) {
|
|
240
|
+
// Git push failed - no remote, auth issue, or git not found
|
|
241
|
+
if (isNotFoundError(error)) {
|
|
242
|
+
return { success: false, message: 'Git not found' }
|
|
243
|
+
}
|
|
218
244
|
return { success: false, message: 'Push failed (no remote or auth issue)' }
|
|
219
245
|
}
|
|
220
246
|
}
|