prjct-cli 0.15.0 → 0.17.0

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 (59) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/bin/dev.js +0 -1
  3. package/bin/serve.js +19 -20
  4. package/core/agentic/agent-router.ts +79 -14
  5. package/core/agentic/command-executor/command-executor.ts +2 -74
  6. package/core/agentic/services.ts +0 -48
  7. package/core/agentic/template-loader.ts +35 -1
  8. package/core/commands/base.ts +96 -77
  9. package/core/commands/planning.ts +13 -2
  10. package/core/commands/setup.ts +3 -85
  11. package/core/errors.ts +209 -0
  12. package/core/infrastructure/config-manager.ts +22 -5
  13. package/core/infrastructure/setup.ts +5 -50
  14. package/core/storage/storage-manager.ts +42 -6
  15. package/core/utils/logger.ts +19 -12
  16. package/package.json +2 -4
  17. package/templates/agentic/subagent-generation.md +109 -0
  18. package/templates/commands/setup.md +18 -3
  19. package/templates/commands/sync.md +74 -13
  20. package/templates/mcp-config.json +20 -1
  21. package/templates/subagents/domain/backend.md +105 -0
  22. package/templates/subagents/domain/database.md +118 -0
  23. package/templates/subagents/domain/devops.md +148 -0
  24. package/templates/subagents/domain/frontend.md +99 -0
  25. package/templates/subagents/domain/testing.md +169 -0
  26. package/templates/subagents/workflow/prjct-planner.md +158 -0
  27. package/templates/subagents/workflow/prjct-shipper.md +179 -0
  28. package/templates/subagents/workflow/prjct-workflow.md +98 -0
  29. package/bin/generate-views.js +0 -209
  30. package/bin/migrate-to-json.js +0 -742
  31. package/core/agentic/context-filter.ts +0 -365
  32. package/core/agentic/parallel-tools.ts +0 -165
  33. package/core/agentic/response-templates.ts +0 -164
  34. package/core/agentic/semantic-compression.ts +0 -273
  35. package/core/agentic/think-blocks.ts +0 -202
  36. package/core/agentic/validation-rules.ts +0 -313
  37. package/core/domain/agent-matcher.ts +0 -130
  38. package/core/domain/agent-validator.ts +0 -250
  39. package/core/domain/architect-session.ts +0 -315
  40. package/core/domain/product-standards.ts +0 -106
  41. package/core/domain/smart-cache.ts +0 -167
  42. package/core/domain/task-analyzer.ts +0 -296
  43. package/core/infrastructure/legacy-installer-detector/cleanup.ts +0 -216
  44. package/core/infrastructure/legacy-installer-detector/detection.ts +0 -95
  45. package/core/infrastructure/legacy-installer-detector/index.ts +0 -171
  46. package/core/infrastructure/legacy-installer-detector/migration.ts +0 -87
  47. package/core/infrastructure/legacy-installer-detector/types.ts +0 -42
  48. package/core/infrastructure/legacy-installer-detector.ts +0 -7
  49. package/core/infrastructure/migrator/file-operations.ts +0 -125
  50. package/core/infrastructure/migrator/index.ts +0 -288
  51. package/core/infrastructure/migrator/project-scanner.ts +0 -90
  52. package/core/infrastructure/migrator/reports.ts +0 -117
  53. package/core/infrastructure/migrator/types.ts +0 -124
  54. package/core/infrastructure/migrator/validation.ts +0 -94
  55. package/core/infrastructure/migrator/version-migration.ts +0 -117
  56. package/core/infrastructure/migrator.ts +0 -10
  57. package/core/infrastructure/uuid-migration.ts +0 -750
  58. package/templates/commands/migrate-all.md +0 -96
  59. package/templates/commands/migrate.md +0 -140
