prjct-cli 0.45.0 → 0.45.4

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 +82 -0
  2. package/bin/prjct.ts +117 -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 +58 -39
  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 +28 -4
  43. package/core/commands/commands.ts +57 -24
  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 +13 -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 +18 -19
  59. package/core/context-tools/imports-tool.ts +13 -33
  60. package/core/context-tools/index.ts +29 -54
  61. package/core/context-tools/recent-tool.ts +16 -22
  62. package/core/context-tools/signatures-tool.ts +17 -26
  63. package/core/context-tools/summary-tool.ts +20 -22
  64. package/core/context-tools/token-counter.ts +25 -20
  65. package/core/context-tools/types.ts +5 -5
  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 -16
  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 +25 -25
  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 +87 -345
  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 -17
  157. package/core/storage/metrics-storage.ts +39 -34
  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 -305
  170. package/core/types/integrations.ts +3 -3
  171. package/core/types/storage.ts +14 -14
  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 +18755 -15574
  194. package/dist/core/infrastructure/command-installer.js +86 -79
  195. package/dist/core/infrastructure/editors-config.js +6 -6
  196. package/dist/core/infrastructure/setup.js +246 -225
  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
@@ -5,14 +5,8 @@
5
5
  * Powers the learning loop for better estimates and agent selection.
6
6
  */
7
7
 
8
+ import type { AgentMetrics, DetectedPattern, Outcome, OutcomeSummary } from '../types'
8
9
  import outcomeRecorder from './recorder'
9
- import type {
10
- Outcome,
11
- OutcomeSummary,
12
- QualityScore,
13
- DetectedPattern,
14
- AgentMetrics,
15
- } from '../types'
16
10
 
17
11
  /**
18
12
  * OutcomeAnalyzer - Extracts insights from outcomes.
@@ -36,8 +30,7 @@ export class OutcomeAnalyzer {
36
30
  }
37
31
 
38
32
  // Calculate average quality
39
- const avgQuality =
40
- outcomes.reduce((sum, o) => sum + o.qualityScore, 0) / outcomes.length
33
+ const avgQuality = outcomes.reduce((sum, o) => sum + o.qualityScore, 0) / outcomes.length
41
34
 
42
35
  // Calculate estimate accuracy
43
36
  const estimateAccuracy = await outcomeRecorder.getEstimateAccuracy(projectId)
@@ -98,8 +91,7 @@ export class OutcomeAnalyzer {
98
91
  const successful = agentOutcomes.filter((o) => o.completedAsPlanned)
99
92
  const successRate = Math.round((successful.length / tasksCompleted) * 100)
100
93
 
101
- const avgQuality =
102
- agentOutcomes.reduce((sum, o) => sum + o.qualityScore, 0) / tasksCompleted
94
+ const avgQuality = agentOutcomes.reduce((sum, o) => sum + o.qualityScore, 0) / tasksCompleted
103
95
 
104
96
  // Calculate estimate accuracy for this agent
105
97
  const accurateEstimates = agentOutcomes.filter((o) => {
@@ -109,9 +101,7 @@ export class OutcomeAnalyzer {
109
101
  if (estimated === 0) return false
110
102
  return Math.abs(variance) / estimated <= 0.2
111
103
  })
112
- const estimateAccuracy = Math.round(
113
- (accurateEstimates.length / tasksCompleted) * 100
114
- )
104
+ const estimateAccuracy = Math.round((accurateEstimates.length / tasksCompleted) * 100)
115
105
 
116
106
  // Find best task types
117
107
  const taskTypes = new Map<string, number>()
@@ -214,10 +204,7 @@ export class OutcomeAnalyzer {
214
204
  /**
215
205
  * Suggest estimate for a task type based on history.
216
206
  */
