prjct-cli 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/core/bus/bus.ts +47 -26
- package/core/commands/analysis.ts +17 -4
- package/core/index.ts +1 -1
- package/core/server/routes.ts +4 -3
- package/core/types/bus.ts +112 -1
- package/core/types/index.ts +16 -0
- package/dist/bin/prjct.mjs +58 -48
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,90 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.2] - 2026-02-06
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- replace console.error with logger in routes.ts (PRJ-73) (#125)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [1.6.4] - 2026-02-06
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **Replace console.error with logger in routes.ts**: Server routes now use the centralized `log` module instead of raw `console.error` for JSON read/write and context read errors. Production remains quiet by default; enable with `PRJCT_DEBUG=1`.
|
|
15
|
+
|
|
16
|
+
## [1.6.3] - 2026-02-06
|
|
17
|
+
|
|
18
|
+
### Improvements
|
|
19
|
+
|
|
20
|
+
- **Typed event bus payloads**: Added 15 typed payload interfaces (`SessionStartedPayload`, `SnapshotCreatedPayload`, etc.) and an `EventMap` type mapping event strings to their payloads. Convenience `emit` methods now enforce required fields at compile time. Backward compatible — callers with `Record<string, unknown>` still work.
|
|
21
|
+
|
|
22
|
+
### Implementation Details
|
|
23
|
+
- `core/types/bus.ts`: Added `EventMap` interface and all payload types
|
|
24
|
+
- `core/bus/bus.ts`: Generic overload `emit<K extends keyof EventMap>()`, typed convenience methods
|
|
25
|
+
- `core/types/index.ts`: Exported all new payload types
|
|
26
|
+
|
|
27
|
+
### Test Plan
|
|
28
|
+
|
|
29
|
+
#### For QA
|
|
30
|
+
1. `bun run typecheck` — zero errors
|
|
31
|
+
2. `emit.sessionStarted({})` → TS error for missing fields (IntelliSense works)
|
|
32
|
+
3. `bun test` — all 416 tests pass
|
|
33
|
+
|
|
34
|
+
#### For Users
|
|
35
|
+
- **What changed:** Event emit methods have typed payloads with autocomplete
|
|
36
|
+
- **Breaking changes:** None
|
|
37
|
+
|
|
38
|
+
## [1.6.2] - 2026-02-06
|
|
39
|
+
|
|
40
|
+
### Improvements
|
|
41
|
+
|
|
42
|
+
- **Diff preview before sync overwrites**: `prjct sync --dry-run` (or `--preview`) now shows what would change in CLAUDE.md without applying changes. Cancelling interactive sync restores the original file. Previously, files were written before the diff was shown, so cancel/preview still applied changes.
|
|
43
|
+
|
|
44
|
+
### Implementation Details
|
|
45
|
+
- Added `--dry-run` CLI flag as alias for `--preview`
|
|
46
|
+
- Added `restoreOriginal()` helper that writes back saved CLAUDE.md content on cancel/preview
|
|
47
|
+
- Non-interactive mode (LLM) restores original and returns JSON — apply with `prjct sync --yes`
|
|
48
|
+
|
|
49
|
+
### Test Plan
|
|
50
|
+
|
|
51
|
+
#### For QA
|
|
52
|
+
1. `prjct sync --dry-run` — diff shown, CLAUDE.md NOT modified
|
|
53
|
+
2. `prjct sync` → cancel — CLAUDE.md restored
|
|
54
|
+
3. `prjct sync` → approve — changes kept
|
|
55
|
+
4. `prjct sync --yes` — applied directly
|
|
56
|
+
5. `prjct sync --json` — JSON returned, CLAUDE.md restored
|
|
57
|
+
|
|
58
|
+
#### For Users
|
|
59
|
+
- **What changed:** `--dry-run` flag works correctly; cancel restores original
|
|
60
|
+
- **How to use:** `prjct sync --dry-run` to preview, `prjct sync --yes` to apply
|
|
61
|
+
- **Breaking changes:** None
|
|
62
|
+
|
|
63
|
+
## [1.6.1] - 2026-02-06
|
|
64
|
+
|
|
65
|
+
### Bug Fixes
|
|
66
|
+
|
|
67
|
+
- replace console.error with logger in bus.ts (PRJ-72) (#122)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
## [1.6.1] - 2026-02-06
|
|
71
|
+
|
|
72
|
+
### Bug Fixes
|
|
73
|
+
|
|
74
|
+
- **Replace console.error with logger in bus.ts**: Event bus now uses the centralized `log` module instead of raw `console.error` for error logging. Silent catch block in `logEvent()` now logs at debug level with `getErrorMessage()` context. Production remains quiet by default; enable with `PRJCT_DEBUG=1`.
|
|
75
|
+
|
|
76
|
+
### Test Plan
|
|
77
|
+
|
|
78
|
+
#### For QA
|
|
79
|
+
1. Run `PRJCT_DEBUG=1 bun test` — verify bus errors appear with `[prjct:error]` prefix
|
|
80
|
+
2. Run `bun test` (no debug) — verify bus errors are silent by default
|
|
81
|
+
3. Trigger a listener error — verify it logs via logger, not console.error
|
|
82
|
+
|
|
83
|
+
#### For Users
|
|
84
|
+
- **What changed:** Error logging in event bus uses centralized logger
|
|
85
|
+
- **How to use:** `PRJCT_DEBUG=1` to see bus errors; quiet by default
|
|
86
|
+
- **Breaking changes:** None
|
|
87
|
+
|
|
3
88
|
## [1.6.0] - 2026-02-06
|
|
4
89
|
|
|
5
90
|
### Features
|
package/core/bus/bus.ts
CHANGED
|
@@ -9,8 +9,30 @@
|
|
|
9
9
|
|
|
10
10
|
import fs from 'node:fs/promises'
|
|
11
11
|
import path from 'node:path'
|
|
12
|
+
import { getErrorMessage } from '../errors'
|
|
12
13
|
import pathManager from '../infrastructure/path-manager'
|
|
13
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
type AnalysisCompletedPayload,
|
|
16
|
+
type EventCallback,
|
|
17
|
+
type EventData,
|
|
18
|
+
type EventMap,
|
|
19
|
+
EventTypes,
|
|
20
|
+
type FeaturePayload,
|
|
21
|
+
type GitCommitPayload,
|
|
22
|
+
type GitPushPayload,
|
|
23
|
+
type IdeaCapturedPayload,
|
|
24
|
+
type ProjectInitializedPayload,
|
|
25
|
+
type ProjectSyncedPayload,
|
|
26
|
+
type SessionCompletedPayload,
|
|
27
|
+
type SessionPausedPayload,
|
|
28
|
+
type SessionResumedPayload,
|
|
29
|
+
type SessionStartedPayload,
|
|
30
|
+
type SnapshotCreatedPayload,
|
|
31
|
+
type SnapshotRestoredPayload,
|
|
32
|
+
type TaskCompletedPayload,
|
|
33
|
+
type TaskCreatedPayload,
|
|
34
|
+
} from '../types'
|
|
35
|
+
import log from '../utils/logger'
|
|
14
36
|
|
|
15
37
|
class EventBus {
|
|
16
38
|
private listeners: Map<string, Set<EventCallback>>
|
|
@@ -75,8 +97,10 @@ class EventBus {
|
|
|
75
97
|
}
|
|
76
98
|
|
|
77
99
|
/**
|
|
78
|
-
* Emit an event
|
|
100
|
+
* Emit an event with typed payload
|
|
79
101
|
*/
|
|
102
|
+
async emit<K extends keyof EventMap>(event: K, data: EventMap[K]): Promise<void>
|
|
103
|
+
async emit(event: string, data: Record<string, unknown>): Promise<void>
|
|
80
104
|
async emit(event: string, data: Record<string, unknown> = {}): Promise<void> {
|
|
81
105
|
const timestamp = new Date().toISOString()
|
|
82
106
|
const eventData: EventData = {
|
|
@@ -108,7 +132,7 @@ class EventBus {
|
|
|
108
132
|
// Log any errors
|
|
109
133
|
results.forEach((result) => {
|
|
110
134
|
if (result.status === 'rejected') {
|
|
111
|
-
|
|
135
|
+
log.error(`Event listener error for ${event}:`, result.reason)
|
|
112
136
|
}
|
|
113
137
|
})
|
|
114
138
|
|
|
@@ -169,7 +193,7 @@ class EventBus {
|
|
|
169
193
|
await result
|
|
170
194
|
}
|
|
171
195
|
} catch (error) {
|
|
172
|
-
|
|
196
|
+
log.error('Event callback error:', error)
|
|
173
197
|
throw error
|
|
174
198
|
}
|
|
175
199
|
}
|
|
@@ -188,8 +212,8 @@ class EventBus {
|
|
|
188
212
|
// Append event
|
|
189
213
|
const line = `${JSON.stringify(eventData)}\n`
|
|
190
214
|
await fs.appendFile(eventsPath, line)
|
|
191
|
-
} catch (
|
|
192
|
-
|
|
215
|
+
} catch (error) {
|
|
216
|
+
log.debug('Failed to log event:', getErrorMessage(error))
|
|
193
217
|
}
|
|
194
218
|
}
|
|
195
219
|
|
|
@@ -231,37 +255,34 @@ class EventBus {
|
|
|
231
255
|
// Singleton instance
|
|
232
256
|
const eventBus = new EventBus()
|
|
233
257
|
|
|
234
|
-
// Convenience methods for common events
|
|
258
|
+
// Convenience methods for common events (typed payloads)
|
|
235
259
|
const emit = {
|
|
236
|
-
sessionStarted: (data:
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
eventBus.emit(EventTypes.SESSION_RESUMED, data),
|
|
241
|
-
sessionCompleted: (data: Record<string, unknown>) =>
|
|
260
|
+
sessionStarted: (data: SessionStartedPayload) => eventBus.emit(EventTypes.SESSION_STARTED, data),
|
|
261
|
+
sessionPaused: (data: SessionPausedPayload) => eventBus.emit(EventTypes.SESSION_PAUSED, data),
|
|
262
|
+
sessionResumed: (data: SessionResumedPayload) => eventBus.emit(EventTypes.SESSION_RESUMED, data),
|
|
263
|
+
sessionCompleted: (data: SessionCompletedPayload) =>
|
|
242
264
|
eventBus.emit(EventTypes.SESSION_COMPLETED, data),
|
|
243
265
|
|
|
244
|
-
taskCreated: (data:
|
|
245
|
-
taskCompleted: (data:
|
|
266
|
+
taskCreated: (data: TaskCreatedPayload) => eventBus.emit(EventTypes.TASK_CREATED, data),
|
|
267
|
+
taskCompleted: (data: TaskCompletedPayload) => eventBus.emit(EventTypes.TASK_COMPLETED, data),
|
|
246
268
|
|
|
247
|
-
featureAdded: (data:
|
|
248
|
-
featureShipped: (data:
|
|
249
|
-
eventBus.emit(EventTypes.FEATURE_SHIPPED, data),
|
|
269
|
+
featureAdded: (data: FeaturePayload) => eventBus.emit(EventTypes.FEATURE_ADDED, data),
|
|
270
|
+
featureShipped: (data: FeaturePayload) => eventBus.emit(EventTypes.FEATURE_SHIPPED, data),
|
|
250
271
|
|
|
251
|
-
ideaCaptured: (data:
|
|
272
|
+
ideaCaptured: (data: IdeaCapturedPayload) => eventBus.emit(EventTypes.IDEA_CAPTURED, data),
|
|
252
273
|
|
|
253
|
-
snapshotCreated: (data:
|
|
274
|
+
snapshotCreated: (data: SnapshotCreatedPayload) =>
|
|
254
275
|
eventBus.emit(EventTypes.SNAPSHOT_CREATED, data),
|
|
255
|
-
snapshotRestored: (data:
|
|
276
|
+
snapshotRestored: (data: SnapshotRestoredPayload) =>
|
|
256
277
|
eventBus.emit(EventTypes.SNAPSHOT_RESTORED, data),
|
|
257
278
|
|
|
258
|
-
commitCreated: (data:
|
|
259
|
-
pushCompleted: (data:
|
|
279
|
+
commitCreated: (data: GitCommitPayload) => eventBus.emit(EventTypes.COMMIT_CREATED, data),
|
|
280
|
+
pushCompleted: (data: GitPushPayload) => eventBus.emit(EventTypes.PUSH_COMPLETED, data),
|
|
260
281
|
|
|
261
|
-
projectInitialized: (data:
|
|
282
|
+
projectInitialized: (data: ProjectInitializedPayload) =>
|
|
262
283
|
eventBus.emit(EventTypes.PROJECT_INITIALIZED, data),
|
|
263
|
-
projectSynced: (data:
|
|
264
|
-
analysisCompleted: (data:
|
|
284
|
+
projectSynced: (data: ProjectSyncedPayload) => eventBus.emit(EventTypes.PROJECT_SYNCED, data),
|
|
285
|
+
analysisCompleted: (data: AnalysisCompletedPayload) =>
|
|
265
286
|
eventBus.emit(EventTypes.ANALYSIS_COMPLETED, data),
|
|
266
287
|
}
|
|
267
288
|
|
|
@@ -347,8 +347,18 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
347
347
|
return { success: true, message: 'No changes' }
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
+
// Helper to restore original CLAUDE.md (undo sync's write)
|
|
351
|
+
const restoreOriginal = async () => {
|
|
352
|
+
if (existingContent != null) {
|
|
353
|
+
await fs.writeFile(claudeMdPath, existingContent, 'utf-8')
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
350
357
|
// Non-interactive mode: return JSON for LLM to handle
|
|
351
358
|
if (isNonInteractive) {
|
|
359
|
+
// Restore original — LLM will call `prjct sync --yes` to apply
|
|
360
|
+
await restoreOriginal()
|
|
361
|
+
|
|
352
362
|
// Build a plain-text diff summary for LLM to show user
|
|
353
363
|
const diffSummary = {
|
|
354
364
|
added: diff.added.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
@@ -388,8 +398,9 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
388
398
|
// Show diff preview (interactive mode)
|
|
389
399
|
console.log(formatDiffPreview(diff))
|
|
390
400
|
|
|
391
|
-
// Preview-only mode - don't apply
|
|
401
|
+
// Preview-only mode (--preview / --dry-run) - restore and don't apply
|
|
392
402
|
if (options.preview) {
|
|
403
|
+
await restoreOriginal()
|
|
393
404
|
return {
|
|
394
405
|
success: true,
|
|
395
406
|
isPreview: true,
|
|
@@ -411,7 +422,8 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
411
422
|
})
|
|
412
423
|
|
|
413
424
|
if (response.action === 'cancel' || !response.action) {
|
|
414
|
-
|
|
425
|
+
await restoreOriginal()
|
|
426
|
+
out.warn('Sync cancelled — no changes applied')
|
|
415
427
|
return { success: false, message: 'Cancelled by user' }
|
|
416
428
|
}
|
|
417
429
|
|
|
@@ -424,12 +436,13 @@ export class AnalysisCommands extends PrjctCommandsBase {
|
|
|
424
436
|
initial: true,
|
|
425
437
|
})
|
|
426
438
|
if (!confirm.apply) {
|
|
427
|
-
|
|
439
|
+
await restoreOriginal()
|
|
440
|
+
out.warn('Sync cancelled — no changes applied')
|
|
428
441
|
return { success: false, message: 'Cancelled by user' }
|
|
429
442
|
}
|
|
430
443
|
}
|
|
431
444
|
|
|
432
|
-
//
|
|
445
|
+
// User approved — changes already applied by sync
|
|
433
446
|
out.done('Changes applied')
|
|
434
447
|
return this.showSyncResult(result, startTime)
|
|
435
448
|
}
|
package/core/index.ts
CHANGED
|
@@ -162,7 +162,7 @@ async function main(): Promise<void> {
|
|
|
162
162
|
sync: () =>
|
|
163
163
|
commands.sync(process.cwd(), {
|
|
164
164
|
aiTools: options.agents ? String(options.agents).split(',') : undefined,
|
|
165
|
-
preview: options.preview === true,
|
|
165
|
+
preview: options.preview === true || options['dry-run'] === true,
|
|
166
166
|
yes: options.yes === true,
|
|
167
167
|
json: options.json === true,
|
|
168
168
|
package: options.package ? String(options.package) : undefined,
|
package/core/server/routes.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { Hono } from 'hono'
|
|
|
12
12
|
import * as jsonc from 'jsonc-parser'
|
|
13
13
|
import pathManager from '../infrastructure/path-manager'
|
|
14
14
|
import { isNotFoundError } from '../types/fs'
|
|
15
|
+
import log from '../utils/logger'
|
|
15
16
|
|
|
16
17
|
// Storage paths relative to project data directory
|
|
17
18
|
const STORAGE_PATHS = {
|
|
@@ -34,7 +35,7 @@ async function readJsonFile<T>(filePath: string): Promise<T | null> {
|
|
|
34
35
|
} catch (error) {
|
|
35
36
|
// ENOENT or parse error - expected for new projects
|
|
36
37
|
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
37
|
-
|
|
38
|
+
log.error(`JSON read error: ${(error as Error).message}`)
|
|
38
39
|
}
|
|
39
40
|
return null
|
|
40
41
|
}
|
|
@@ -49,7 +50,7 @@ async function writeJsonFile(filePath: string, data: unknown): Promise<boolean>
|
|
|
49
50
|
await fs.writeFile(filePath, `${JSON.stringify(data, null, 2)}\n`, 'utf-8')
|
|
50
51
|
return true
|
|
51
52
|
} catch (error) {
|
|
52
|
-
|
|
53
|
+
log.error(`JSON write error: ${(error as Error).message}`)
|
|
53
54
|
return false
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -165,7 +166,7 @@ export function createRoutes(projectId: string, _projectPath: string): Hono {
|
|
|
165
166
|
} catch (error) {
|
|
166
167
|
// ENOENT - context file doesn't exist yet (expected)
|
|
167
168
|
if (!isNotFoundError(error)) {
|
|
168
|
-
|
|
169
|
+
log.error(`Context read error: ${(error as Error).message}`)
|
|
169
170
|
}
|
|
170
171
|
return c.text('', 200, { 'Content-Type': 'text/markdown' })
|
|
171
172
|
}
|
package/core/types/bus.ts
CHANGED
|
@@ -58,7 +58,7 @@ export const EventTypes = {
|
|
|
58
58
|
export type BusEventType = (typeof EventTypes)[keyof typeof EventTypes]
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
|
-
* Event data payload
|
|
61
|
+
* Event data payload (base interface for all events)
|
|
62
62
|
*/
|
|
63
63
|
export interface EventData {
|
|
64
64
|
type: string
|
|
@@ -67,6 +67,117 @@ export interface EventData {
|
|
|
67
67
|
[key: string]: unknown
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// Typed Event Payloads
|
|
72
|
+
// =============================================================================
|
|
73
|
+
|
|
74
|
+
export interface SessionStartedPayload {
|
|
75
|
+
sessionId: string
|
|
76
|
+
task: unknown
|
|
77
|
+
projectId: string | null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface SessionPausedPayload {
|
|
81
|
+
sessionId: string
|
|
82
|
+
task: unknown
|
|
83
|
+
duration: number
|
|
84
|
+
projectId: string | null
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface SessionResumedPayload {
|
|
88
|
+
sessionId: string
|
|
89
|
+
task: unknown
|
|
90
|
+
projectId: string | null
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface SessionCompletedPayload {
|
|
94
|
+
sessionId: string
|
|
95
|
+
task: unknown
|
|
96
|
+
duration: number
|
|
97
|
+
metrics: unknown
|
|
98
|
+
projectId: string | null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface TaskCreatedPayload {
|
|
102
|
+
taskId: string
|
|
103
|
+
description: string
|
|
104
|
+
[key: string]: unknown
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface TaskCompletedPayload {
|
|
108
|
+
taskId: string
|
|
109
|
+
[key: string]: unknown
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface FeaturePayload {
|
|
113
|
+
[key: string]: unknown
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface IdeaCapturedPayload {
|
|
117
|
+
[key: string]: unknown
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface SnapshotCreatedPayload {
|
|
121
|
+
hash: string
|
|
122
|
+
message: string
|
|
123
|
+
timestamp: string
|
|
124
|
+
filesCount: number
|
|
125
|
+
projectId: string | null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface SnapshotRestoredPayload {
|
|
129
|
+
hash: string
|
|
130
|
+
filesCount: number
|
|
131
|
+
timestamp: string
|
|
132
|
+
projectId: string | null
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface GitCommitPayload {
|
|
136
|
+
[key: string]: unknown
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface GitPushPayload {
|
|
140
|
+
[key: string]: unknown
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface ProjectInitializedPayload {
|
|
144
|
+
[key: string]: unknown
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface ProjectSyncedPayload {
|
|
148
|
+
[key: string]: unknown
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface AnalysisCompletedPayload {
|
|
152
|
+
[key: string]: unknown
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Maps event type strings to their typed payloads
|
|
157
|
+
*/
|
|
158
|
+
export interface EventMap {
|
|
159
|
+
[EventTypes.SESSION_STARTED]: SessionStartedPayload
|
|
160
|
+
[EventTypes.SESSION_PAUSED]: SessionPausedPayload
|
|
161
|
+
[EventTypes.SESSION_RESUMED]: SessionResumedPayload
|
|
162
|
+
[EventTypes.SESSION_COMPLETED]: SessionCompletedPayload
|
|
163
|
+
[EventTypes.TASK_CREATED]: TaskCreatedPayload
|
|
164
|
+
[EventTypes.TASK_COMPLETED]: TaskCompletedPayload
|
|
165
|
+
[EventTypes.TASK_UPDATED]: Record<string, unknown>
|
|
166
|
+
[EventTypes.FEATURE_ADDED]: FeaturePayload
|
|
167
|
+
[EventTypes.FEATURE_SHIPPED]: FeaturePayload
|
|
168
|
+
[EventTypes.FEATURE_UPDATED]: FeaturePayload
|
|
169
|
+
[EventTypes.IDEA_CAPTURED]: IdeaCapturedPayload
|
|
170
|
+
[EventTypes.IDEA_PROMOTED]: Record<string, unknown>
|
|
171
|
+
[EventTypes.SNAPSHOT_CREATED]: SnapshotCreatedPayload
|
|
172
|
+
[EventTypes.SNAPSHOT_RESTORED]: SnapshotRestoredPayload
|
|
173
|
+
[EventTypes.COMMIT_CREATED]: GitCommitPayload
|
|
174
|
+
[EventTypes.PUSH_COMPLETED]: GitPushPayload
|
|
175
|
+
[EventTypes.PROJECT_INITIALIZED]: ProjectInitializedPayload
|
|
176
|
+
[EventTypes.PROJECT_SYNCED]: ProjectSyncedPayload
|
|
177
|
+
[EventTypes.ANALYSIS_COMPLETED]: AnalysisCompletedPayload
|
|
178
|
+
[EventTypes.ALL]: Record<string, unknown>
|
|
179
|
+
}
|
|
180
|
+
|
|
70
181
|
/**
|
|
71
182
|
* Event callback handler
|
|
72
183
|
*/
|
package/core/types/index.ts
CHANGED
|
@@ -118,10 +118,26 @@ export type {
|
|
|
118
118
|
// Bus Types
|
|
119
119
|
// =============================================================================
|
|
120
120
|
export type {
|
|
121
|
+
AnalysisCompletedPayload,
|
|
121
122
|
BusEventType,
|
|
122
123
|
EventCallback,
|
|
123
124
|
EventData,
|
|
125
|
+
EventMap,
|
|
124
126
|
EventSubscription,
|
|
127
|
+
FeaturePayload,
|
|
128
|
+
GitCommitPayload,
|
|
129
|
+
GitPushPayload,
|
|
130
|
+
IdeaCapturedPayload,
|
|
131
|
+
ProjectInitializedPayload,
|
|
132
|
+
ProjectSyncedPayload,
|
|
133
|
+
SessionCompletedPayload,
|
|
134
|
+
SessionPausedPayload,
|
|
135
|
+
SessionResumedPayload,
|
|
136
|
+
SessionStartedPayload,
|
|
137
|
+
SnapshotCreatedPayload,
|
|
138
|
+
SnapshotRestoredPayload,
|
|
139
|
+
TaskCompletedPayload,
|
|
140
|
+
TaskCreatedPayload,
|
|
125
141
|
} from './bus'
|
|
126
142
|
export { EventTypes } from './bus'
|
|
127
143
|
// =============================================================================
|
package/dist/bin/prjct.mjs
CHANGED
|
@@ -2092,6 +2092,45 @@ var init_editors_config = __esm({
|
|
|
2092
2092
|
}
|
|
2093
2093
|
});
|
|
2094
2094
|
|
|
2095
|
+
// core/utils/logger.ts
|
|
2096
|
+
function getLogLevel() {
|
|
2097
|
+
const debugEnv = process.env.PRJCT_DEBUG || process.env.DEBUG || "";
|
|
2098
|
+
if (!debugEnv) return { level: -1, name: "disabled" };
|
|
2099
|
+
if (TRUTHY_VALUES.has(debugEnv) || debugEnv.includes("prjct")) {
|
|
2100
|
+
return { level: LEVELS.debug, name: "debug" };
|
|
2101
|
+
}
|
|
2102
|
+
const levelValue = LEVELS[debugEnv] ?? -1;
|
|
2103
|
+
const levelName = levelValue >= 0 ? debugEnv : "disabled";
|
|
2104
|
+
return { level: levelValue, name: levelName };
|
|
2105
|
+
}
|
|
2106
|
+
function createLogMethod(levelThreshold, prefix, method) {
|
|
2107
|
+
return currentLevel >= levelThreshold ? (...args2) => console[method](prefix, ...args2) : noop;
|
|
2108
|
+
}
|
|
2109
|
+
var LEVELS, TRUTHY_VALUES, currentLevel, currentLevelName, noop, logger, logger_default;
|
|
2110
|
+
var init_logger = __esm({
|
|
2111
|
+
"core/utils/logger.ts"() {
|
|
2112
|
+
"use strict";
|
|
2113
|
+
LEVELS = { error: 0, warn: 1, info: 2, debug: 3 };
|
|
2114
|
+
TRUTHY_VALUES = /* @__PURE__ */ new Set(["1", "true", "*"]);
|
|
2115
|
+
__name(getLogLevel, "getLogLevel");
|
|
2116
|
+
({ level: currentLevel, name: currentLevelName } = getLogLevel());
|
|
2117
|
+
noop = /* @__PURE__ */ __name(() => {
|
|
2118
|
+
}, "noop");
|
|
2119
|
+
__name(createLogMethod, "createLogMethod");
|
|
2120
|
+
logger = {
|
|
2121
|
+
error: createLogMethod(LEVELS.error, "[prjct:error]", "error"),
|
|
2122
|
+
warn: createLogMethod(LEVELS.warn, "[prjct:warn]", "warn"),
|
|
2123
|
+
info: createLogMethod(LEVELS.info, "[prjct:info]", "log"),
|
|
2124
|
+
debug: createLogMethod(LEVELS.debug, "[prjct:debug]", "log"),
|
|
2125
|
+
// Check if logging is enabled (useful for expensive log prep)
|
|
2126
|
+
isEnabled: /* @__PURE__ */ __name(() => currentLevel >= 0, "isEnabled"),
|
|
2127
|
+
// Get current level name (pre-computed, no runtime lookup)
|
|
2128
|
+
level: /* @__PURE__ */ __name(() => currentLevelName, "level")
|
|
2129
|
+
};
|
|
2130
|
+
logger_default = logger;
|
|
2131
|
+
}
|
|
2132
|
+
});
|
|
2133
|
+
|
|
2095
2134
|
// core/utils/branding.ts
|
|
2096
2135
|
import chalk from "chalk";
|
|
2097
2136
|
var SPINNER_FRAMES, SPINNER_SPEED, branding, branding_default;
|
|
@@ -19160,7 +19199,13 @@ var init_analysis2 = __esm({
|
|
|
19160
19199
|
output_default.done("No changes detected (context is up to date)");
|
|
19161
19200
|
return { success: true, message: "No changes" };
|
|
19162
19201
|
}
|
|
19202
|
+
const restoreOriginal = /* @__PURE__ */ __name(async () => {
|
|
19203
|
+
if (existingContent != null) {
|
|
19204
|
+
await fs36.writeFile(claudeMdPath, existingContent, "utf-8");
|
|
19205
|
+
}
|
|
19206
|
+
}, "restoreOriginal");
|
|
19163
19207
|
if (isNonInteractive) {
|
|
19208
|
+
await restoreOriginal();
|
|
19164
19209
|
const diffSummary = {
|
|
19165
19210
|
added: diff.added.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
19166
19211
|
modified: diff.modified.map((s) => ({ name: s.name, lineCount: s.lineCount })),
|
|
@@ -19193,6 +19238,7 @@ var init_analysis2 = __esm({
|
|
|
19193
19238
|
}
|
|
19194
19239
|
console.log(formatDiffPreview(diff));
|
|
19195
19240
|
if (options.preview) {
|
|
19241
|
+
await restoreOriginal();
|
|
19196
19242
|
return {
|
|
19197
19243
|
success: true,
|
|
19198
19244
|
isPreview: true,
|
|
@@ -19211,7 +19257,8 @@ var init_analysis2 = __esm({
|
|
|
19211
19257
|
]
|
|
19212
19258
|
});
|
|
19213
19259
|
if (response.action === "cancel" || !response.action) {
|
|
19214
|
-
|
|
19260
|
+
await restoreOriginal();
|
|
19261
|
+
output_default.warn("Sync cancelled \u2014 no changes applied");
|
|
19215
19262
|
return { success: false, message: "Cancelled by user" };
|
|
19216
19263
|
}
|
|
19217
19264
|
if (response.action === "diff") {
|
|
@@ -19224,7 +19271,8 @@ ${formatFullDiff(diff)}`);
|
|
|
19224
19271
|
initial: true
|
|
19225
19272
|
});
|
|
19226
19273
|
if (!confirm.apply) {
|
|
19227
|
-
|
|
19274
|
+
await restoreOriginal();
|
|
19275
|
+
output_default.warn("Sync cancelled \u2014 no changes applied");
|
|
19228
19276
|
return { success: false, message: "Cancelled by user" };
|
|
19229
19277
|
}
|
|
19230
19278
|
}
|
|
@@ -21052,45 +21100,6 @@ var init_ai_tools = __esm({
|
|
|
21052
21100
|
}
|
|
21053
21101
|
});
|
|
21054
21102
|
|
|
21055
|
-
// core/utils/logger.ts
|
|
21056
|
-
function getLogLevel() {
|
|
21057
|
-
const debugEnv = process.env.PRJCT_DEBUG || process.env.DEBUG || "";
|
|
21058
|
-
if (!debugEnv) return { level: -1, name: "disabled" };
|
|
21059
|
-
if (TRUTHY_VALUES.has(debugEnv) || debugEnv.includes("prjct")) {
|
|
21060
|
-
return { level: LEVELS.debug, name: "debug" };
|
|
21061
|
-
}
|
|
21062
|
-
const levelValue = LEVELS[debugEnv] ?? -1;
|
|
21063
|
-
const levelName = levelValue >= 0 ? debugEnv : "disabled";
|
|
21064
|
-
return { level: levelValue, name: levelName };
|
|
21065
|
-
}
|
|
21066
|
-
function createLogMethod(levelThreshold, prefix, method) {
|
|
21067
|
-
return currentLevel >= levelThreshold ? (...args2) => console[method](prefix, ...args2) : noop;
|
|
21068
|
-
}
|
|
21069
|
-
var LEVELS, TRUTHY_VALUES, currentLevel, currentLevelName, noop, logger2, logger_default;
|
|
21070
|
-
var init_logger = __esm({
|
|
21071
|
-
"core/utils/logger.ts"() {
|
|
21072
|
-
"use strict";
|
|
21073
|
-
LEVELS = { error: 0, warn: 1, info: 2, debug: 3 };
|
|
21074
|
-
TRUTHY_VALUES = /* @__PURE__ */ new Set(["1", "true", "*"]);
|
|
21075
|
-
__name(getLogLevel, "getLogLevel");
|
|
21076
|
-
({ level: currentLevel, name: currentLevelName } = getLogLevel());
|
|
21077
|
-
noop = /* @__PURE__ */ __name(() => {
|
|
21078
|
-
}, "noop");
|
|
21079
|
-
__name(createLogMethod, "createLogMethod");
|
|
21080
|
-
logger2 = {
|
|
21081
|
-
error: createLogMethod(LEVELS.error, "[prjct:error]", "error"),
|
|
21082
|
-
warn: createLogMethod(LEVELS.warn, "[prjct:warn]", "warn"),
|
|
21083
|
-
info: createLogMethod(LEVELS.info, "[prjct:info]", "log"),
|
|
21084
|
-
debug: createLogMethod(LEVELS.debug, "[prjct:debug]", "log"),
|
|
21085
|
-
// Check if logging is enabled (useful for expensive log prep)
|
|
21086
|
-
isEnabled: /* @__PURE__ */ __name(() => currentLevel >= 0, "isEnabled"),
|
|
21087
|
-
// Get current level name (pre-computed, no runtime lookup)
|
|
21088
|
-
level: /* @__PURE__ */ __name(() => currentLevelName, "level")
|
|
21089
|
-
};
|
|
21090
|
-
logger_default = logger2;
|
|
21091
|
-
}
|
|
21092
|
-
});
|
|
21093
|
-
|
|
21094
21103
|
// core/services/context-generator.ts
|
|
21095
21104
|
import fs39 from "node:fs/promises";
|
|
21096
21105
|
import path43 from "node:path";
|
|
@@ -28604,7 +28613,7 @@ var require_package = __commonJS({
|
|
|
28604
28613
|
"package.json"(exports, module) {
|
|
28605
28614
|
module.exports = {
|
|
28606
28615
|
name: "prjct-cli",
|
|
28607
|
-
version: "1.6.
|
|
28616
|
+
version: "1.6.2",
|
|
28608
28617
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
28609
28618
|
main: "core/index.ts",
|
|
28610
28619
|
bin: {
|
|
@@ -28812,7 +28821,7 @@ async function main() {
|
|
|
28812
28821
|
// Setup
|
|
28813
28822
|
sync: /* @__PURE__ */ __name(() => commands.sync(process.cwd(), {
|
|
28814
28823
|
aiTools: options.agents ? String(options.agents).split(",") : void 0,
|
|
28815
|
-
preview: options.preview === true,
|
|
28824
|
+
preview: options.preview === true || options["dry-run"] === true,
|
|
28816
28825
|
yes: options.yes === true,
|
|
28817
28826
|
json: options.json === true,
|
|
28818
28827
|
package: options.package ? String(options.package) : void 0
|
|
@@ -29058,7 +29067,7 @@ import chalk19 from "chalk";
|
|
|
29058
29067
|
// core/server/server.ts
|
|
29059
29068
|
import { Hono as Hono3 } from "hono";
|
|
29060
29069
|
import { cors } from "hono/cors";
|
|
29061
|
-
import { logger } from "hono/logger";
|
|
29070
|
+
import { logger as logger2 } from "hono/logger";
|
|
29062
29071
|
|
|
29063
29072
|
// core/utils/runtime.ts
|
|
29064
29073
|
function detectRuntime() {
|
|
@@ -29076,6 +29085,7 @@ __name(isBun, "isBun");
|
|
|
29076
29085
|
// core/server/routes.ts
|
|
29077
29086
|
init_path_manager();
|
|
29078
29087
|
init_fs();
|
|
29088
|
+
init_logger();
|
|
29079
29089
|
import fs7 from "node:fs/promises";
|
|
29080
29090
|
import path7 from "node:path";
|
|
29081
29091
|
import { Hono } from "hono";
|
|
@@ -29095,7 +29105,7 @@ async function readJsonFile(filePath) {
|
|
|
29095
29105
|
return errors.length > 0 ? null : result;
|
|
29096
29106
|
} catch (error) {
|
|
29097
29107
|
if (!isNotFoundError(error) && !(error instanceof SyntaxError)) {
|
|
29098
|
-
|
|
29108
|
+
logger_default.error(`JSON read error: ${error.message}`);
|
|
29099
29109
|
}
|
|
29100
29110
|
return null;
|
|
29101
29111
|
}
|
|
@@ -29108,7 +29118,7 @@ async function writeJsonFile(filePath, data) {
|
|
|
29108
29118
|
`, "utf-8");
|
|
29109
29119
|
return true;
|
|
29110
29120
|
} catch (error) {
|
|
29111
|
-
|
|
29121
|
+
logger_default.error(`JSON write error: ${error.message}`);
|
|
29112
29122
|
return false;
|
|
29113
29123
|
}
|
|
29114
29124
|
}
|
|
@@ -29198,7 +29208,7 @@ function createRoutes(projectId, _projectPath) {
|
|
|
29198
29208
|
return c.text(content, 200, { "Content-Type": "text/markdown" });
|
|
29199
29209
|
} catch (error) {
|
|
29200
29210
|
if (!isNotFoundError(error)) {
|
|
29201
|
-
|
|
29211
|
+
logger_default.error(`Context read error: ${error.message}`);
|
|
29202
29212
|
}
|
|
29203
29213
|
return c.text("", 200, { "Content-Type": "text/markdown" });
|
|
29204
29214
|
}
|
|
@@ -29704,7 +29714,7 @@ function createServer(config) {
|
|
|
29704
29714
|
);
|
|
29705
29715
|
}
|
|
29706
29716
|
if (config.enableLogging !== false) {
|
|
29707
|
-
app.use("*",
|
|
29717
|
+
app.use("*", logger2());
|
|
29708
29718
|
}
|
|
29709
29719
|
app.get("/health", (c) => c.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() }));
|
|
29710
29720
|
app.get(
|