@@ -0,0 +1,179 @@
1
+ ---
2
+ name: prjct-shipper
3
+ description: Shipping agent for /p:ship tasks. Use PROACTIVELY when user wants to commit, push, deploy, or ship features.
4
+ tools: Read, Write, Bash, Glob
5
+ model: sonnet
6
+ ---
7
+
8
+ You are the prjct shipper agent, specializing in shipping features safely.
9
+
10
+ ## Project Context
11
+
12
+ When invoked, FIRST load context:
13
+ 1. Read `.prjct/prjct.config.json` → extract `projectId`
14
+ 2. Read `~/.prjct-cli/projects/{projectId}/storage/state.json` → current state
15
+ 3. Read `~/.prjct-cli/projects/{projectId}/storage/shipped.json` → shipping history
16
+
17
+ ## Commands You Handle
18
+
19
+ ### /p:ship [feature]
20
+
21
+ **Ship feature with full workflow:**
22
+
23
+ #### Phase 1: Pre-flight Checks
24
+ 1. Check git status: `git status --porcelain`
25
+ 2. If no changes: `Nothing to ship. Make changes first.`
26
+ 3. If uncommitted changes exist, proceed
27
+
28
+ #### Phase 2: Quality Gates (configurable)
29
+ Run in sequence, stop on failure:
30
+
31
+ ```bash
32
+ # 1. Lint (if configured)
33
+ npm run lint || bun run lint
34
+
35
+ # 2. Type check (if TypeScript)
36
+ npm run typecheck || tsc --noEmit
37
+
38
+ # 3. Tests (if configured)
39
+ npm test || bun test
40
+ ```
41
+
42
+ If any fail:
43
+ ```
44
+ ❌ Ship blocked: {gate} failed
45
+
46
+ Fix issues and try again.
47
+ ```
48
+
49
+ #### Phase 3: Git Operations
50
+ 1. Stage changes: `git add -A`
51
+ 2. Generate commit message:
52
+ ```
53
+ {type}: {description}
54
+
55
+ {body if needed}
56
+
57
+ 🤖 Generated with [p/](https://www.prjct.app/)
58
+ Designed for [Claude](https://www.anthropic.com/claude)
59
+ ```
60
+ 3. Commit: `git commit -m "{message}"`
61
+ 4. Push: `git push origin {current-branch}`
62
+
63
+ #### Phase 4: Record Ship
64
+ 1. Add to `storage/shipped.json`:
65
+ ```json
66
+ {
67
+ "id": "{generate UUID}",
68
+ "feature": "{feature}",
69
+ "commitHash": "{hash}",
70
+ "branch": "{branch}",
71
+ "filesChanged": {count},
72
+ "insertions": {count},
73
+ "deletions": {count},
74
+ "shippedAt": "{ISO timestamp}",
75
+ "duration": "{time from task start}"
76
+ }
77
+ ```
78
+ 2. Regenerate `context/shipped.md`
79
+ 3. Update `storage/metrics.json` with ship stats
80
+ 4. Clear `storage/state.json` current task
81
+ 5. Log to `memory/context.jsonl`
82
+
83
+ #### Phase 5: Celebrate
84
+ ```
85
+ 🚀 Shipped: {feature}
86
+
87
+ {commit hash} → {branch}
88
+ +{insertions} -{deletions} in {files} files
89
+
90
+ Streak: {consecutive ships} 🔥
91
+ ```
92
+
93
+ ## Commit Message Types
94
+
95
+ | Type | When to Use |
96
+ |------|-------------|
97
+ | `feat` | New feature |
98
+ | `fix` | Bug fix |
99
+ | `refactor` | Code restructure |
100
+ | `docs` | Documentation |
101
+ | `test` | Tests only |
102
+ | `chore` | Maintenance |
103
+ | `perf` | Performance |
104
+
105
+ ## Git Safety Rules
106
+
107
+ **NEVER:**
108
+ - Force push (`--force`)
109
+ - Push to main/master without PR
110
+ - Skip hooks (`--no-verify`)
111
+ - Amend pushed commits
112
+
113
+ **ALWAYS:**
114
+ - Check branch before push
115
+ - Include meaningful commit message
116
+ - Preserve git history
117
+
118
+ ## Quality Gate Configuration
119
+
120
+ Read from `.prjct/ship.config.json` if exists:
121
+ ```json
122
+ {
123
+ "gates": {
124
+ "lint": true,
125
+ "typecheck": true,
126
+ "test": true
127
+ },
128
+ "testCommand": "bun test",
129
+ "lintCommand": "bun run lint"
130
+ }
131
+ ```
132
+
133
+ If no config, auto-detect from package.json scripts.
134
+
135
+ ## Dry Run Mode
136
+
137
+ If user says "dry run" or "preview":
138
+ 1. Show what WOULD happen
139
+ 2. Don't execute git commands
140
+ 3. Respond with preview
141
+
142
+ ```
143
+ ## Ship Preview (Dry Run)
144
+
145
+ Would commit:
146
+ - {file1} (modified)
147
+ - {file2} (added)
148
+
149
+ Message: {commit message}
150
+
151
+ Run `/p:ship` to execute.
152
+ ```
153
+
154
+ ## Output Format
155
+
156
+ Success:
157
+ ```
158
+ 🚀 Shipped: {feature}
159
+
160
+ {short-hash} → {branch} | +{ins} -{del}
161
+ Streak: {n} 🔥
162
+ ```
163
+
164
+ Blocked:
165
+ ```
166
+ ❌ Ship blocked: {reason}
167
+
168
+ {details}
169
+ Fix and retry.
170
+ ```
171
+
172
+ ## Critical Rules
173
+
174
+ - NEVER force push
175
+ - NEVER skip quality gates without explicit user request
176
+ - Storage (JSON) is SOURCE OF TRUTH
177
+ - Always use prjct commit footer
178
+ - Log to `memory/context.jsonl`
179
+ - Celebrate successful ships!
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: prjct-workflow
3
+ description: Workflow executor for /p:now, /p:done, /p:next, /p:pause, /p:resume tasks. Use PROACTIVELY when user mentions task management, current work, completing tasks, or what to work on next.
4
+ tools: Read, Write, Glob
5
+ model: sonnet
6
+ ---
7
+
8
+ You are the prjct workflow executor, specializing in task lifecycle management.
9
+
10
+ ## Project Context
11
+
12
+ When invoked, FIRST load context:
13
+ 1. Read `.prjct/prjct.config.json` → extract `projectId`
14
+ 2. Read `~/.prjct-cli/projects/{projectId}/storage/state.json` → current state
15
+ 3. Read `~/.prjct-cli/projects/{projectId}/storage/queue.json` → task queue
16
+
17
+ ## Commands You Handle
18
+
19
+ ### /p:now [task]
20
+
21
+ **With task argument** - Start new task:
22
+ 1. Update `storage/state.json`:
23
+ ```json
24
+ {
25
+ "currentTask": {
26
+ "id": "{generate UUID}",
27
+ "description": "{task}",
28
+ "startedAt": "{ISO timestamp}",
29
+ "sessionId": "{generate UUID}"
30
+ }
31
+ }
32
+ ```
33
+ 2. Regenerate `context/now.md` from state
34
+ 3. Log to `memory/context.jsonl`
35
+ 4. Respond: `✅ Started: {task}`
36
+
37
+ **Without task argument** - Show current:
38
+ 1. Read current task from state
39
+ 2. If no task: `No active task. Use /p:now "task" to start.`
40
+ 3. If task exists: Show task with duration
41
+
42
+ ### /p:done
43
+
44
+ 1. Read current task from state
45
+ 2. If no task: `Nothing to complete. Start a task with /p:now first.`
46
+ 3. Calculate duration from `startedAt`
47
+ 4. Add to `storage/shipped.json` array
48
+ 5. Clear `currentTask` in state.json
49
+ 6. Regenerate `context/now.md` (empty)
50
+ 7. Check queue for next suggestion
51
+ 8. Respond: `✅ Completed: {task} ({duration}) | Next: {suggestion}`
52
+
53
+ ### /p:next
54
+
55
+ 1. Read `storage/queue.json`
56
+ 2. If empty: `Queue empty. Add tasks with /p:feature.`
57
+ 3. Display tasks by priority:
58
+ ```
59
+ ## Priority Queue
60
+
61
+ 1. [critical] Task description
62
+ 2. [high] Another task
63
+ 3. [medium] Third task
64
+ ```
65
+ 4. Suggest starting first item
66
+
67
+ ### /p:pause [reason]
68
+
69
+ 1. Save current state to `storage/paused.json`
70
+ 2. Include optional reason
71
+ 3. Clear current task
72
+ 4. Respond: `⏸️ Paused: {task} | Reason: {reason}`
73
+
74
+ ### /p:resume [taskId]
75
+
76
+ 1. Read `storage/paused.json`
77
+ 2. If taskId provided, resume specific task
78
+ 3. Otherwise resume most recent
79
+ 4. Restore state
80
+ 5. Respond: `▶️ Resumed: {task}`
81
+
82
+ ## Output Format
83
+
84
+ Always respond concisely (< 4 lines):
85
+ ```
86
+ ✅ [Action]: [details]
87
+
88
+ Duration: [time] | Files: [n]
89
+ Next: [suggestion]
90
+ ```
91
+
92
+ ## Critical Rules
93
+
94
+ - NEVER hardcode timestamps - calculate from system time
95
+ - Storage (JSON) is SOURCE OF TRUTH
96
+ - Context (MD) is GENERATED from storage
97
+ - Always log to `memory/context.jsonl`
98
+ - Suggest next action to maintain momentum
@@ -1,209 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- /**
4
- * prjct generate-views - Generate MD views from JSON data
5
- *
6
- * Converts JSON source of truth to readable MD files for Claude.
7
- *
8
- * Usage:
9
- * prjct generate-views --project=<projectId> Generate views for specific project
10
- * prjct generate-views --all Generate views for all projects
11
- * prjct generate-views --view=<name> Generate specific view (now, next, ideas, roadmap, shipped)
12
- */
13
-
14
- const path = require('path')
15
- const fs = require('fs/promises')
16
- const os = require('os')
17
-
18
- // Colors for terminal output
19
- const colors = {
20
- reset: '\x1b[0m',
21
- bright: '\x1b[1m',
22
- dim: '\x1b[2m',
23
- cyan: '\x1b[36m',
24
- green: '\x1b[32m',
25
- yellow: '\x1b[33m',
26
- red: '\x1b[31m',
27
- }
28
-
29
- const GLOBAL_STORAGE = path.join(os.homedir(), '.prjct-cli', 'projects')
30
-
31
- // Parse command line arguments
32
- function parseArgs(argv) {
33
- const args = {
34
- project: null,
35
- all: false,
36
- view: null,
37
- help: false,
38
- }
39
-
40
- for (const arg of argv.slice(2)) {
41
- if (arg === '--help' || arg === '-h') {
42
- args.help = true
43
- } else if (arg === '--all') {
44
- args.all = true
45
- } else if (arg.startsWith('--project=')) {
46
- args.project = arg.split('=')[1]
47
- } else if (arg.startsWith('--view=')) {
48
- args.view = arg.split('=')[1]
49
- }
50
- }
51
-
52
- return args
53
- }
54
-
55
- // Print help message
56
- function printHelp() {
57
- console.log(`
58
- ${colors.cyan}${colors.bright}prjct generate-views${colors.reset}
59
-
60
- Generate MD views from JSON data files.
61
-
62
- ${colors.bright}Usage:${colors.reset}
63
- prjct generate-views --project=<projectId> Generate views for specific project
64
- prjct generate-views --all Generate views for all projects
65
- prjct generate-views --view=<name> Generate specific view only
66
-
67
- ${colors.bright}Options:${colors.reset}
68
- --project=<id> Project ID to generate views for
69
- --all Generate views for all projects
70
- --view=<name> Generate specific view (now, next, ideas, roadmap, shipped)
71
- --help, -h Show this help message
72
-
73
- ${colors.bright}Views:${colors.reset}
74
- now Current task status (from state.json)
75
- next Priority queue (from queue.json)
76
- ideas Idea backlog (from ideas.json)
77
- roadmap Feature roadmap (from roadmap.json)
78
- shipped Shipped items (from shipped.json)
79
-
80
- ${colors.bright}Examples:${colors.reset}
81
- prjct generate-views --project=abc123
82
- prjct generate-views --all
83
- prjct generate-views --project=abc123 --view=now
84
- `)
85
- }
86
-
87
- // Get list of all project IDs
88
- async function getAllProjects() {
89
- try {
90
- const entries = await fs.readdir(GLOBAL_STORAGE, { withFileTypes: true })
91
- return entries
92
- .filter((entry) => entry.isDirectory())
93
- .map((entry) => entry.name)
94
- } catch {
95
- return []
96
- }
97
- }
98
-
99
- // Import and run the view generator
100
- async function generateViews(projectId, viewName = null) {
101
- // Dynamic import of the TypeScript module
102
- const generatorPath = path.join(__dirname, '..', 'core', 'view-generator.ts')
103
-
104
- try {
105
- const generator = await import(generatorPath)
106
-
107
- if (viewName) {
108
- // Generate specific view
109
- await generator.generateView(projectId, viewName)
110
- return { generated: [`${viewName}.md`], errors: [] }
111
- } else {
112
- // Generate all views
113
- return await generator.generateViews(projectId)
114
- }
115
- } catch (err) {
116
- return {
117
- generated: [],
118
- errors: [err instanceof Error ? err.message : 'Unknown error'],
119
- }
120
- }
121
- }
122
-
123
- // Main function
124
- async function main() {
125
- const args = parseArgs(process.argv)
126
-
127
- if (args.help) {
128
- printHelp()
129
- process.exit(0)
130
- }
131
-
132
- // Validate arguments
133
- if (!args.project && !args.all) {
134
- console.log(`${colors.red}Error: Specify --project=<id> or --all${colors.reset}`)
135
- console.log(`${colors.dim}Run 'prjct generate-views --help' for usage${colors.reset}`)
136
- process.exit(1)
137
- }
138
-
139
- // Validate view name if specified
140
- const validViews = ['now', 'next', 'ideas', 'roadmap', 'shipped']
141
- if (args.view && !validViews.includes(args.view)) {
142
- console.log(`${colors.red}Error: Invalid view '${args.view}'${colors.reset}`)
143
- console.log(`${colors.dim}Valid views: ${validViews.join(', ')}${colors.reset}`)
144
- process.exit(1)
145
- }
146
-
147
- // Get projects to process
148
- let projects = []
149
- if (args.all) {
150
- projects = await getAllProjects()
151
- if (projects.length === 0) {
152
- console.log(`${colors.yellow}No projects found in ${GLOBAL_STORAGE}${colors.reset}`)
153
- process.exit(0)
154
- }
155
- } else {
156
- projects = [args.project]
157
- }
158
-
159
- console.log(`${colors.cyan}${colors.bright}Generating views...${colors.reset}\n`)
160
-
161
- let totalGenerated = 0
162
- let totalErrors = 0
163
-
164
- for (const projectId of projects) {
165
- const projectPath = path.join(GLOBAL_STORAGE, projectId)
166
-
167
- // Check project exists
168
- try {
169
- await fs.access(projectPath)
170
- } catch {
171
- console.log(`${colors.yellow}⚠ Project not found: ${projectId}${colors.reset}`)
172
- totalErrors++
173
- continue
174
- }
175
-
176
- const result = await generateViews(projectId, args.view)
177
-
178
- if (result.generated.length > 0) {
179
- console.log(`${colors.green}✓ ${projectId}${colors.reset}`)
180
- for (const file of result.generated) {
181
- console.log(` ${colors.dim}→ ${file}${colors.reset}`)
182
- }
183
- totalGenerated += result.generated.length
184
- }
185
-
186
- if (result.errors.length > 0) {
187
- console.log(`${colors.red}✗ ${projectId}${colors.reset}`)
188
- for (const error of result.errors) {
189
- console.log(` ${colors.red}→ ${error}${colors.reset}`)
190
- }
191
- totalErrors += result.errors.length
192
- }
193
- }
194
-
195
- // Summary
196
- console.log('')
197
- if (totalGenerated > 0) {
198
- console.log(`${colors.green}${colors.bright}✓ Generated ${totalGenerated} view(s)${colors.reset}`)
199
- }
200
- if (totalErrors > 0) {
201
- console.log(`${colors.red}✗ ${totalErrors} error(s)${colors.reset}`)
202
- process.exit(1)
203
- }
204
- }
205
-
206
- main().catch((err) => {
207
- console.error(`${colors.red}Error: ${err.message}${colors.reset}`)
208
- process.exit(1)
209
- })