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.
Files changed (207) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/bin/prjct.ts +131 -10
  3. package/core/__tests__/agentic/memory-system.test.ts +39 -26
  4. package/core/__tests__/agentic/plan-mode.test.ts +64 -46
  5. package/core/__tests__/agentic/prompt-builder.test.ts +14 -14
  6. package/core/__tests__/services/project-index.test.ts +353 -0
  7. package/core/__tests__/types/fs.test.ts +3 -3
  8. package/core/__tests__/utils/date-helper.test.ts +10 -10
  9. package/core/__tests__/utils/output.test.ts +9 -6
  10. package/core/__tests__/utils/project-commands.test.ts +5 -6
  11. package/core/agentic/agent-router.ts +9 -10
  12. package/core/agentic/chain-of-thought.ts +16 -4
  13. package/core/agentic/command-executor.ts +66 -40
  14. package/core/agentic/context-builder.ts +8 -5
  15. package/core/agentic/ground-truth.ts +15 -9
  16. package/core/agentic/index.ts +145 -152
  17. package/core/agentic/loop-detector.ts +40 -11
  18. package/core/agentic/memory-system.ts +98 -35
  19. package/core/agentic/orchestrator-executor.ts +135 -71
  20. package/core/agentic/plan-mode.ts +46 -16
  21. package/core/agentic/prompt-builder.ts +108 -42
  22. package/core/agentic/services.ts +10 -9
  23. package/core/agentic/skill-loader.ts +9 -15
  24. package/core/agentic/smart-context.ts +129 -79
  25. package/core/agentic/template-executor.ts +13 -12
  26. package/core/agentic/template-loader.ts +7 -4
  27. package/core/agentic/tool-registry.ts +16 -13
  28. package/core/agents/index.ts +1 -1
  29. package/core/agents/performance.ts +10 -27
  30. package/core/ai-tools/formatters.ts +8 -6
  31. package/core/ai-tools/generator.ts +4 -4
  32. package/core/ai-tools/index.ts +1 -1
  33. package/core/ai-tools/registry.ts +21 -11
  34. package/core/bus/bus.ts +23 -16
  35. package/core/bus/index.ts +2 -2
  36. package/core/cli/linear.ts +3 -5
  37. package/core/cli/start.ts +28 -25
  38. package/core/commands/analysis.ts +287 -29
  39. package/core/commands/analytics.ts +52 -44
  40. package/core/commands/base.ts +15 -13
  41. package/core/commands/cleanup.ts +6 -13
  42. package/core/commands/command-data.ts +49 -8
  43. package/core/commands/commands.ts +60 -23
  44. package/core/commands/context.ts +4 -4
  45. package/core/commands/design.ts +3 -10
  46. package/core/commands/index.ts +5 -8
  47. package/core/commands/maintenance.ts +7 -4
  48. package/core/commands/planning.ts +179 -56
  49. package/core/commands/register.ts +14 -9
  50. package/core/commands/registry.ts +15 -14
  51. package/core/commands/setup.ts +26 -14
  52. package/core/commands/shipping.ts +11 -16
  53. package/core/commands/snapshots.ts +16 -32
  54. package/core/commands/uninstall.ts +541 -0
  55. package/core/commands/workflow.ts +24 -28
  56. package/core/constants/index.ts +10 -22
  57. package/core/context/generator.ts +82 -33
  58. package/core/context-tools/files-tool.ts +583 -0
  59. package/core/context-tools/imports-tool.ts +403 -0
  60. package/core/context-tools/index.ts +433 -0
  61. package/core/context-tools/recent-tool.ts +307 -0
  62. package/core/context-tools/signatures-tool.ts +501 -0
  63. package/core/context-tools/summary-tool.ts +307 -0
  64. package/core/context-tools/token-counter.ts +284 -0
  65. package/core/context-tools/types.ts +253 -0
  66. package/core/domain/agent-generator.ts +7 -5
  67. package/core/domain/agent-loader.ts +2 -2
  68. package/core/domain/analyzer.ts +19 -16
  69. package/core/domain/architecture-generator.ts +6 -3
  70. package/core/domain/context-estimator.ts +3 -4
  71. package/core/domain/snapshot-manager.ts +25 -22
  72. package/core/domain/task-stack.ts +24 -14
  73. package/core/errors.ts +1 -1
  74. package/core/events/events.ts +2 -4
  75. package/core/events/index.ts +1 -2
  76. package/core/index.ts +28 -12
  77. package/core/infrastructure/agent-detector.ts +3 -3
  78. package/core/infrastructure/ai-provider.ts +23 -20
  79. package/core/infrastructure/author-detector.ts +16 -10
  80. package/core/infrastructure/capability-installer.ts +2 -2
  81. package/core/infrastructure/claude-agent.ts +6 -6
  82. package/core/infrastructure/command-installer.ts +22 -17
  83. package/core/infrastructure/config-manager.ts +18 -14
  84. package/core/infrastructure/editors-config.ts +8 -4
  85. package/core/infrastructure/path-manager.ts +8 -6
  86. package/core/infrastructure/permission-manager.ts +20 -17
  87. package/core/infrastructure/setup.ts +42 -38
  88. package/core/infrastructure/update-checker.ts +5 -5
  89. package/core/integrations/issue-tracker/enricher.ts +8 -19
  90. package/core/integrations/issue-tracker/index.ts +2 -2
  91. package/core/integrations/issue-tracker/manager.ts +15 -15
  92. package/core/integrations/issue-tracker/types.ts +5 -22
  93. package/core/integrations/jira/client.ts +67 -59
  94. package/core/integrations/jira/index.ts +11 -14
  95. package/core/integrations/jira/mcp-adapter.ts +5 -10
  96. package/core/integrations/jira/service.ts +10 -10
  97. package/core/integrations/linear/client.ts +27 -18
  98. package/core/integrations/linear/index.ts +9 -12
  99. package/core/integrations/linear/service.ts +11 -11
  100. package/core/integrations/linear/sync.ts +8 -8
  101. package/core/outcomes/analyzer.ts +5 -18
  102. package/core/outcomes/index.ts +2 -2
  103. package/core/outcomes/recorder.ts +3 -3
  104. package/core/plugin/builtin/webhook.ts +19 -15
  105. package/core/plugin/hooks.ts +29 -21
  106. package/core/plugin/index.ts +7 -7
  107. package/core/plugin/loader.ts +19 -19
  108. package/core/plugin/registry.ts +12 -23
  109. package/core/schemas/agents.ts +1 -1
  110. package/core/schemas/analysis.ts +1 -1
  111. package/core/schemas/enriched-task.ts +62 -49
  112. package/core/schemas/ideas.ts +13 -13
  113. package/core/schemas/index.ts +17 -27
  114. package/core/schemas/issues.ts +40 -25
  115. package/core/schemas/metrics.ts +143 -0
  116. package/core/schemas/outcomes.ts +70 -62
  117. package/core/schemas/permissions.ts +15 -12
  118. package/core/schemas/prd.ts +27 -14
  119. package/core/schemas/project.ts +3 -3
  120. package/core/schemas/roadmap.ts +47 -34
  121. package/core/schemas/schemas.ts +3 -4
  122. package/core/schemas/shipped.ts +3 -3
  123. package/core/schemas/state.ts +43 -29
  124. package/core/server/index.ts +5 -6
  125. package/core/server/routes-extended.ts +68 -72
  126. package/core/server/routes.ts +3 -3
  127. package/core/server/server.ts +31 -26
  128. package/core/services/agent-generator.ts +237 -0
  129. package/core/services/agent-service.ts +2 -2
  130. package/core/services/breakdown-service.ts +2 -4
  131. package/core/services/context-generator.ts +299 -0
  132. package/core/services/context-selector.ts +420 -0
  133. package/core/services/doctor-service.ts +426 -0
  134. package/core/services/file-categorizer.ts +448 -0
  135. package/core/services/file-scorer.ts +270 -0
  136. package/core/services/git-analyzer.ts +267 -0
  137. package/core/services/index.ts +27 -10
  138. package/core/services/memory-service.ts +3 -4
  139. package/core/services/project-index.ts +911 -0
  140. package/core/services/project-service.ts +4 -4
  141. package/core/services/skill-installer.ts +14 -17
  142. package/core/services/skill-lock.ts +3 -3
  143. package/core/services/skill-service.ts +12 -6
  144. package/core/services/stack-detector.ts +245 -0
  145. package/core/services/sync-service.ts +170 -329
  146. package/core/services/watch-service.ts +294 -0
  147. package/core/session/compaction.ts +23 -31
  148. package/core/session/index.ts +11 -5
  149. package/core/session/log-migration.ts +3 -3
  150. package/core/session/metrics.ts +19 -14
  151. package/core/session/session-log-manager.ts +12 -17
  152. package/core/session/task-session-manager.ts +25 -25
  153. package/core/session/utils.ts +1 -1
  154. package/core/storage/ideas-storage.ts +41 -57
  155. package/core/storage/index-storage.ts +514 -0
  156. package/core/storage/index.ts +41 -13
  157. package/core/storage/metrics-storage.ts +320 -0
  158. package/core/storage/queue-storage.ts +35 -45
  159. package/core/storage/shipped-storage.ts +17 -20
  160. package/core/storage/state-storage.ts +50 -30
  161. package/core/storage/storage-manager.ts +6 -6
  162. package/core/storage/storage.ts +18 -15
  163. package/core/sync/auth-config.ts +3 -3
  164. package/core/sync/index.ts +13 -19
  165. package/core/sync/oauth-handler.ts +3 -3
  166. package/core/sync/sync-client.ts +4 -9
  167. package/core/sync/sync-manager.ts +12 -14
  168. package/core/types/commands.ts +42 -7
  169. package/core/types/index.ts +284 -302
  170. package/core/types/integrations.ts +3 -3
  171. package/core/types/storage.ts +49 -0
  172. package/core/types/utils.ts +3 -3
  173. package/core/utils/agent-stream.ts +3 -1
  174. package/core/utils/animations.ts +14 -11
  175. package/core/utils/branding.ts +7 -7
  176. package/core/utils/cache.ts +1 -3
  177. package/core/utils/collection-filters.ts +3 -15
  178. package/core/utils/date-helper.ts +2 -7
  179. package/core/utils/file-helper.ts +13 -8
  180. package/core/utils/jsonl-helper.ts +13 -10
  181. package/core/utils/keychain.ts +4 -8
  182. package/core/utils/logger.ts +1 -1
  183. package/core/utils/next-steps.ts +3 -3
  184. package/core/utils/output.ts +58 -11
  185. package/core/utils/project-commands.ts +6 -6
  186. package/core/utils/project-credentials.ts +5 -12
  187. package/core/utils/runtime.ts +2 -2
  188. package/core/utils/session-helper.ts +3 -4
  189. package/core/utils/version.ts +3 -3
  190. package/core/wizard/index.ts +13 -0
  191. package/core/wizard/onboarding.ts +633 -0
  192. package/core/workflow/state-machine.ts +7 -7
  193. package/dist/bin/prjct.mjs +18907 -13189
  194. package/dist/core/infrastructure/command-installer.js +96 -111
  195. package/dist/core/infrastructure/editors-config.js +6 -6
  196. package/dist/core/infrastructure/setup.js +256 -257
  197. package/dist/core/utils/version.js +9 -9
  198. package/package.json +11 -12
  199. package/scripts/build.js +3 -3
  200. package/scripts/postinstall.js +2 -2
  201. package/templates/mcp-config.json +6 -1
  202. package/templates/permissions/permissive.jsonc +1 -1
  203. package/templates/permissions/strict.jsonc +5 -9
  204. package/templates/global/docs/agents.md +0 -88
  205. package/templates/global/docs/architecture.md +0 -103
  206. package/templates/global/docs/commands.md +0 -96
  207. package/templates/global/docs/validation.md +0 -95