217
- async suggestEstimate(
218
- projectId: string,
219
- taskType: string
220
- ): Promise<string | null> {
207
+ async suggestEstimate(projectId: string, taskType: string): Promise<string | null> {
221
208
  const outcomes = await outcomeRecorder.getAll(projectId)
222
209
 
223
210
  // Filter by task type (using tags)
@@ -29,6 +29,6 @@
29
29
  * ```
30
30
  */
31
31
 
32
- export { OutcomeRecorder, default as outcomeRecorder } from './recorder'
33
- export { OutcomeAnalyzer, default as outcomeAnalyzer } from './analyzer'
34
32
  export * from '../types'
33
+ export { default as outcomeAnalyzer, OutcomeAnalyzer } from './analyzer'
34
+ export { default as outcomeRecorder, OutcomeRecorder } from './recorder'
@@ -5,11 +5,11 @@
5
5
  * Appends to JSONL files for efficient streaming.
6
6
  */
7
7
 
8
- import path from 'path'
9
- import * as fileHelper from '../utils/file-helper'
8
+ import path from 'node:path'
10
9
  import pathManager from '../infrastructure/path-manager'
11
10
  import { generateUUID } from '../schemas'
12
- import type { Outcome, OutcomeInput, OutcomeFilter } from '../types'
11
+ import type { Outcome, OutcomeFilter, OutcomeInput } from '../types'
12
+ import * as fileHelper from '../utils/file-helper'
13
13
 
14
14
  const OUTCOMES_DIR = 'outcomes'
15
15
  const OUTCOMES_FILE = 'outcomes.jsonl'
@@ -17,10 +17,10 @@
17
17
  * }
18
18
  */
19
19
 
20
- import crypto from 'crypto'
20
+ import crypto from 'node:crypto'
21
21
  import { EventTypes } from '../../bus'
22
+ import type { WebhookConfig, WebhookPayload, WebhookPluginContext } from '../../types'
22
23
  import { HookPoints } from '../hooks'
23
- import type { WebhookConfig, WebhookPluginContext, WebhookPayload } from '../../types'
24
24
 
25
25
  const plugin = {
26
26
  name: 'webhook',
@@ -47,7 +47,7 @@ const plugin = {
47
47
  plugin.enabledEvents = config.events || [
48
48
  EventTypes.SESSION_COMPLETED,
49
49
  EventTypes.FEATURE_SHIPPED,
50
- EventTypes.SNAPSHOT_CREATED
50
+ EventTypes.SNAPSHOT_CREATED,
51
51
  ]
52
52
  },
53
53
 
@@ -62,34 +62,38 @@ const plugin = {
62
62
  * Event handlers
63
63
  */
64
64
  events: {
65
- [EventTypes.SESSION_COMPLETED]: async function(data: unknown): Promise<void> {
65
+ [EventTypes.SESSION_COMPLETED]: async (data: unknown): Promise<void> => {
66
66
  await plugin.sendWebhook('session.completed', data)
67
67
  },
68
68
 
69
- [EventTypes.FEATURE_SHIPPED]: async function(data: unknown): Promise<void> {
69
+ [EventTypes.FEATURE_SHIPPED]: async (data: unknown): Promise<void> => {
70
70
  await plugin.sendWebhook('feature.shipped', data)
71
71
  },
72
72
 
73
- [EventTypes.SNAPSHOT_CREATED]: async function(data: unknown): Promise<void> {
73
+ [EventTypes.SNAPSHOT_CREATED]: async (data: unknown): Promise<void> => {
74
74
  await plugin.sendWebhook('snapshot.created', data)
75
75
  },
76
76
 
77
- [EventTypes.TASK_COMPLETED]: async function(data: unknown): Promise<void> {
77
+ [EventTypes.TASK_COMPLETED]: async (data: unknown): Promise<void> => {
78
78
  await plugin.sendWebhook('task.completed', data)
79
- }
79
+ },
80
80
  },
81
81
 
82
82
  /**
83
83
  * Hook handlers
84
84
  */
85
85
  hooks: {
86
- [HookPoints.AFTER_FEATURE_SHIP]: async function(data: { feature: string; version: string; timestamp: string }): Promise<void> {
86
+ [HookPoints.AFTER_FEATURE_SHIP]: async (data: {
87
+ feature: string
88
+ version: string
89
+ timestamp: string
90
+ }): Promise<void> => {
87
91
  await plugin.sendWebhook('feature.shipped', {
88
92
  feature: data.feature,
89
93
  version: data.version,
90
- timestamp: data.timestamp
94
+ timestamp: data.timestamp,
91
95
  })
92
- }
96
+ },
93
97
  },
94
98
 
95
99
  /**
@@ -107,13 +111,13 @@ const plugin = {
107
111
  event,
108
112
  timestamp: new Date().toISOString(),
109
113
  source: 'prjct-cli',
110
- data
114
+ data,
111
115
  }
112
116
 
113
117
  try {
114
118
  const headers: Record<string, string> = {
115
119
  'Content-Type': 'application/json',
116
- 'User-Agent': 'prjct-cli/webhook'
120
+ 'User-Agent': 'prjct-cli/webhook',
117
121
  }
118
122
 
119
123
  // Add signature if secret is configured
@@ -128,7 +132,7 @@ const plugin = {
128
132
  const response = await fetch(plugin.config.url, {
129
133
  method: 'POST',
130
134
  headers,
131
- body: JSON.stringify(payload)
135
+ body: JSON.stringify(payload),
132
136
  })
133
137
 
134
138
  if (!response.ok) {
@@ -137,7 +141,7 @@ const plugin = {
137
141
  } catch (error) {
138
142
  console.error(`[webhook] Error sending webhook:`, (error as Error).message)
139
143
  }
140
- }
144
+ },
141
145
  }
142
146
 
143
147
  export default plugin
@@ -7,7 +7,7 @@
7
7
  * @version 1.0.0
8
8
  */
9
9
 
10
- import { eventBus, EventTypes } from '../bus'
10
+ import { EventTypes, eventBus } from '../bus'
11
11
 
12
12
  /**
13
13
  * Hook Points - Where plugins can intercept
@@ -37,10 +37,10 @@ const HookPoints = {
37
37
  // Transform hooks (must return modified data)
38
38
  TRANSFORM_COMMIT_MESSAGE: 'transform:commit.message',
39
39
  TRANSFORM_TASK_DATA: 'transform:task.data',
40
- TRANSFORM_METRICS: 'transform:metrics'
40
+ TRANSFORM_METRICS: 'transform:metrics',
41
41
  } as const
42
42
 
43
- type HookPoint = typeof HookPoints[keyof typeof HookPoints]
43
+ type HookPoint = (typeof HookPoints)[keyof typeof HookPoints]
44
44
  type HookHandler = (data: unknown, context?: unknown) => unknown | Promise<unknown>
45
45
 
46
46
  interface HookEntry {
@@ -83,7 +83,7 @@ class HookSystem {
83
83
  handler,
84
84
  pluginName,
85
85
  priority,
86
- id: `${pluginName}:${Date.now()}`
86
+ id: `${pluginName}:${Date.now()}`,
87
87
  }
88
88
 
89
89
  this.hooks.get(hookPoint)!.push(hookEntry)
@@ -107,7 +107,7 @@ class HookSystem {
107
107
  unregister(hookPoint: string, id: string): void {
108
108
  const hooks = this.hooks.get(hookPoint)
109
109
  if (hooks) {
110
- const index = hooks.findIndex(h => h.id === id)
110
+ const index = hooks.findIndex((h) => h.id === id)
111
111
  if (index !== -1) {
112
112
  hooks.splice(index, 1)
113
113
  }
@@ -130,7 +130,10 @@ class HookSystem {
130
130
  /**
131
131
  * Execute a "before" hook (can modify data)
132
132
  */
133
- async executeBefore(hookPoint: string, data: Record<string, unknown>): Promise<Record<string, unknown>> {
133
+ async executeBefore(
134
+ hookPoint: string,
135
+ data: Record<string, unknown>
136
+ ): Promise<Record<string, unknown>> {
134
137
  const hooks = this.hooks.get(hookPoint) || []
135
138
  let result = { ...data }
136
139
 
@@ -157,11 +160,14 @@ class HookSystem {
157
160
 
158
161
  // Execute all hooks in parallel for after hooks
159
162
  await Promise.allSettled(
160
- hooks.map(async hook => {
163
+ hooks.map(async (hook) => {
161
164
  try {
162
165
  await hook.handler(data)
163
166
  } catch (error) {
164
- console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, (error as Error).message)
167
+ console.error(
168
+ `Hook error [${hook.pluginName}] at ${hookPoint}:`,
169
+ (error as Error).message
170
+ )
165
171
  }
166
172
  })
167
173
  )
@@ -176,7 +182,11 @@ class HookSystem {
176
182
  /**
177
183
  * Execute a "transform" hook (must return modified value)
178
184
  */
179
- async executeTransform<T>(hookPoint: string, value: T, context: Record<string, unknown> = {}): Promise<T> {
185
+ async executeTransform<T>(
186
+ hookPoint: string,
187
+ value: T,
188
+ context: Record<string, unknown> = {}
189
+ ): Promise<T> {
180
190
  const hooks = this.hooks.get(hookPoint) || []
181
191
  let result = value
182
192
 
@@ -187,7 +197,10 @@ class HookSystem {
187
197
  result = transformed as T
188
198
  }
189
199
  } catch (error) {
190
- console.error(`Transform hook error [${hook.pluginName}] at ${hookPoint}:`, (error as Error).message)
200
+ console.error(
201
+ `Transform hook error [${hook.pluginName}] at ${hookPoint}:`,
202
+ (error as Error).message
203
+ )
191
204
  // Keep previous value on error
192
205
  }
193
206
  }
@@ -210,7 +223,7 @@ class HookSystem {
210
223
  [HookPoints.AFTER_SNAPSHOT_RESTORE]: EventTypes.SNAPSHOT_RESTORED,
211
224
  [HookPoints.AFTER_COMMIT]: EventTypes.COMMIT_CREATED,
212
225
  [HookPoints.AFTER_PUSH]: EventTypes.PUSH_COMPLETED,
213
- [HookPoints.AFTER_SYNC]: EventTypes.PROJECT_SYNCED
226
+ [HookPoints.AFTER_SYNC]: EventTypes.PROJECT_SYNCED,
214
227
  }
215
228
  return mapping[hookPoint] || null
216
229
  }
@@ -219,9 +232,9 @@ class HookSystem {
219
232
  * Get all registered hooks for a point
220
233
  */
221
234
  getHooks(hookPoint: string): Array<{ pluginName: string; priority: number }> {
222
- return (this.hooks.get(hookPoint) || []).map(h => ({
235
+ return (this.hooks.get(hookPoint) || []).map((h) => ({
223
236
  pluginName: h.pluginName,
224
- priority: h.priority
237
+ priority: h.priority,
225
238
  }))
226
239
  }
227
240
 
@@ -230,7 +243,7 @@ class HookSystem {
230
243
  */
231
244
  getPluginHooks(pluginName: string): string[] {
232
245
  const entries = this.pluginHooks.get(pluginName) || []
233
- return entries.map(e => e.hookPoint)
246
+ return entries.map((e) => e.hookPoint)
234
247
  }
235
248
 
236
249
  /**
@@ -298,14 +311,9 @@ const hooks = {
298
311
  */
299
312
  runTransform: <T>(point: string, value: T, context?: Record<string, unknown>) => {
300
313
  return hookSystem.executeTransform(`transform:${point}`, value, context)
301
- }
314
+ },
302
315
  }
303
316
 
304
- export {
305
- HookSystem,
306
- HookPoints,
307
- hookSystem,
308
- hooks
309
- }
317
+ export { HookSystem, HookPoints, hookSystem, hooks }
310
318
 
311
319
  export default { HookSystem, HookPoints, hookSystem, hooks }
@@ -6,14 +6,17 @@
6
6
  * @version 1.0.0
7
7
  */
8
8
 
9
- import { HookSystem, HookPoints, hookSystem, hooks } from './hooks'
9
+ import { HookPoints, HookSystem, hookSystem, hooks } from './hooks'
10
10
  import { PluginLoader, pluginLoader } from './loader'
11
11
  import { PluginRegistry, pluginRegistry } from './registry'
12
12
 
13
13
  /**
14
14
  * Initialize the complete plugin system
15
15
  */
16
- async function initializePlugins(projectPath: string, config: Record<string, unknown> = {}): Promise<void> {
16
+ async function initializePlugins(
17
+ projectPath: string,
18
+ config: Record<string, unknown> = {}
19
+ ): Promise<void> {
17
20
  await pluginRegistry.initialize()
18
21
  await pluginLoader.initialize(projectPath, config)
19
22
  }
@@ -35,18 +38,15 @@ export {
35
38
  HookPoints,
36
39
  hookSystem,
37
40
  hooks,
38
-
39
41
  // Plugin loader
40
42
  PluginLoader,
41
43
  pluginLoader,
42
-
43
44
  // Plugin registry
44
45
  PluginRegistry,
45
46
  pluginRegistry,
46
-
47
47
  // Convenience functions
48
48
  initializePlugins,
49
- shutdownPlugins
49
+ shutdownPlugins,
50
50
  }
51
51
 
52
52
  export default {
@@ -59,5 +59,5 @@ export default {
59
59
  PluginRegistry,
60
60
  pluginRegistry,
61
61
  initializePlugins,
62
- shutdownPlugins
62
+ shutdownPlugins,
63
63
  }
@@ -9,12 +9,12 @@
9
9
  * @version 1.0.0
10
10
  */
11
11
 
12
- import fs from 'fs/promises'
13
- import path from 'path'
14
- import { hookSystem } from './hooks'
15
- import { eventBus, type EventCallback } from '../bus'
12
+ import fs from 'node:fs/promises'
13
+ import path from 'node:path'
14
+ import { type EventCallback, eventBus } from '../bus'
16
15
  import pathManager from '../infrastructure/path-manager'
17
16
  import { isNotFoundError } from '../types/fs'
17
+ import { hookSystem } from './hooks'
18
18
 
19
19
  type PluginSource = 'builtin' | 'global' | 'project'
20
20
  type HookHandler = (data: unknown) => unknown | Promise<unknown>
@@ -118,9 +118,10 @@ class PluginLoader {
118
118
  for (const file of files) {
119
119
  const filePath = path.join(globalPath, file)
120
120
  if (file.endsWith('.js') || file.endsWith('.ts') || (await this.isDirectory(filePath))) {
121
- const pluginPath = (file.endsWith('.js') || file.endsWith('.ts'))
122
- ? filePath
123
- : path.join(filePath, 'index.js')
121
+ const pluginPath =
122
+ file.endsWith('.js') || file.endsWith('.ts')
123
+ ? filePath
124
+ : path.join(filePath, 'index.js')
124
125
  await this.loadPlugin(pluginPath, 'global')
125
126
  }
126
127
  }
@@ -169,7 +170,11 @@ class PluginLoader {
169
170
  /**
170
171
  * Load a single plugin
171
172
  */
172
- async loadPlugin(pluginPath: string, source: PluginSource, config: Record<string, unknown> = {}): Promise<void> {
173
+ async loadPlugin(
174
+ pluginPath: string,
175
+ source: PluginSource,
176
+ config: Record<string, unknown> = {}
177
+ ): Promise<void> {
173
178
  try {
174
179
  // Check if file exists
175
180
  await fs.access(pluginPath)
@@ -192,7 +197,7 @@ class PluginLoader {
192
197
  this.plugins.set(plugin.name, {
193
198
  ...plugin,
194
199
  source,
195
- config: { ...config, ...(this.config[plugin.name] as Record<string, unknown> || {}) }
200
+ config: { ...config, ...((this.config[plugin.name] as Record<string, unknown>) || {}) },
196
201
  })
197
202
  this.pluginPaths.set(plugin.name, pluginPath)
198
203
 
@@ -212,10 +217,9 @@ class PluginLoader {
212
217
  config: this.plugins.get(plugin.name)!.config!,
213
218
  eventBus,
214
219
  hookSystem,
215
- projectPath: this.projectPath
220
+ projectPath: this.projectPath,
216
221
  })
217
222
  }
218
-
219
223
  } catch (error) {
220
224
  const err = error as NodeJS.ErrnoException
221
225
  if (err.code === 'ENOENT') {
@@ -235,7 +239,7 @@ class PluginLoader {
235
239
  for (const [hookPoint, handler] of Object.entries(plugin.hooks || {})) {
236
240
  hookSystem.register(hookPoint, handler, {
237
241
  pluginName: plugin.name,
238
- priority: plugin.priority || 10
242
+ priority: plugin.priority || 10,
239
243
  })
240
244
  }
241
245
  }
@@ -304,7 +308,7 @@ class PluginLoader {
304
308
  * Get plugins by source
305
309
  */
306
310
  getPluginsBySource(source: PluginSource): Plugin[] {
307
- return this.getAllPlugins().filter(p => p.source === source)
311
+ return this.getAllPlugins().filter((p) => p.source === source)
308
312
  }
309
313
 
310
314
  /**
@@ -319,7 +323,7 @@ class PluginLoader {
319
323
  commands[name] = {
320
324
  handler: handler.handler,
321
325
  plugin: plugin.name,
322
- description: handler.description || `Command from ${plugin.name}`
326
+ description: handler.description || `Command from ${plugin.name}`,
323
327
  }
324
328
  }
325
329
  }
@@ -347,10 +351,6 @@ class PluginLoader {
347
351
  // Singleton instance
348
352
  const pluginLoader = new PluginLoader()
349
353
 
350
- export {
351
- PluginLoader,
352
- pluginLoader,
353
- Plugin
354
- }
354
+ export { PluginLoader, pluginLoader, type Plugin }
355
355
 
356
356
  export default { PluginLoader, pluginLoader }
@@ -6,11 +6,11 @@
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
- import { pluginLoader } from './loader'
13
12
  import { isNotFoundError } from '../types/fs'
13
+ import { pluginLoader } from './loader'
14
14
 
15
15
  type PluginSource = 'builtin' | 'global' | 'project'
16
16
 
@@ -51,16 +51,10 @@ class PluginRegistry {
51
51
  */
52
52
  async discoverPlugins(): Promise<void> {
53
53
  // Built-in plugins
54
- await this.discoverFromPath(
55
- path.join(__dirname, '..', 'plugins'),
56
- 'builtin'
57
- )
54
+ await this.discoverFromPath(path.join(__dirname, '..', 'plugins'), 'builtin')
58
55
 
59
56
  // Global plugins
60
- await this.discoverFromPath(
61
- path.join(pathManager.getGlobalBasePath(), 'plugins'),
62
- 'global'
63
- )
57
+ await this.discoverFromPath(path.join(pathManager.getGlobalBasePath(), 'plugins'), 'global')
64
58
  }
65
59
 
66
60
  /**
@@ -91,7 +85,7 @@ class PluginRegistry {
91
85
  this.availablePlugins.set(metadata.name, {
92
86
  ...metadata,
93
87
  path: pluginPath,
94
- source
88
+ source,
95
89
  })
96
90
  }
97
91
  } catch (error) {
@@ -125,7 +119,7 @@ class PluginRegistry {
125
119
  return {
126
120
  name: nameMatch[1],
127
121
  version: versionMatch ? versionMatch[1] : '1.0.0',
128
- description: descMatch ? descMatch[1] : ''
122
+ description: descMatch ? descMatch[1] : '',
129
123
  }
130
124
  }
131
125
 
@@ -137,7 +131,7 @@ class PluginRegistry {
137
131
  return {
138
132
  name: plugin.name,
139
133
  version: plugin.version || '1.0.0',
140
- description: plugin.description || ''
134
+ description: plugin.description || '',
141
135
  }
142
136
  }
143
137
  } catch (error) {
@@ -161,7 +155,7 @@ class PluginRegistry {
161
155
  * Get available plugins by source
162
156
  */
163
157
  getAvailableBySource(source: PluginSource): PluginMetadata[] {
164
- return this.getAvailable().filter(p => p.source === source)
158
+ return this.getAvailable().filter((p) => p.source === source)
165
159
  }
166
160
 
167
161
  /**
@@ -190,7 +184,7 @@ class PluginRegistry {
190
184
  return {
191
185
  ...(available || { name, version: '1.0.0', description: '' }),
192
186
  loaded: !!loaded,
193
- active: loaded ? true : false
187
+ active: !!loaded,
194
188
  }
195
189
  }
196
190
 
@@ -287,7 +281,7 @@ class PluginRegistry {
287
281
  const bySource: Record<PluginSource, PluginMetadata[]> = {
288
282
  builtin: [],
289
283
  global: [],
290
- project: []
284
+ project: [],
291
285
  }
292
286
 
293
287
  for (const plugin of available) {
@@ -329,11 +323,6 @@ class PluginRegistry {
329
323
  // Singleton instance
330
324
  const pluginRegistry = new PluginRegistry()
331
325
 
332
- export {
333
- PluginRegistry,
334
- pluginRegistry,
335
- PluginMetadata,
336
- PluginInfo
337
- }
326
+ export { PluginRegistry, pluginRegistry, type PluginMetadata, type PluginInfo }
338
327
 
339
328
  export default { PluginRegistry, pluginRegistry }
@@ -23,5 +23,5 @@ export const DEFAULT_AGENT: Omit<AgentSchema, 'name' | 'description'> = {
23
23
  patterns: [],
24
24
  filesOwned: [],
25
25
  bestFor: [],
26
- avoidFor: []
26
+ avoidFor: [],
27
27
  }
@@ -37,5 +37,5 @@ export const DEFAULT_ANALYSIS: Omit<AnalysisSchema, 'projectId'> = {
37
37
  fileCount: 0,
38
38
  patterns: [],
39
39
  antiPatterns: [],
40
- analyzedAt: new Date().toISOString()
40
+ analyzedAt: new Date().toISOString(),
41
41
  }