prjct-cli 0.44.1 → 0.45.3
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 +114 -0
- package/bin/prjct.ts +131 -10
- package/core/__tests__/agentic/memory-system.test.ts +39 -26
- package/core/__tests__/agentic/plan-mode.test.ts +64 -46
- package/core/__tests__/agentic/prompt-builder.test.ts +14 -14
- package/core/__tests__/services/project-index.test.ts +353 -0
- package/core/__tests__/types/fs.test.ts +3 -3
- package/core/__tests__/utils/date-helper.test.ts +10 -10
- package/core/__tests__/utils/output.test.ts +9 -6
- package/core/__tests__/utils/project-commands.test.ts +5 -6
- package/core/agentic/agent-router.ts +9 -10
- package/core/agentic/chain-of-thought.ts +16 -4
- package/core/agentic/command-executor.ts +66 -40
- package/core/agentic/context-builder.ts +8 -5
- package/core/agentic/ground-truth.ts +15 -9
- package/core/agentic/index.ts +145 -152
- package/core/agentic/loop-detector.ts +40 -11
- package/core/agentic/memory-system.ts +98 -35
- package/core/agentic/orchestrator-executor.ts +135 -71
- package/core/agentic/plan-mode.ts +46 -16
- package/core/agentic/prompt-builder.ts +108 -42
- package/core/agentic/services.ts +10 -9
- package/core/agentic/skill-loader.ts +9 -15
- package/core/agentic/smart-context.ts +129 -79
- package/core/agentic/template-executor.ts +13 -12
- package/core/agentic/template-loader.ts +7 -4
- package/core/agentic/tool-registry.ts +16 -13
- package/core/agents/index.ts +1 -1
- package/core/agents/performance.ts +10 -27
- package/core/ai-tools/formatters.ts +8 -6
- package/core/ai-tools/generator.ts +4 -4
- package/core/ai-tools/index.ts +1 -1
- package/core/ai-tools/registry.ts +21 -11
- package/core/bus/bus.ts +23 -16
- package/core/bus/index.ts +2 -2
- package/core/cli/linear.ts +3 -5
- package/core/cli/start.ts +28 -25
- package/core/commands/analysis.ts +287 -29
- package/core/commands/analytics.ts +52 -44
- package/core/commands/base.ts +15 -13
- package/core/commands/cleanup.ts +6 -13
- package/core/commands/command-data.ts +49 -8
- package/core/commands/commands.ts +60 -23
- package/core/commands/context.ts +4 -4
- package/core/commands/design.ts +3 -10
- package/core/commands/index.ts +5 -8
- package/core/commands/maintenance.ts +7 -4
- package/core/commands/planning.ts +179 -56
- package/core/commands/register.ts +14 -9
- package/core/commands/registry.ts +15 -14
- package/core/commands/setup.ts +26 -14
- package/core/commands/shipping.ts +11 -16
- package/core/commands/snapshots.ts +16 -32
- package/core/commands/uninstall.ts +541 -0
- package/core/commands/workflow.ts +24 -28
- package/core/constants/index.ts +10 -22
- package/core/context/generator.ts +82 -33
- package/core/context-tools/files-tool.ts +583 -0
- package/core/context-tools/imports-tool.ts +403 -0
- package/core/context-tools/index.ts +433 -0
- package/core/context-tools/recent-tool.ts +307 -0
- package/core/context-tools/signatures-tool.ts +501 -0
- package/core/context-tools/summary-tool.ts +307 -0
- package/core/context-tools/token-counter.ts +284 -0
- package/core/context-tools/types.ts +253 -0
- package/core/domain/agent-generator.ts +7 -5
- package/core/domain/agent-loader.ts +2 -2
- package/core/domain/analyzer.ts +19 -16
- package/core/domain/architecture-generator.ts +6 -3
- package/core/domain/context-estimator.ts +3 -4
- package/core/domain/snapshot-manager.ts +25 -22
- package/core/domain/task-stack.ts +24 -14
- package/core/errors.ts +1 -1
- package/core/events/events.ts +2 -4
- package/core/events/index.ts +1 -2
- package/core/index.ts +28 -12
- package/core/infrastructure/agent-detector.ts +3 -3
- package/core/infrastructure/ai-provider.ts +23 -20
- package/core/infrastructure/author-detector.ts +16 -10
- package/core/infrastructure/capability-installer.ts +2 -2
- package/core/infrastructure/claude-agent.ts +6 -6
- package/core/infrastructure/command-installer.ts +22 -17
- package/core/infrastructure/config-manager.ts +18 -14
- package/core/infrastructure/editors-config.ts +8 -4
- package/core/infrastructure/path-manager.ts +8 -6
- package/core/infrastructure/permission-manager.ts +20 -17
- package/core/infrastructure/setup.ts +42 -38
- package/core/infrastructure/update-checker.ts +5 -5
- package/core/integrations/issue-tracker/enricher.ts +8 -19
- package/core/integrations/issue-tracker/index.ts +2 -2
- package/core/integrations/issue-tracker/manager.ts +15 -15
- package/core/integrations/issue-tracker/types.ts +5 -22
- package/core/integrations/jira/client.ts +67 -59
- package/core/integrations/jira/index.ts +11 -14
- package/core/integrations/jira/mcp-adapter.ts +5 -10
- package/core/integrations/jira/service.ts +10 -10
- package/core/integrations/linear/client.ts +27 -18
- package/core/integrations/linear/index.ts +9 -12
- package/core/integrations/linear/service.ts +11 -11
- package/core/integrations/linear/sync.ts +8 -8
- package/core/outcomes/analyzer.ts +5 -18
- package/core/outcomes/index.ts +2 -2
- package/core/outcomes/recorder.ts +3 -3
- package/core/plugin/builtin/webhook.ts +19 -15
- package/core/plugin/hooks.ts +29 -21
- package/core/plugin/index.ts +7 -7
- package/core/plugin/loader.ts +19 -19
- package/core/plugin/registry.ts +12 -23
- package/core/schemas/agents.ts +1 -1
- package/core/schemas/analysis.ts +1 -1
- package/core/schemas/enriched-task.ts +62 -49
- package/core/schemas/ideas.ts +13 -13
- package/core/schemas/index.ts +17 -27
- package/core/schemas/issues.ts +40 -25
- package/core/schemas/metrics.ts +143 -0
- package/core/schemas/outcomes.ts +70 -62
- package/core/schemas/permissions.ts +15 -12
- package/core/schemas/prd.ts +27 -14
- package/core/schemas/project.ts +3 -3
- package/core/schemas/roadmap.ts +47 -34
- package/core/schemas/schemas.ts +3 -4
- package/core/schemas/shipped.ts +3 -3
- package/core/schemas/state.ts +43 -29
- package/core/server/index.ts +5 -6
- package/core/server/routes-extended.ts +68 -72
- package/core/server/routes.ts +3 -3
- package/core/server/server.ts +31 -26
- package/core/services/agent-generator.ts +237 -0
- package/core/services/agent-service.ts +2 -2
- package/core/services/breakdown-service.ts +2 -4
- package/core/services/context-generator.ts +299 -0
- package/core/services/context-selector.ts +420 -0
- package/core/services/doctor-service.ts +426 -0
- package/core/services/file-categorizer.ts +448 -0
- package/core/services/file-scorer.ts +270 -0
- package/core/services/git-analyzer.ts +267 -0
- package/core/services/index.ts +27 -10
- package/core/services/memory-service.ts +3 -4
- package/core/services/project-index.ts +911 -0
- package/core/services/project-service.ts +4 -4
- package/core/services/skill-installer.ts +14 -17
- package/core/services/skill-lock.ts +3 -3
- package/core/services/skill-service.ts +12 -6
- package/core/services/stack-detector.ts +245 -0
- package/core/services/sync-service.ts +170 -329
- package/core/services/watch-service.ts +294 -0
- package/core/session/compaction.ts +23 -31
- package/core/session/index.ts +11 -5
- package/core/session/log-migration.ts +3 -3
- package/core/session/metrics.ts +19 -14
- package/core/session/session-log-manager.ts +12 -17
- package/core/session/task-session-manager.ts +25 -25
- package/core/session/utils.ts +1 -1
- package/core/storage/ideas-storage.ts +41 -57
- package/core/storage/index-storage.ts +514 -0
- package/core/storage/index.ts +41 -13
- package/core/storage/metrics-storage.ts +320 -0
- package/core/storage/queue-storage.ts +35 -45
- package/core/storage/shipped-storage.ts +17 -20
- package/core/storage/state-storage.ts +50 -30
- package/core/storage/storage-manager.ts +6 -6
- package/core/storage/storage.ts +18 -15
- package/core/sync/auth-config.ts +3 -3
- package/core/sync/index.ts +13 -19
- package/core/sync/oauth-handler.ts +3 -3
- package/core/sync/sync-client.ts +4 -9
- package/core/sync/sync-manager.ts +12 -14
- package/core/types/commands.ts +42 -7
- package/core/types/index.ts +284 -302
- package/core/types/integrations.ts +3 -3
- package/core/types/storage.ts +49 -0
- package/core/types/utils.ts +3 -3
- package/core/utils/agent-stream.ts +3 -1
- package/core/utils/animations.ts +14 -11
- package/core/utils/branding.ts +7 -7
- package/core/utils/cache.ts +1 -3
- package/core/utils/collection-filters.ts +3 -15
- package/core/utils/date-helper.ts +2 -7
- package/core/utils/file-helper.ts +13 -8
- package/core/utils/jsonl-helper.ts +13 -10
- package/core/utils/keychain.ts +4 -8
- package/core/utils/logger.ts +1 -1
- package/core/utils/next-steps.ts +3 -3
- package/core/utils/output.ts +58 -11
- package/core/utils/project-commands.ts +6 -6
- package/core/utils/project-credentials.ts +5 -12
- package/core/utils/runtime.ts +2 -2
- package/core/utils/session-helper.ts +3 -4
- package/core/utils/version.ts +3 -3
- package/core/wizard/index.ts +13 -0
- package/core/wizard/onboarding.ts +633 -0
- package/core/workflow/state-machine.ts +7 -7
- package/dist/bin/prjct.mjs +18907 -13189
- package/dist/core/infrastructure/command-installer.js +96 -111
- package/dist/core/infrastructure/editors-config.js +6 -6
- package/dist/core/infrastructure/setup.js +256 -257
- package/dist/core/utils/version.js +9 -9
- package/package.json +11 -12
- package/scripts/build.js +3 -3
- package/scripts/postinstall.js +2 -2
- package/templates/mcp-config.json +6 -1
- package/templates/permissions/permissive.jsonc +1 -1
- package/templates/permissions/strict.jsonc +5 -9
- 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
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Tools Types
|
|
3
|
+
*
|
|
4
|
+
* Shared interfaces for all context filtering tools.
|
|
5
|
+
* These tools are designed for AI agents to efficiently explore
|
|
6
|
+
* codebases WITHOUT consuming tokens for filtering.
|
|
7
|
+
*
|
|
8
|
+
* @module context-tools/types
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Token Measurement Types
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cost savings breakdown by model
|
|
18
|
+
*/
|
|
19
|
+
export interface CostBreakdown {
|
|
20
|
+
model: string
|
|
21
|
+
inputSaved: number // $ saved on input tokens
|
|
22
|
+
outputPotential: number // $ potential savings on output (estimated)
|
|
23
|
+
total: number // Combined savings
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Token measurement result
|
|
28
|
+
*/
|
|
29
|
+
export interface TokenMetrics {
|
|
30
|
+
tokens: {
|
|
31
|
+
original: number
|
|
32
|
+
filtered: number
|
|
33
|
+
saved: number
|
|
34
|
+
}
|
|
35
|
+
compression: number // 0-1 (e.g., 0.90 = 90% reduction)
|
|
36
|
+
cost: {
|
|
37
|
+
saved: number // $ saved (using default model)
|
|
38
|
+
formatted: string // Human-readable (e.g., "$0.02")
|
|
39
|
+
byModel: CostBreakdown[] // Breakdown by popular models
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// Files Tool Types
|
|
45
|
+
// =============================================================================
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Relevance score reasons
|
|
49
|
+
*/
|
|
50
|
+
export type ScoreReason =
|
|
51
|
+
| `keyword:${string}` // Matched keyword in path
|
|
52
|
+
| `domain:${string}` // Matched domain pattern
|
|
53
|
+
| `recent:${string}` // Recently modified (e.g., "3d" = 3 days)
|
|
54
|
+
| `import:${number}` // Import distance from entry point
|
|
55
|
+
| `extension:${string}` // File extension match
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* File with relevance score
|
|
59
|
+
*/
|
|
60
|
+
export interface ScoredFile {
|
|
61
|
+
path: string
|
|
62
|
+
score: number // 0-1
|
|
63
|
+
reasons: ScoreReason[]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Files tool output
|
|
68
|
+
*/
|
|
69
|
+
export interface FilesToolOutput {
|
|
70
|
+
files: ScoredFile[]
|
|
71
|
+
metrics: {
|
|
72
|
+
filesScanned: number
|
|
73
|
+
filesReturned: number
|
|
74
|
+
scanDuration: number // ms
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Signatures Tool Types
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Code signature types
|
|
84
|
+
*/
|
|
85
|
+
export type SignatureType =
|
|
86
|
+
| 'function'
|
|
87
|
+
| 'method'
|
|
88
|
+
| 'class'
|
|
89
|
+
| 'interface'
|
|
90
|
+
| 'type'
|
|
91
|
+
| 'enum'
|
|
92
|
+
| 'const'
|
|
93
|
+
| 'variable'
|
|
94
|
+
| 'export'
|
|
95
|
+
| 'import'
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Extracted code signature
|
|
99
|
+
*/
|
|
100
|
+
export interface CodeSignature {
|
|
101
|
+
type: SignatureType
|
|
102
|
+
name: string
|
|
103
|
+
signature: string // Full signature string (e.g., "(token: string) => Promise<User>")
|
|
104
|
+
exported: boolean
|
|
105
|
+
line: number
|
|
106
|
+
docstring?: string
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Signatures tool output
|
|
111
|
+
*/
|
|
112
|
+
export interface SignaturesToolOutput {
|
|
113
|
+
file: string
|
|
114
|
+
language: string
|
|
115
|
+
signatures: CodeSignature[]
|
|
116
|
+
fallback: boolean // True if full file was returned (no grammar)
|
|
117
|
+
fallbackReason?: string
|
|
118
|
+
metrics: TokenMetrics
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// =============================================================================
|
|
122
|
+
// Imports Tool Types
|
|
123
|
+
// =============================================================================
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Import relationship
|
|
127
|
+
*/
|
|
128
|
+
export interface ImportRelation {
|
|
129
|
+
source: string // Import path (e.g., "./types", "lodash")
|
|
130
|
+
resolved: string | null // Resolved file path (null for external)
|
|
131
|
+
isExternal: boolean
|
|
132
|
+
importedNames?: string[] // Named imports
|
|
133
|
+
isDefault?: boolean
|
|
134
|
+
isNamespace?: boolean // import * as X
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* File that imports the target
|
|
139
|
+
*/
|
|
140
|
+
export interface ImportedBy {
|
|
141
|
+
file: string
|
|
142
|
+
importedNames?: string[]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Dependency tree node
|
|
147
|
+
*/
|
|
148
|
+
export interface DependencyNode {
|
|
149
|
+
file: string
|
|
150
|
+
imports: DependencyNode[]
|
|
151
|
+
depth: number
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Imports tool output
|
|
156
|
+
*/
|
|
157
|
+
export interface ImportsToolOutput {
|
|
158
|
+
file: string
|
|
159
|
+
imports: ImportRelation[]
|
|
160
|
+
importedBy: ImportedBy[]
|
|
161
|
+
dependencyTree?: DependencyNode
|
|
162
|
+
metrics: {
|
|
163
|
+
totalImports: number
|
|
164
|
+
externalImports: number
|
|
165
|
+
internalImports: number
|
|
166
|
+
importedByCount: number
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// =============================================================================
|
|
171
|
+
// Recent Tool Types
|
|
172
|
+
// =============================================================================
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Hot file from git analysis
|
|
176
|
+
*/
|
|
177
|
+
export interface HotFile {
|
|
178
|
+
path: string
|
|
179
|
+
changes: number // Number of commits touching this file
|
|
180
|
+
heatScore: number // 0-1 normalized score
|
|
181
|
+
lastChanged: string // Human-readable (e.g., "2h ago", "3d ago")
|
|
182
|
+
lastChangedAt: string // ISO timestamp
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Recent tool output
|
|
187
|
+
*/
|
|
188
|
+
export interface RecentToolOutput {
|
|
189
|
+
hotFiles: HotFile[]
|
|
190
|
+
branchOnlyFiles: string[] // Files only changed in current branch
|
|
191
|
+
metrics: {
|
|
192
|
+
commitsAnalyzed: number
|
|
193
|
+
totalFilesChanged: number
|
|
194
|
+
filesReturned: number
|
|
195
|
+
analysisWindow: string // e.g., "30 commits", "main..HEAD"
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// =============================================================================
|
|
200
|
+
// Summary Tool Types
|
|
201
|
+
// =============================================================================
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Public API entry
|
|
205
|
+
*/
|
|
206
|
+
export interface PublicAPIEntry {
|
|
207
|
+
name: string
|
|
208
|
+
type: SignatureType
|
|
209
|
+
signature: string
|
|
210
|
+
description?: string // From JSDoc/docstring
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Summary tool output
|
|
215
|
+
*/
|
|
216
|
+
export interface SummaryToolOutput {
|
|
217
|
+
file: string
|
|
218
|
+
purpose: string // Short description of file purpose
|
|
219
|
+
publicAPI: PublicAPIEntry[]
|
|
220
|
+
dependencies: string[] // Key dependencies
|
|
221
|
+
metrics: TokenMetrics
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// =============================================================================
|
|
225
|
+
// Context Tool Usage Tracking
|
|
226
|
+
// =============================================================================
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Tool usage record for metrics
|
|
230
|
+
*/
|
|
231
|
+
export interface ContextToolUsage {
|
|
232
|
+
tool: 'files' | 'signatures' | 'imports' | 'recent' | 'summary'
|
|
233
|
+
timestamp: string
|
|
234
|
+
inputArgs: string
|
|
235
|
+
tokensSaved: number
|
|
236
|
+
compressionRate: number
|
|
237
|
+
duration: number // ms
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// =============================================================================
|
|
241
|
+
// Main Tool Result Type
|
|
242
|
+
// =============================================================================
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Union type for all tool outputs
|
|
246
|
+
*/
|
|
247
|
+
export type ContextToolOutput =
|
|
248
|
+
| { tool: 'files'; result: FilesToolOutput }
|
|
249
|
+
| { tool: 'signatures'; result: SignaturesToolOutput }
|
|
250
|
+
| { tool: 'imports'; result: ImportsToolOutput }
|
|
251
|
+
| { tool: 'recent'; result: RecentToolOutput }
|
|
252
|
+
| { tool: 'summary'; result: SummaryToolOutput }
|
|
253
|
+
| { tool: 'error'; result: { error: string; code: string } }
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @version 1.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import fs from 'fs/promises'
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import AgentLoader from './agent-loader'
|
|
7
|
+
import fs from 'node:fs/promises'
|
|
8
|
+
import os from 'node:os'
|
|
9
|
+
import path from 'node:path'
|
|
11
10
|
import log from '../utils/logger'
|
|
11
|
+
import AgentLoader from './agent-loader'
|
|
12
12
|
|
|
13
13
|
interface AgentConfig {
|
|
14
14
|
role?: string
|
|
@@ -152,7 +152,9 @@ ${config.contextFilter || 'Only relevant files'}
|
|
|
152
152
|
async listAgents(): Promise<string[]> {
|
|
153
153
|
try {
|
|
154
154
|
const files = await fs.readdir(this.outputDir)
|
|
155
|
-
return files
|
|
155
|
+
return files
|
|
156
|
+
.filter((f) => f.endsWith('.md') && !f.startsWith('.'))
|
|
157
|
+
.map((f) => f.replace('.md', ''))
|
|
156
158
|
} catch (_error) {
|
|
157
159
|
return []
|
|
158
160
|
}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* @version 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import fs from 'fs/promises'
|
|
10
|
-
import path from 'path'
|
|
9
|
+
import fs from 'node:fs/promises'
|
|
10
|
+
import path from 'node:path'
|
|
11
11
|
import pathManager from '../infrastructure/path-manager'
|
|
12
12
|
import { isNotFoundError } from '../types/fs'
|
|
13
13
|
|
package/core/domain/analyzer.ts
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
* @version 0.6.0 - Fully agentic refactor
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
13
|
+
import { exec as execCallback } from 'node:child_process'
|
|
14
|
+
import fs from 'node:fs/promises'
|
|
15
|
+
import path from 'node:path'
|
|
16
|
+
import { promisify } from 'node:util'
|
|
17
17
|
import { isNotFoundError } from '../types/fs'
|
|
18
18
|
|
|
19
19
|
const exec = promisify(execCallback)
|
|
@@ -209,11 +209,11 @@ class CodebaseAnalyzer {
|
|
|
209
209
|
.forEach((line) => {
|
|
210
210
|
const match = line.trim().match(/^\s*(\d+)\s+(\.\w+)$/)
|
|
211
211
|
if (match) {
|
|
212
|
-
extensions[match[2]] = parseInt(match[1])
|
|
212
|
+
extensions[match[2]] = parseInt(match[1], 10)
|
|
213
213
|
}
|
|
214
214
|
})
|
|
215
215
|
return extensions
|
|
216
|
-
} catch (
|
|
216
|
+
} catch (_error) {
|
|
217
217
|
// exec errors (find command not available, etc.) - return empty
|
|
218
218
|
return {}
|
|
219
219
|
}
|
|
@@ -278,7 +278,7 @@ class CodebaseAnalyzer {
|
|
|
278
278
|
cwd: this.projectPath!,
|
|
279
279
|
})
|
|
280
280
|
return stdout
|
|
281
|
-
} catch (
|
|
281
|
+
} catch (_error) {
|
|
282
282
|
// Git errors (not a repo, git not installed) - return empty
|
|
283
283
|
return ''
|
|
284
284
|
}
|
|
@@ -297,16 +297,19 @@ class CodebaseAnalyzer {
|
|
|
297
297
|
cwd: this.projectPath!,
|
|
298
298
|
})
|
|
299
299
|
|
|
300
|
-
const { stdout: firstCommit } = await exec(
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
const { stdout: firstCommit } = await exec(
|
|
301
|
+
'git log --reverse --pretty=format:"%ar" | head -1',
|
|
302
|
+
{
|
|
303
|
+
cwd: this.projectPath!,
|
|
304
|
+
}
|
|
305
|
+
)
|
|
303
306
|
|
|
304
307
|
return {
|
|
305
|
-
totalCommits: parseInt(totalCommits.trim()) || 0,
|
|
306
|
-
contributors: parseInt(contributors.trim()) || 0,
|
|
308
|
+
totalCommits: parseInt(totalCommits.trim(), 10) || 0,
|
|
309
|
+
contributors: parseInt(contributors.trim(), 10) || 0,
|
|
307
310
|
age: firstCommit.trim() || 'unknown',
|
|
308
311
|
}
|
|
309
|
-
} catch (
|
|
312
|
+
} catch (_error) {
|
|
310
313
|
// Git errors (not a repo, git not installed) - return defaults
|
|
311
314
|
return {
|
|
312
315
|
totalCommits: 0,
|
|
@@ -325,8 +328,8 @@ class CodebaseAnalyzer {
|
|
|
325
328
|
'find . -type f ! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/dist/*" | wc -l',
|
|
326
329
|
{ cwd: this.projectPath! }
|
|
327
330
|
)
|
|
328
|
-
return parseInt(stdout.trim()) || 0
|
|
329
|
-
} catch (
|
|
331
|
+
return parseInt(stdout.trim(), 10) || 0
|
|
332
|
+
} catch (_error) {
|
|
330
333
|
// exec errors (find command not available, etc.) - return 0
|
|
331
334
|
return 0
|
|
332
335
|
}
|
|
@@ -372,7 +375,7 @@ class CodebaseAnalyzer {
|
|
|
372
375
|
{ cwd: this.projectPath! }
|
|
373
376
|
)
|
|
374
377
|
return stdout.trim().split('\n').filter(Boolean)
|
|
375
|
-
} catch (
|
|
378
|
+
} catch (_error) {
|
|
376
379
|
// exec errors (find command not available, etc.) - return empty
|
|
377
380
|
return []
|
|
378
381
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* This file only provides structure - real content from Claude
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import
|
|
7
|
+
import fs from 'node:fs/promises'
|
|
8
|
+
import path from 'node:path'
|
|
9
9
|
|
|
10
10
|
interface ArchitectureContext {
|
|
11
11
|
[key: string]: unknown
|
|
@@ -40,7 +40,10 @@ class ArchitectureGenerator {
|
|
|
40
40
|
* Generate architecture skeleton
|
|
41
41
|
* AGENTIC: Claude fills in content using templates
|
|
42
42
|
*/
|
|
43
|
-
async generateArchitecture(
|
|
43
|
+
async generateArchitecture(
|
|
44
|
+
idea: string,
|
|
45
|
+
_context: ArchitectureContext = {}
|
|
46
|
+
): Promise<Architecture> {
|
|
44
47
|
// Return skeleton - Claude generates actual content via templates
|
|
45
48
|
return {
|
|
46
49
|
id: `arch-${Date.now()}`,
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
* @version 1.0.0
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import path from 'path'
|
|
11
10
|
import { glob } from 'glob'
|
|
12
11
|
import log from '../utils/logger'
|
|
13
12
|
|
|
@@ -79,7 +78,7 @@ class ContextEstimator {
|
|
|
79
78
|
* 100% AGENTIC: Uses REAL project data, not hardcoded patterns.
|
|
80
79
|
* No domain-specific assumptions or language→extension mapping.
|
|
81
80
|
*/
|
|
82
|
-
getPatternsForDomain(
|
|
81
|
+
getPatternsForDomain(_domain: string, projectData: ProjectTech): FilePatterns {
|
|
83
82
|
const patterns: FilePatterns = {
|
|
84
83
|
include: [],
|
|
85
84
|
extensions: [],
|
|
@@ -87,7 +86,7 @@ class ContextEstimator {
|
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
// Use REAL extensions from project (if provided in projectData)
|
|
90
|
-
if (projectData
|
|
89
|
+
if (projectData?.extensions) {
|
|
91
90
|
// projectData.extensions is {'.js': 45, '.ts': 23, ...}
|
|
92
91
|
patterns.extensions = Object.keys(projectData.extensions)
|
|
93
92
|
.filter((ext) => ext.startsWith('.'))
|
|
@@ -95,7 +94,7 @@ class ContextEstimator {
|
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
// Use REAL directories from project (if provided in projectData)
|
|
98
|
-
if (projectData
|
|
97
|
+
if (projectData?.directories) {
|
|
99
98
|
patterns.include = projectData.directories.filter((dir) => !patterns.exclude.includes(dir))
|
|
100
99
|
}
|
|
101
100
|
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
* @version 1.0.0
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import { promisify } from 'util'
|
|
16
|
-
import pathManager from '../infrastructure/path-manager'
|
|
17
|
-
import configManager from '../infrastructure/config-manager'
|
|
12
|
+
import { exec } from 'node:child_process'
|
|
13
|
+
import fs from 'node:fs/promises'
|
|
14
|
+
import path from 'node:path'
|
|
15
|
+
import { promisify } from 'node:util'
|
|
18
16
|
import { emit } from '../bus'
|
|
17
|
+
import configManager from '../infrastructure/config-manager'
|
|
18
|
+
import pathManager from '../infrastructure/path-manager'
|
|
19
19
|
import { isNotFoundError } from '../types/fs'
|
|
20
20
|
|
|
21
21
|
const execAsync = promisify(exec)
|
|
@@ -100,7 +100,9 @@ class SnapshotManager {
|
|
|
100
100
|
await execAsync(`git config user.name "prjct-snapshots"`, { cwd: this.snapshotDir! })
|
|
101
101
|
|
|
102
102
|
// Create initial empty commit
|
|
103
|
-
await execAsync(`git commit --allow-empty -m "init: snapshot system"`, {
|
|
103
|
+
await execAsync(`git commit --allow-empty -m "init: snapshot system"`, {
|
|
104
|
+
cwd: this.snapshotDir!,
|
|
105
|
+
})
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
/**
|
|
@@ -236,9 +238,12 @@ class SnapshotManager {
|
|
|
236
238
|
if (!this.initialized) await this.initialize()
|
|
237
239
|
|
|
238
240
|
// Get files changed in that commit
|
|
239
|
-
const { stdout: filesOutput } = await execAsync(
|
|
240
|
-
|
|
241
|
-
|
|
241
|
+
const { stdout: filesOutput } = await execAsync(
|
|
242
|
+
`git diff-tree --no-commit-id --name-only -r ${hash}`,
|
|
243
|
+
{
|
|
244
|
+
cwd: this.snapshotDir!,
|
|
245
|
+
}
|
|
246
|
+
)
|
|
242
247
|
|
|
243
248
|
const files = filesOutput.split('\n').filter(Boolean)
|
|
244
249
|
|
|
@@ -337,11 +342,10 @@ class SnapshotManager {
|
|
|
337
342
|
*/
|
|
338
343
|
async logSnapshot(snapshot: SnapshotInfo): Promise<void> {
|
|
339
344
|
const manifestPath = path.join(this.snapshotDir!, 'manifest.jsonl')
|
|
340
|
-
const entry =
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}) + '\n'
|
|
345
|
+
const entry = `${JSON.stringify({
|
|
346
|
+
type: 'snapshot',
|
|
347
|
+
...snapshot,
|
|
348
|
+
})}\n`
|
|
345
349
|
|
|
346
350
|
await fs.appendFile(manifestPath, entry)
|
|
347
351
|
}
|
|
@@ -351,13 +355,12 @@ class SnapshotManager {
|
|
|
351
355
|
*/
|
|
352
356
|
async logRestore(hash: string, files: string[]): Promise<void> {
|
|
353
357
|
const manifestPath = path.join(this.snapshotDir!, 'manifest.jsonl')
|
|
354
|
-
const entry =
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}) + '\n'
|
|
358
|
+
const entry = `${JSON.stringify({
|
|
359
|
+
type: 'restore',
|
|
360
|
+
hash,
|
|
361
|
+
files,
|
|
362
|
+
timestamp: new Date().toISOString(),
|
|
363
|
+
})}\n`
|
|
361
364
|
|
|
362
365
|
await fs.appendFile(manifestPath, entry)
|
|
363
366
|
}
|
|
@@ -3,23 +3,22 @@
|
|
|
3
3
|
* Manages task breakdown and hierarchical task tracking.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import fs from 'fs/promises'
|
|
8
|
-
import
|
|
9
|
-
import { promisify } from 'util'
|
|
10
|
-
import log from '../utils/logger'
|
|
11
|
-
import { isNotFoundError } from '../types/fs'
|
|
6
|
+
import { exec } from 'node:child_process'
|
|
7
|
+
import fs from 'node:fs/promises'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
import { promisify } from 'node:util'
|
|
12
10
|
import type {
|
|
13
|
-
TaskStackEntry,
|
|
14
11
|
ParsedNowFile,
|
|
12
|
+
TaskStackEntry,
|
|
15
13
|
TaskStackMigrationResult,
|
|
16
|
-
TaskSwitchResult,
|
|
17
14
|
TaskStackSummary,
|
|
15
|
+
TaskSwitchResult,
|
|
18
16
|
} from '../types'
|
|
17
|
+
import { isNotFoundError } from '../types/fs'
|
|
18
|
+
import log from '../utils/logger'
|
|
19
19
|
|
|
20
20
|
const execAsync = promisify(exec)
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
// =============================================================================
|
|
24
23
|
// Parser
|
|
25
24
|
// =============================================================================
|
|
@@ -129,7 +128,7 @@ export async function ensureStackFile(stackPath: string): Promise<void> {
|
|
|
129
128
|
*/
|
|
130
129
|
export async function appendToStack(stackPath: string, entry: TaskStackEntry): Promise<void> {
|
|
131
130
|
await ensureStackFile(stackPath)
|
|
132
|
-
const line = JSON.stringify(entry)
|
|
131
|
+
const line = `${JSON.stringify(entry)}\n`
|
|
133
132
|
await fs.appendFile(stackPath, line)
|
|
134
133
|
}
|
|
135
134
|
|
|
@@ -162,14 +161,18 @@ export async function readStack(stackPath: string): Promise<TaskStackEntry[]> {
|
|
|
162
161
|
* Write full stack to file
|
|
163
162
|
*/
|
|
164
163
|
export async function writeStack(stackPath: string, stack: TaskStackEntry[]): Promise<void> {
|
|
165
|
-
const content = stack.map((task) => JSON.stringify(task)).join('\n')
|
|
164
|
+
const content = `${stack.map((task) => JSON.stringify(task)).join('\n')}\n`
|
|
166
165
|
await fs.writeFile(stackPath, content)
|
|
167
166
|
}
|
|
168
167
|
|
|
169
168
|
/**
|
|
170
169
|
* Generate now.md content for a task
|
|
171
170
|
*/
|
|
172
|
-
export function generateNowContent(
|
|
171
|
+
export function generateNowContent(
|
|
172
|
+
task: TaskStackEntry | null,
|
|
173
|
+
customContent: string | null,
|
|
174
|
+
formatDurationFn: (ms: number) => string
|
|
175
|
+
): string {
|
|
173
176
|
if (customContent !== undefined && customContent !== null) {
|
|
174
177
|
return customContent
|
|
175
178
|
}
|
|
@@ -340,7 +343,11 @@ export class TaskStack {
|
|
|
340
343
|
/**
|
|
341
344
|
* Start a new task
|
|
342
345
|
*/
|
|
343
|
-
async startTask(
|
|
346
|
+
async startTask(
|
|
347
|
+
description: string,
|
|
348
|
+
agent: string = 'general',
|
|
349
|
+
complexity: string = 'moderate'
|
|
350
|
+
): Promise<TaskStackEntry> {
|
|
344
351
|
// Check if there's already an active task
|
|
345
352
|
const active = await this.getActiveTask()
|
|
346
353
|
if (active) {
|
|
@@ -524,7 +531,10 @@ export class TaskStack {
|
|
|
524
531
|
/**
|
|
525
532
|
* Update now.md to reflect current state
|
|
526
533
|
*/
|
|
527
|
-
async updateNowFile(
|
|
534
|
+
async updateNowFile(
|
|
535
|
+
task: TaskStackEntry | null,
|
|
536
|
+
customContent: string | null = null
|
|
537
|
+
): Promise<void> {
|
|
528
538
|
await updateNowFile(this.nowPath, task, customContent, formatDuration)
|
|
529
539
|
}
|
|
530
540
|
|
package/core/errors.ts
CHANGED
package/core/events/events.ts
CHANGED
|
@@ -6,10 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import pathManager from '../infrastructure/path-manager'
|
|
9
|
-
import
|
|
9
|
+
import type { SyncEvent, SyncEventType } from '../types'
|
|
10
10
|
import { getTimestamp } from '../utils/date-helper'
|
|
11
|
-
|
|
12
|
-
import type { SyncEventType, SyncEvent } from '../types'
|
|
11
|
+
import * as fileHelper from '../utils/file-helper'
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
14
|
* Infer event type from path and action
|
|
@@ -84,4 +83,3 @@ class EventBus {
|
|
|
84
83
|
|
|
85
84
|
export const eventBus = new EventBus()
|
|
86
85
|
export default eventBus
|
|
87
|
-
|
package/core/events/index.ts
CHANGED