@@ -11,12 +11,12 @@
11
11
  * └── summary.md - Project summary
12
12
  */
13
13
 
14
- import fs from 'fs/promises'
15
- import path from 'path'
16
- import { exec } from 'child_process'
17
- import { promisify } from 'util'
18
- import { getStorage } from '../storage'
14
+ import { exec } from 'node:child_process'
15
+ import fs from 'node:fs/promises'
16
+ import path from 'node:path'
17
+ import { promisify } from 'node:util'
19
18
  import pathManager from '../infrastructure/path-manager'
19
+ import { getStorage } from '../storage'
20
20
 
21
21
  const execAsync = promisify(exec)
22
22
 
@@ -59,7 +59,7 @@ interface Agent {
59
59
  * Generate all context MD files from JSON data
60
60
  */
61
61
  export async function generateContext(projectId: string, repoPath: string): Promise<void> {
62
- const globalPath = pathManager.getGlobalProjectPath(projectId)
62
+ const _globalPath = pathManager.getGlobalProjectPath(projectId)
63
63
  const contextPath = pathManager.getContextPath(projectId)
64
64
  const storage = getStorage(projectId)
65
65
 
@@ -67,7 +67,7 @@ export async function generateContext(projectId: string, repoPath: string): Prom
67
67
  await fs.mkdir(contextPath, { recursive: true })
68
68
 
69
69
  // Read all data
70
- const project = await storage.read<ProjectData>(['project']) || {}
70
+ const project = (await storage.read<ProjectData>(['project'])) || {}
71
71
  const taskPaths = await storage.list(['task'])
72
72
  const featurePaths = await storage.list(['feature'])
73
73
  const ideaPaths = await storage.list(['idea'])
@@ -104,7 +104,18 @@ export async function generateContext(projectId: string, repoPath: string): Prom
104
104
  const pkgData = await getPackageData(repoPath)
105
105
 
106
106
  // Generate each context file
107
- await generateClaudeMd(contextPath, projectId, project, tasks, features, ideas, agents, gitData, pkgData, repoPath)
107
+ await generateClaudeMd(
108
+ contextPath,
109
+ projectId,
110
+ project,
111
+ tasks,
112
+ features,
113
+ ideas,
114
+ agents,
115
+ gitData,
116
+ pkgData,
117
+ repoPath
118
+ )
108
119
  await generateNowMd(contextPath, tasks)
109
120
  await generateQueueMd(contextPath, tasks)
110
121
  await generateSummaryMd(contextPath, project, gitData, pkgData)
@@ -116,7 +127,7 @@ async function getGitData(repoPath: string) {
116
127
  commits: 0,
117
128
  contributors: 0,
118
129
  hasChanges: false,
119
- recentCommits: [] as { hash: string; message: string; date: string }[]
130
+ recentCommits: [] as { hash: string; message: string; date: string }[],
120
131
  }
121
132
 
122
133
  try {
@@ -124,19 +135,27 @@ async function getGitData(repoPath: string) {
124
135
  data.branch = branch.trim() || 'main'
125
136
 
126
137
  const { stdout: commits } = await execAsync('git rev-list --count HEAD', { cwd: repoPath })
127
- data.commits = parseInt(commits.trim()) || 0
138
+ data.commits = parseInt(commits.trim(), 10) || 0
128
139
 
129
- const { stdout: contributors } = await execAsync('git shortlog -sn --all | wc -l', { cwd: repoPath })
130
- data.contributors = parseInt(contributors.trim()) || 0
140
+ const { stdout: contributors } = await execAsync('git shortlog -sn --all | wc -l', {
141
+ cwd: repoPath,
142
+ })
143
+ data.contributors = parseInt(contributors.trim(), 10) || 0
131
144
 
132
145
  const { stdout: status } = await execAsync('git status --porcelain', { cwd: repoPath })
133
146
  data.hasChanges = status.trim().length > 0
134
147
 
135
- const { stdout: log } = await execAsync('git log --oneline -10 --pretty=format:"%h|%s|%ad" --date=short', { cwd: repoPath })
136
- data.recentCommits = log.split('\n').filter(Boolean).map(line => {
137
- const [hash, message, date] = line.split('|')
138
- return { hash, message, date }
139
- })
148
+ const { stdout: log } = await execAsync(
149
+ 'git log --oneline -10 --pretty=format:"%h|%s|%ad" --date=short',
150
+ { cwd: repoPath }
151
+ )
152
+ data.recentCommits = log
153
+ .split('\n')
154
+ .filter(Boolean)
155
+ .map((line) => {
156
+ const [hash, message, date] = line.split('|')
157
+ return { hash, message, date }
158
+ })
140
159
  } catch (_error) {
141
160
  // Not a git repo - expected
142
161
  }
@@ -148,7 +167,7 @@ async function getPackageData(repoPath: string) {
148
167
  const data = {
149
168
  dependencies: {} as Record<string, string>,
150
169
  devDependencies: {} as Record<string, string>,
151
- scripts: {} as Record<string, string>
170
+ scripts: {} as Record<string, string>,
152
171
  }
153
172
 
154
173
  try {
@@ -177,9 +196,9 @@ async function generateClaudeMd(
177
196
  repoPath: string
178
197
  ) {
179
198
  const projectName = project.name || path.basename(repoPath)
180
- const currentTask = tasks.find(t => t.status === 'in_progress')
181
- const pendingTasks = tasks.filter(t => t.status === 'pending')
182
- const activeFeatures = features.filter(f => f.status === 'in_progress' || f.status === 'active')
199
+ const currentTask = tasks.find((t) => t.status === 'in_progress')
200
+ const pendingTasks = tasks.filter((t) => t.status === 'pending')
201
+ const activeFeatures = features.filter((f) => f.status === 'in_progress' || f.status === 'active')
183
202
 
184
203
  const deps = Object.keys(pkgData.dependencies)
185
204
  const devDeps = Object.keys(pkgData.devDependencies)
@@ -193,14 +212,20 @@ async function generateClaudeMd(
193
212
  ### Dependencies (${deps.length + devDeps.length})
194
213
 
195
214
  **Production** (${deps.length}):
196
- ${deps.length > 0 ? deps.map(d => `- ${d}: ${pkgData.dependencies[d]}`).join('\n') : '_None_'}
215
+ ${deps.length > 0 ? deps.map((d) => `- ${d}: ${pkgData.dependencies[d]}`).join('\n') : '_None_'}
197
216
 
198
217
  **Dev** (${devDeps.length}):
199
- ${devDeps.length > 0 ? devDeps.map(d => `- ${d}: ${pkgData.devDependencies[d]}`).join('\n') : '_None_'}
218
+ ${devDeps.length > 0 ? devDeps.map((d) => `- ${d}: ${pkgData.devDependencies[d]}`).join('\n') : '_None_'}
200
219
 
201
220
  ### Scripts
202
221
 
203
- ${Object.keys(pkgData.scripts).length > 0 ? Object.entries(pkgData.scripts).map(([k, v]) => `- \`${k}\`: ${v}`).join('\n') : '_None_'}
222
+ ${
223
+ Object.keys(pkgData.scripts).length > 0
224
+ ? Object.entries(pkgData.scripts)
225
+ .map(([k, v]) => `- \`${k}\`: ${v}`)
226
+ .join('\n')
227
+ : '_None_'
228
+ }
204
229
 
205
230
  ### Git
206
231
 
@@ -210,7 +235,14 @@ ${Object.keys(pkgData.scripts).length > 0 ? Object.entries(pkgData.scripts).map(
210
235
  - Uncommitted: ${gitData.hasChanges ? 'Yes' : 'No'}
211
236
 
212
237
  **Recent:**
213
- ${gitData.recentCommits.length > 0 ? gitData.recentCommits.slice(0, 5).map(c => `- \`${c.hash}\` ${c.message}`).join('\n') : '_None_'}
238
+ ${
239
+ gitData.recentCommits.length > 0
240
+ ? gitData.recentCommits
241
+ .slice(0, 5)
242
+ .map((c) => `- \`${c.hash}\` ${c.message}`)
243
+ .join('\n')
244
+ : '_None_'
245
+ }
214
246
 
215
247
  ---
216
248
 
@@ -219,19 +251,33 @@ ${gitData.recentCommits.length > 0 ? gitData.recentCommits.slice(0, 5).map(c =>
219
251
  **Now:** ${currentTask ? currentTask.description : '_No active task_'}
220
252
 
221
253
  **Queue (${pendingTasks.length}):**
222
- ${pendingTasks.length > 0 ? pendingTasks.slice(0, 10).map((t, i) => `${i + 1}. ${t.description}`).join('\n') : '_Empty_'}
254
+ ${
255
+ pendingTasks.length > 0
256
+ ? pendingTasks
257
+ .slice(0, 10)
258
+ .map((t, i) => `${i + 1}. ${t.description}`)
259
+ .join('\n')
260
+ : '_Empty_'
261
+ }
223
262
 
224
263
  **Active Features (${activeFeatures.length}):**
225
- ${activeFeatures.length > 0 ? activeFeatures.map(f => `- ${f.name}`).join('\n') : '_None_'}
264
+ ${activeFeatures.length > 0 ? activeFeatures.map((f) => `- ${f.name}`).join('\n') : '_None_'}
226
265
 
227
266
  **Ideas (${ideas.length}):**
228
- ${ideas.length > 0 ? ideas.slice(0, 5).map(i => `- ${i.title}`).join('\n') : '_None_'}
267
+ ${
268
+ ideas.length > 0
269
+ ? ideas
270
+ .slice(0, 5)
271
+ .map((i) => `- ${i.title}`)
272
+ .join('\n')
273
+ : '_None_'
274
+ }
229
275
 
230
276
  ---
231
277
 
232
278
  ## AGENTS
233
279
 
234
- ${agents.length > 0 ? agents.map(a => `- **${a.name}**: ${a.role || 'Specialist'}`).join('\n') : '_None_'}
280
+ ${agents.length > 0 ? agents.map((a) => `- **${a.name}**: ${a.role || 'Specialist'}`).join('\n') : '_None_'}
235
281
 
236
282
  ---
237
283
 
@@ -258,7 +304,7 @@ ${agents.length > 0 ? agents.map(a => `- **${a.name}**: ${a.role || 'Specialist'
258
304
  }
259
305
 
260
306
  async function generateNowMd(contextPath: string, tasks: Task[]) {
261
- const currentTask = tasks.find(t => t.status === 'in_progress')
307
+ const currentTask = tasks.find((t) => t.status === 'in_progress')
262
308
 
263
309
  const content = currentTask
264
310
  ? `# NOW
@@ -278,12 +324,15 @@ _No active task. Use /p:now to start._
278
324
  }
279
325
 
280
326
  async function generateQueueMd(contextPath: string, tasks: Task[]) {
281
- const pendingTasks = tasks.filter(t => t.status === 'pending')
327
+ const pendingTasks = tasks.filter((t) => t.status === 'pending')
282
328
 
283
329
  const content = `# QUEUE
284
330
 
285
- ${pendingTasks.length > 0
286
- ? pendingTasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ''}`).join('\n')
331
+ ${
332
+ pendingTasks.length > 0
333
+ ? pendingTasks
334
+ .map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ''}`)
335
+ .join('\n')
287
336
  : '_Empty queue. Use /p:next to add tasks._'
288
337
  }
289
338
  `