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
package/core/plugin/loader.ts
CHANGED
|
@@ -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 {
|
|
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 =
|
|
122
|
-
|
|
123
|
-
|
|
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(
|
|
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 }
|
package/core/plugin/registry.ts
CHANGED
|
@@ -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
|
|
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 }
|
package/core/schemas/agents.ts
CHANGED
package/core/schemas/analysis.ts
CHANGED
|
@@ -19,20 +19,14 @@ export const TaskTypeSchema = z.enum([
|
|
|
19
19
|
'epic',
|
|
20
20
|
])
|
|
21
21
|
|
|
22
|
-
export const PrioritySchema = z.enum([
|
|
23
|
-
'critical',
|
|
24
|
-
'high',
|
|
25
|
-
'medium',
|
|
26
|
-
'low',
|
|
27
|
-
'none',
|
|
28
|
-
])
|
|
22
|
+
export const PrioritySchema = z.enum(['critical', 'high', 'medium', 'low', 'none'])
|
|
29
23
|
|
|
30
24
|
export const ComplexitySchema = z.enum([
|
|
31
|
-
'trivial',
|
|
32
|
-
'small',
|
|
33
|
-
'medium',
|
|
34
|
-
'large',
|
|
35
|
-
'epic',
|
|
25
|
+
'trivial', // < 1 hour
|
|
26
|
+
'small', // 1-4 hours
|
|
27
|
+
'medium', // 1-2 days
|
|
28
|
+
'large', // 3-5 days
|
|
29
|
+
'epic', // > 1 week
|
|
36
30
|
])
|
|
37
31
|
|
|
38
32
|
export const RiskLevelSchema = z.enum(['none', 'low', 'medium', 'high', 'critical'])
|
|
@@ -45,7 +39,9 @@ export const UserStorySchema = z.object({
|
|
|
45
39
|
role: z.string().describe('The user role (e.g., "mobile user")'),
|
|
46
40
|
action: z.string().describe('What the user wants to do'),
|
|
47
41
|
benefit: z.string().describe('The benefit they get'),
|
|
48
|
-
formatted: z
|
|
42
|
+
formatted: z
|
|
43
|
+
.string()
|
|
44
|
+
.describe('Formatted user story: "As a [role], I want [action] so that [benefit]"'),
|
|
49
45
|
})
|
|
50
46
|
|
|
51
47
|
// =============================================================================
|
|
@@ -91,11 +87,15 @@ export const DependenciesSchema = z.object({
|
|
|
91
87
|
code: z.array(CodeDependencySchema).default([]),
|
|
92
88
|
api: z.array(ApiDependencySchema).default([]),
|
|
93
89
|
tasks: z.array(TaskDependencySchema).default([]),
|
|
94
|
-
infrastructure: z
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
infrastructure: z
|
|
91
|
+
.array(
|
|
92
|
+
z.object({
|
|
93
|
+
service: z.string(),
|
|
94
|
+
purpose: z.string(),
|
|
95
|
+
risk: RiskLevelSchema,
|
|
96
|
+
})
|
|
97
|
+
)
|
|
98
|
+
.default([]),
|
|
99
99
|
})
|
|
100
100
|
|
|
101
101
|
// =============================================================================
|
|
@@ -103,31 +103,45 @@ export const DependenciesSchema = z.object({
|
|
|
103
103
|
// =============================================================================
|
|
104
104
|
|
|
105
105
|
export const TechnicalAnalysisSchema = z.object({
|
|
106
|
-
affectedFiles: z
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
106
|
+
affectedFiles: z
|
|
107
|
+
.array(
|
|
108
|
+
z.object({
|
|
109
|
+
path: z.string(),
|
|
110
|
+
changes: z.string().describe('Expected changes'),
|
|
111
|
+
complexity: ComplexitySchema,
|
|
112
|
+
})
|
|
113
|
+
)
|
|
114
|
+
.default([]),
|
|
115
|
+
|
|
116
|
+
existingPatterns: z
|
|
117
|
+
.array(
|
|
118
|
+
z.object({
|
|
119
|
+
pattern: z.string().describe('Pattern name'),
|
|
120
|
+
file: z.string().describe('Reference file'),
|
|
121
|
+
relevance: z.string().describe('Why it is relevant'),
|
|
122
|
+
})
|
|
123
|
+
)
|
|
124
|
+
.default([]),
|
|
117
125
|
|
|
118
126
|
suggestedApproach: z.string().optional().describe('Recommended approach'),
|
|
119
127
|
|
|
120
|
-
potentialRisks: z
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
potentialRisks: z
|
|
129
|
+
.array(
|
|
130
|
+
z.object({
|
|
131
|
+
risk: z.string(),
|
|
132
|
+
mitigation: z.string(),
|
|
133
|
+
severity: RiskLevelSchema,
|
|
134
|
+
})
|
|
135
|
+
)
|
|
136
|
+
.default([]),
|
|
137
|
+
|
|
138
|
+
testingStrategy: z
|
|
139
|
+
.object({
|
|
140
|
+
unit: z.array(z.string()).default([]),
|
|
141
|
+
integration: z.array(z.string()).default([]),
|
|
142
|
+
e2e: z.array(z.string()).default([]),
|
|
143
|
+
})
|
|
144
|
+
.optional(),
|
|
131
145
|
})
|
|
132
146
|
|
|
133
147
|
// =============================================================================
|
|
@@ -174,12 +188,9 @@ export const EnrichedTaskSchema = z.object({
|
|
|
174
188
|
// Enrichment
|
|
175
189
|
userStory: UserStorySchema,
|
|
176
190
|
acceptanceCriteria: z.array(AcceptanceCriterionSchema).min(1),
|
|
177
|
-
definitionOfDone: z
|
|
178
|
-
|
|
179
|
-
'Tests pass',
|
|
180
|
-
'Documentation updated',
|
|
181
|
-
'Deployed to staging',
|
|
182
|
-
]),
|
|
191
|
+
definitionOfDone: z
|
|
192
|
+
.array(z.string())
|
|
193
|
+
.default(['Code reviewed', 'Tests pass', 'Documentation updated', 'Deployed to staging']),
|
|
183
194
|
|
|
184
195
|
// Technical analysis
|
|
185
196
|
technicalAnalysis: TechnicalAnalysisSchema,
|
|
@@ -241,13 +252,15 @@ export function isReadyForDev(task: EnrichedTask): { ready: boolean; reasons: st
|
|
|
241
252
|
}
|
|
242
253
|
|
|
243
254
|
// Check blockers
|
|
244
|
-
const blockingDeps = task.dependencies.tasks.filter(t => t.blocking)
|
|
255
|
+
const blockingDeps = task.dependencies.tasks.filter((t) => t.blocking)
|
|
245
256
|
if (blockingDeps.length > 0) {
|
|
246
|
-
reasons.push(`Blocked by: ${blockingDeps.map(t => t.id).join(', ')}`)
|
|
257
|
+
reasons.push(`Blocked by: ${blockingDeps.map((t) => t.id).join(', ')}`)
|
|
247
258
|
}
|
|
248
259
|
|
|
249
260
|
// Check critical risks
|
|
250
|
-
const criticalRisks = task.technicalAnalysis.potentialRisks.filter(
|
|
261
|
+
const criticalRisks = task.technicalAnalysis.potentialRisks.filter(
|
|
262
|
+
(r) => r.severity === 'critical'
|
|
263
|
+
)
|
|
251
264
|
if (criticalRisks.length > 0) {
|
|
252
265
|
reasons.push('Has unmitigated critical risks')
|
|
253
266
|
}
|
package/core/schemas/ideas.ts
CHANGED
|
@@ -23,32 +23,32 @@ export const ImpactEffortSchema = z.object({
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
export const TechStackSchema = z.object({
|
|
26
|
-
frontend: z.string().optional(),
|
|
27
|
-
backend: z.string().optional(),
|
|
28
|
-
payments: z.string().optional(),
|
|
29
|
-
ai: z.string().optional(),
|
|
30
|
-
deploy: z.string().optional(),
|
|
26
|
+
frontend: z.string().optional(), // "Next.js 14, HeroUI"
|
|
27
|
+
backend: z.string().optional(), // "Supabase (Auth, DB, RLS, Realtime)"
|
|
28
|
+
payments: z.string().optional(), // "Stripe Billing"
|
|
29
|
+
ai: z.string().optional(), // "Vercel AI SDK"
|
|
30
|
+
deploy: z.string().optional(), // "Vercel"
|
|
31
31
|
other: z.array(z.string()).optional(),
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
export const IdeaModuleSchema = z.object({
|
|
35
|
-
name: z.string(),
|
|
36
|
-
description: z.string(),
|
|
35
|
+
name: z.string(), // "Multi-tenant"
|
|
36
|
+
description: z.string(), // "Empresas con RLS estricto"
|
|
37
37
|
})
|
|
38
38
|
|
|
39
39
|
export const IdeaRoleSchema = z.object({
|
|
40
|
-
name: z.string(),
|
|
40
|
+
name: z.string(), // "SUPER_ADMIN"
|
|
41
41
|
description: z.string().optional(),
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
export const IdeaItemSchema = z.object({
|
|
45
|
-
id: z.string(),
|
|
46
|
-
text: z.string(),
|
|
45
|
+
id: z.string(), // idea_xxxxxxxx
|
|
46
|
+
text: z.string(), // Title/summary
|
|
47
47
|
details: z.string().optional(),
|
|
48
48
|
priority: IdeaPrioritySchema,
|
|
49
49
|
status: IdeaStatusSchema,
|
|
50
50
|
tags: z.array(z.string()),
|
|
51
|
-
addedAt: z.string(),
|
|
51
|
+
addedAt: z.string(), // ISO8601
|
|
52
52
|
completedAt: z.string().optional(),
|
|
53
53
|
convertedTo: z.string().optional(),
|
|
54
54
|
// Source documentation
|
|
@@ -105,10 +105,10 @@ export const DEFAULT_IDEA: Omit<IdeaSchema, 'id' | 'text'> = {
|
|
|
105
105
|
priority: 'medium',
|
|
106
106
|
status: 'pending',
|
|
107
107
|
tags: [],
|
|
108
|
-
addedAt: new Date().toISOString()
|
|
108
|
+
addedAt: new Date().toISOString(),
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
export const DEFAULT_IDEAS: IdeasJson = {
|
|
112
112
|
ideas: [],
|
|
113
|
-
lastUpdated: ''
|
|
113
|
+
lastUpdated: '',
|
|
114
114
|
}
|
package/core/schemas/index.ts
CHANGED
|
@@ -12,44 +12,34 @@
|
|
|
12
12
|
* - memory/ (context.jsonl, patterns.json)
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
// State (current task + queue)
|
|
16
|
-
export * from './state'
|
|
17
|
-
|
|
18
|
-
// Issues (local cache of issue tracker issues)
|
|
19
|
-
export * from './issues'
|
|
20
|
-
|
|
21
|
-
// Project metadata
|
|
22
|
-
export * from './project'
|
|
23
|
-
|
|
24
15
|
// Agents
|
|
25
16
|
export * from './agents'
|
|
26
|
-
|
|
27
|
-
// Ideas
|
|
28
|
-
export * from './ideas'
|
|
29
|
-
|
|
30
|
-
// Roadmap (features)
|
|
31
|
-
export * from './roadmap'
|
|
32
|
-
|
|
33
|
-
// Shipped items
|
|
34
|
-
export * from './shipped'
|
|
35
|
-
|
|
36
17
|
// Analysis
|
|
37
18
|
export * from './analysis'
|
|
38
|
-
|
|
19
|
+
// Ideas
|
|
20
|
+
export * from './ideas'
|
|
21
|
+
// Issues (local cache of issue tracker issues)
|
|
22
|
+
export * from './issues'
|
|
39
23
|
// Outcomes
|
|
40
24
|
export * from './outcomes'
|
|
41
|
-
|
|
42
25
|
// Permissions
|
|
43
26
|
export * from './permissions'
|
|
44
|
-
|
|
27
|
+
// Project metadata
|
|
28
|
+
export * from './project'
|
|
29
|
+
// Roadmap (features)
|
|
30
|
+
export * from './roadmap'
|
|
45
31
|
// Utilities (ID generators and path helpers)
|
|
46
32
|
export {
|
|
47
|
-
|
|
48
|
-
generateTaskId,
|
|
33
|
+
GLOBAL_STORAGE,
|
|
49
34
|
generateFeatureId,
|
|
50
35
|
generateIdeaId,
|
|
51
|
-
generateShipId,
|
|
52
36
|
generateSessionId,
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
generateShipId,
|
|
38
|
+
generateTaskId,
|
|
39
|
+
generateUUID,
|
|
40
|
+
getProjectPath,
|
|
55
41
|
} from './schemas'
|
|
42
|
+
// Shipped items
|
|
43
|
+
export * from './shipped'
|
|
44
|
+
// State (current task + queue)
|
|
45
|
+
export * from './state'
|
package/core/schemas/issues.ts
CHANGED
|
@@ -14,7 +14,14 @@ import { z } from 'zod'
|
|
|
14
14
|
// =============================================================================
|
|
15
15
|
|
|
16
16
|
export const IssueProviderSchema = z.enum(['linear', 'jira', 'github', 'monday', 'asana', 'none'])
|
|
17
|
-
export const IssueStatusSchema = z.enum([
|
|
17
|
+
export const IssueStatusSchema = z.enum([
|
|
18
|
+
'backlog',
|
|
19
|
+
'todo',
|
|
20
|
+
'in_progress',
|
|
21
|
+
'in_review',
|
|
22
|
+
'done',
|
|
23
|
+
'cancelled',
|
|
24
|
+
])
|
|
18
25
|
export const IssuePrioritySchema = z.enum(['none', 'urgent', 'high', 'medium', 'low'])
|
|
19
26
|
export const IssueTypeSchema = z.enum(['feature', 'bug', 'improvement', 'task', 'chore', 'epic'])
|
|
20
27
|
|
|
@@ -27,8 +34,8 @@ export const IssueTypeSchema = z.enum(['feature', 'bug', 'improvement', 'task',
|
|
|
27
34
|
*/
|
|
28
35
|
export const CachedIssueSchema = z.object({
|
|
29
36
|
// Core identifiers
|
|
30
|
-
id: z.string(),
|
|
31
|
-
identifier: z.string(),
|
|
37
|
+
id: z.string(), // Provider UUID
|
|
38
|
+
identifier: z.string(), // Human-readable ID (e.g., "PRJ-123")
|
|
32
39
|
|
|
33
40
|
// Issue content
|
|
34
41
|
title: z.string(),
|
|
@@ -40,27 +47,33 @@ export const CachedIssueSchema = z.object({
|
|
|
40
47
|
type: IssueTypeSchema.optional(),
|
|
41
48
|
|
|
42
49
|
// Metadata
|
|
43
|
-
assignee: z
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
assignee: z
|
|
51
|
+
.object({
|
|
52
|
+
id: z.string(),
|
|
53
|
+
name: z.string(),
|
|
54
|
+
email: z.string().optional(),
|
|
55
|
+
})
|
|
56
|
+
.optional(),
|
|
48
57
|
labels: z.array(z.string()).default([]),
|
|
49
|
-
team: z
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
team: z
|
|
59
|
+
.object({
|
|
60
|
+
id: z.string(),
|
|
61
|
+
name: z.string(),
|
|
62
|
+
key: z.string().optional(),
|
|
63
|
+
})
|
|
64
|
+
.optional(),
|
|
65
|
+
project: z
|
|
66
|
+
.object({
|
|
67
|
+
id: z.string(),
|
|
68
|
+
name: z.string(),
|
|
69
|
+
})
|
|
70
|
+
.optional(),
|
|
58
71
|
|
|
59
72
|
// URLs and timestamps
|
|
60
73
|
url: z.string(),
|
|
61
|
-
createdAt: z.string(),
|
|
62
|
-
updatedAt: z.string(),
|
|
63
|
-
fetchedAt: z.string(),
|
|
74
|
+
createdAt: z.string(), // ISO8601 from provider
|
|
75
|
+
updatedAt: z.string(), // ISO8601 from provider
|
|
76
|
+
fetchedAt: z.string(), // ISO8601 when we cached it
|
|
64
77
|
})
|
|
65
78
|
|
|
66
79
|
// =============================================================================
|
|
@@ -76,7 +89,7 @@ export const IssuesJsonSchema = z.object({
|
|
|
76
89
|
provider: IssueProviderSchema,
|
|
77
90
|
|
|
78
91
|
// Sync metadata
|
|
79
|
-
lastSync: z.string(),
|
|
92
|
+
lastSync: z.string(), // ISO8601 of last full sync
|
|
80
93
|
staleAfter: z.number().default(1800000), // 30 minutes in ms
|
|
81
94
|
|
|
82
95
|
// Issues map: identifier -> issue
|
|
@@ -91,10 +104,12 @@ export const SyncResultSchema = z.object({
|
|
|
91
104
|
provider: IssueProviderSchema,
|
|
92
105
|
fetched: z.number(),
|
|
93
106
|
updated: z.number(),
|
|
94
|
-
errors: z.array(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
107
|
+
errors: z.array(
|
|
108
|
+
z.object({
|
|
109
|
+
issueId: z.string(),
|
|
110
|
+
error: z.string(),
|
|
111
|
+
})
|
|
112
|
+
),
|
|
98
113
|
timestamp: z.string(),
|
|
99
114
|
})
|
|
100
115
|
|