prjct-cli 0.28.1 → 0.28.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 +93 -0
- package/core/agentic/index.ts +11 -1
- package/core/agentic/prompt-builder.ts +2 -2
- package/core/agentic/token-estimator.ts +264 -0
- package/core/commands/command-data.ts +0 -33
- package/core/commands/commands.ts +4 -12
- package/core/commands/registry.ts +0 -37
- package/core/index.ts +0 -2
- package/core/infrastructure/setup.ts +28 -0
- package/core/infrastructure/slash-command-registry.ts +176 -0
- package/core/types/config.ts +1 -1
- package/core/types/index.ts +0 -2
- package/core/types/integrations.ts +22 -40
- package/core/types/storage.ts +0 -8
- package/core/types/task.ts +0 -4
- package/dist/bin/prjct.mjs +3 -82
- package/package.json +1 -1
- package/templates/agentic/subagent-generation.md +241 -81
- package/templates/commands/init.md +1 -44
- package/templates/commands/ship.md +106 -81
- package/templates/commands/sync.md +154 -402
- package/templates/commands/task.md +14 -31
- package/templates/global/CLAUDE.md +166 -35
- package/templates/guides/agent-generation.md +164 -0
- package/templates/guides/integrations.md +149 -0
- package/templates/mcp-config.json +23 -46
- package/templates/shared/validation.md +75 -0
- package/CLAUDE.md +0 -170
- package/core/integrations/notion/client.ts +0 -413
- package/core/integrations/notion/index.ts +0 -46
- package/core/integrations/notion/setup.ts +0 -235
- package/core/integrations/notion/sync.ts +0 -818
- package/core/integrations/notion/templates.ts +0 -246
- package/core/plugin/builtin/notion.ts +0 -178
- package/templates/agentic/agents/uxui.md +0 -218
- package/templates/commands/feature.md +0 -46
- package/templates/commands/now.md +0 -53
- package/templates/skills/notion-push.md +0 -116
- package/templates/skills/notion-setup.md +0 -199
- package/templates/skills/notion-sync.md +0 -290
- package/templates/subagents/domain/backend.md +0 -106
- package/templates/subagents/domain/database.md +0 -118
- package/templates/subagents/domain/devops.md +0 -149
- package/templates/subagents/domain/frontend.md +0 -100
- package/templates/subagents/domain/testing.md +0 -166
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.28.3] - 2026-01-11
|
|
4
|
+
|
|
5
|
+
### Feature: Claude Code Synergy Optimization
|
|
6
|
+
|
|
7
|
+
Major improvements to maximize prjct + Claude Code integration efficiency.
|
|
8
|
+
|
|
9
|
+
**Skill Auto-Invocation (Phase 4 of /p:task):**
|
|
10
|
+
- Skills are now automatically invoked when loading agents
|
|
11
|
+
- Agent frontmatter `skills: [skill-name]` triggers `Skill("skill-name")`
|
|
12
|
+
- Example: Loading `frontend.md` auto-activates `/frontend-design`
|
|
13
|
+
|
|
14
|
+
**MCP Auto-Usage:**
|
|
15
|
+
- Agents with `mcp: [context7]` auto-query documentation during tasks
|
|
16
|
+
- Per-project MCP config at `{globalPath}/config/mcp-servers.json`
|
|
17
|
+
- Seamless library documentation lookup during implementation
|
|
18
|
+
|
|
19
|
+
**Think Blocks for Destructive Commands:**
|
|
20
|
+
- `/p:ship` now includes mandatory `<think>` block
|
|
21
|
+
- Pre-ship verification checklist (completeness, quality, git state)
|
|
22
|
+
- Prevents shipping incomplete or broken code
|
|
23
|
+
|
|
24
|
+
**Agent Auto-Refresh in /p:sync:**
|
|
25
|
+
- Detects when dependencies change (package.json, etc.)
|
|
26
|
+
- Regenerates stale agents (>7 days old)
|
|
27
|
+
- Versions previous agents as `.backup` files
|
|
28
|
+
- Logs refresh events to memory
|
|
29
|
+
|
|
30
|
+
**Slash Command Registration:**
|
|
31
|
+
- New `slash-commands.json` config for Claude Code integration
|
|
32
|
+
- Enables command discovery and validation
|
|
33
|
+
- Path: `{globalPath}/config/slash-commands.json`
|
|
34
|
+
|
|
35
|
+
**Token Budget Analysis:**
|
|
36
|
+
- Estimates context token usage during sync
|
|
37
|
+
- Warns if approaching 80% of budget (160k tokens)
|
|
38
|
+
- Auto-summarizes large agents if needed
|
|
39
|
+
|
|
40
|
+
**Client Migration on Update:**
|
|
41
|
+
- Setup now creates missing config files for existing projects
|
|
42
|
+
- `slash-commands.json` auto-created for existing installations
|
|
43
|
+
- Seamless upgrade experience for npm update users
|
|
44
|
+
|
|
45
|
+
**New TypeScript Modules:**
|
|
46
|
+
- `core/infrastructure/slash-command-registry.ts` - Command validation
|
|
47
|
+
- `core/agentic/token-estimator.ts` - Token budget estimation
|
|
48
|
+
|
|
49
|
+
**Template Context Optimization:**
|
|
50
|
+
- Reduced main templates from 3,197 to 2,214 lines (-31%)
|
|
51
|
+
- `sync.md`: 1,602 → 835 lines (-48%)
|
|
52
|
+
- `global/CLAUDE.md`: 429 → 363 lines (-15%)
|
|
53
|
+
- `task.md`: 397 → 336 lines (-15%)
|
|
54
|
+
- `ship.md`: 769 → 680 lines (-12%)
|
|
55
|
+
- New `templates/guides/` for on-demand documentation
|
|
56
|
+
- New `templates/shared/validation.md` for reusable validation
|
|
57
|
+
|
|
58
|
+
**Files Removed (Agentic Generation):**
|
|
59
|
+
- Deleted hardcoded domain agents from `templates/subagents/domain/`
|
|
60
|
+
- Deleted `.mcp.json` (now generated per-project)
|
|
61
|
+
- Deleted `CLAUDE.md` from root (moved to templates/global/)
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## [0.28.2] - 2026-01-10
|
|
66
|
+
|
|
67
|
+
### Feature: Agent Mentions and Major Cleanup
|
|
68
|
+
|
|
69
|
+
**Agent Mentions (p.agent.{name}):**
|
|
70
|
+
- New `agentId` field in agent frontmatter for identification
|
|
71
|
+
- Users can invoke agents in prompts: `p.agent.backend help me...`
|
|
72
|
+
- Format: `p.agent.workflow`, `p.agent.planner`, `p.agent.frontend`, etc.
|
|
73
|
+
|
|
74
|
+
**Deprecated Commands Removed:**
|
|
75
|
+
- `/p:now` - Use `/p:task` instead
|
|
76
|
+
- `/p:feature` - Use `/p:task` instead
|
|
77
|
+
- `/p:work` - Use `/p:task` instead
|
|
78
|
+
|
|
79
|
+
**Notion Integration Removed:**
|
|
80
|
+
- Removed entire `core/integrations/notion/` directory
|
|
81
|
+
- Removed Notion skills and MCP config
|
|
82
|
+
- Cleaned up type references
|
|
83
|
+
|
|
84
|
+
**Code Cleanup:**
|
|
85
|
+
- Removed `executeWithoutProject()` deprecated method
|
|
86
|
+
- Cleaned dead code in prompt-builder arrays
|
|
87
|
+
- Removed ARCHITECTURE.md (outdated)
|
|
88
|
+
|
|
89
|
+
**Ship Template Enhancement:**
|
|
90
|
+
- Version bump now REQUIRED before PR creation
|
|
91
|
+
- CHANGELOG.md update now REQUIRED before PR creation
|
|
92
|
+
- Better categorization of changes (Added/Fixed/Changed)
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
3
96
|
## [0.28.1] - 2026-01-10
|
|
4
97
|
|
|
5
98
|
### Feature: @ Agent Mentions
|
package/core/agentic/index.ts
CHANGED
|
@@ -90,9 +90,19 @@ export { default as toolRegistry } from './tool-registry'
|
|
|
90
90
|
export { default as templateLoader } from './template-loader'
|
|
91
91
|
|
|
92
92
|
// ============ Utilities ============
|
|
93
|
-
// Chain of thought, services
|
|
93
|
+
// Chain of thought, services, token estimation
|
|
94
94
|
export { default as chainOfThought } from './chain-of-thought'
|
|
95
95
|
export { default as services } from './services'
|
|
96
|
+
export {
|
|
97
|
+
default as tokenEstimator,
|
|
98
|
+
estimateTokens,
|
|
99
|
+
getTokenBudget,
|
|
100
|
+
estimateContext,
|
|
101
|
+
filterContext,
|
|
102
|
+
summarizeForTokens,
|
|
103
|
+
createContextSections,
|
|
104
|
+
formatEstimate,
|
|
105
|
+
} from './token-estimator'
|
|
96
106
|
|
|
97
107
|
// ============ Types ============
|
|
98
108
|
// All types re-exported from ../types (canonical source)
|
|
@@ -283,7 +283,7 @@ class PromptBuilder {
|
|
|
283
283
|
|
|
284
284
|
// Agent assignment (CONDITIONAL - only for code-modifying commands)
|
|
285
285
|
const commandName = template.frontmatter?.name?.replace('p:', '') || ''
|
|
286
|
-
const agentCommands = ['
|
|
286
|
+
const agentCommands = ['task', 'design', 'fix', 'bug', 'test', 'cleanup', 'spec']
|
|
287
287
|
const needsAgent = agentCommands.includes(commandName)
|
|
288
288
|
|
|
289
289
|
if (agent && needsAgent) {
|
|
@@ -332,7 +332,7 @@ class PromptBuilder {
|
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
// OPTIMIZED: Only include patterns for code-modifying commands
|
|
335
|
-
const codeCommands = ['
|
|
335
|
+
const codeCommands = ['task', 'design', 'cleanup', 'fix', 'bug', 'test', 'init', 'spec']
|
|
336
336
|
const needsPatterns = codeCommands.includes(commandName)
|
|
337
337
|
|
|
338
338
|
// Include code patterns analysis for code-modifying commands
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Budget Estimator
|
|
3
|
+
* Estimates token usage and provides context filtering for large projects.
|
|
4
|
+
*
|
|
5
|
+
* This prevents context overflow by:
|
|
6
|
+
* - Estimating token count before sending to Claude
|
|
7
|
+
* - Prioritizing critical context over nice-to-have
|
|
8
|
+
* - Truncating or summarizing when needed
|
|
9
|
+
*
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface TokenEstimate {
|
|
14
|
+
total: number
|
|
15
|
+
breakdown: {
|
|
16
|
+
projectContext: number
|
|
17
|
+
agentContext: number
|
|
18
|
+
skillContext: number
|
|
19
|
+
userPrompt: number
|
|
20
|
+
systemPrompt: number
|
|
21
|
+
}
|
|
22
|
+
withinBudget: boolean
|
|
23
|
+
recommendations: string[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ContextSection {
|
|
27
|
+
name: string
|
|
28
|
+
content: string
|
|
29
|
+
priority: 'critical' | 'high' | 'medium' | 'low'
|
|
30
|
+
tokens: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Approximate tokens per character ratio
|
|
35
|
+
* Claude uses ~4 characters per token on average for English text
|
|
36
|
+
* Code tends to be slightly more efficient (~3.5 chars/token)
|
|
37
|
+
*/
|
|
38
|
+
const CHARS_PER_TOKEN = 3.8
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Default token budgets by model
|
|
42
|
+
*/
|
|
43
|
+
const TOKEN_BUDGETS = {
|
|
44
|
+
'claude-3-opus': 200000,
|
|
45
|
+
'claude-3-sonnet': 200000,
|
|
46
|
+
'claude-3-haiku': 200000,
|
|
47
|
+
'claude-3.5-sonnet': 200000,
|
|
48
|
+
'claude-opus-4': 200000,
|
|
49
|
+
default: 100000, // Conservative default
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Estimate tokens from string content
|
|
54
|
+
*/
|
|
55
|
+
export function estimateTokens(content: string): number {
|
|
56
|
+
if (!content) return 0
|
|
57
|
+
return Math.ceil(content.length / CHARS_PER_TOKEN)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get token budget for a model
|
|
62
|
+
*/
|
|
63
|
+
export function getTokenBudget(model: string = 'default'): number {
|
|
64
|
+
return TOKEN_BUDGETS[model as keyof typeof TOKEN_BUDGETS] || TOKEN_BUDGETS.default
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Estimate total context tokens
|
|
69
|
+
*/
|
|
70
|
+
export function estimateContext(sections: ContextSection[]): TokenEstimate {
|
|
71
|
+
const breakdown = {
|
|
72
|
+
projectContext: 0,
|
|
73
|
+
agentContext: 0,
|
|
74
|
+
skillContext: 0,
|
|
75
|
+
userPrompt: 0,
|
|
76
|
+
systemPrompt: 0,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
let total = 0
|
|
80
|
+
|
|
81
|
+
for (const section of sections) {
|
|
82
|
+
const tokens = estimateTokens(section.content)
|
|
83
|
+
section.tokens = tokens
|
|
84
|
+
total += tokens
|
|
85
|
+
|
|
86
|
+
// Categorize for breakdown
|
|
87
|
+
if (section.name.includes('agent')) {
|
|
88
|
+
breakdown.agentContext += tokens
|
|
89
|
+
} else if (section.name.includes('skill')) {
|
|
90
|
+
breakdown.skillContext += tokens
|
|
91
|
+
} else if (section.name.includes('user') || section.name.includes('prompt')) {
|
|
92
|
+
breakdown.userPrompt += tokens
|
|
93
|
+
} else if (section.name.includes('system')) {
|
|
94
|
+
breakdown.systemPrompt += tokens
|
|
95
|
+
} else {
|
|
96
|
+
breakdown.projectContext += tokens
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const budget = getTokenBudget()
|
|
101
|
+
const withinBudget = total < budget * 0.8 // Leave 20% buffer for response
|
|
102
|
+
|
|
103
|
+
const recommendations: string[] = []
|
|
104
|
+
|
|
105
|
+
if (!withinBudget) {
|
|
106
|
+
recommendations.push(`Context exceeds safe limit (${total} tokens vs ${Math.floor(budget * 0.8)} budget)`)
|
|
107
|
+
|
|
108
|
+
// Find sections that can be reduced
|
|
109
|
+
const lowPriority = sections.filter(s => s.priority === 'low')
|
|
110
|
+
if (lowPriority.length > 0) {
|
|
111
|
+
const lowTokens = lowPriority.reduce((sum, s) => sum + s.tokens, 0)
|
|
112
|
+
recommendations.push(`Remove low-priority sections to save ~${lowTokens} tokens`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const mediumPriority = sections.filter(s => s.priority === 'medium')
|
|
116
|
+
if (mediumPriority.length > 0) {
|
|
117
|
+
const medTokens = mediumPriority.reduce((sum, s) => sum + s.tokens, 0)
|
|
118
|
+
recommendations.push(`Consider summarizing medium-priority sections (~${medTokens} tokens)`)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
total,
|
|
124
|
+
breakdown,
|
|
125
|
+
withinBudget,
|
|
126
|
+
recommendations,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Filter context to fit within budget
|
|
132
|
+
*/
|
|
133
|
+
export function filterContext(
|
|
134
|
+
sections: ContextSection[],
|
|
135
|
+
maxTokens?: number
|
|
136
|
+
): { filtered: ContextSection[]; removed: string[]; totalTokens: number } {
|
|
137
|
+
const budget = maxTokens || getTokenBudget() * 0.8
|
|
138
|
+
|
|
139
|
+
// Sort by priority (critical first)
|
|
140
|
+
const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 }
|
|
141
|
+
const sorted = [...sections].sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority])
|
|
142
|
+
|
|
143
|
+
const filtered: ContextSection[] = []
|
|
144
|
+
const removed: string[] = []
|
|
145
|
+
let totalTokens = 0
|
|
146
|
+
|
|
147
|
+
for (const section of sorted) {
|
|
148
|
+
const sectionTokens = estimateTokens(section.content)
|
|
149
|
+
|
|
150
|
+
if (totalTokens + sectionTokens <= budget) {
|
|
151
|
+
filtered.push({ ...section, tokens: sectionTokens })
|
|
152
|
+
totalTokens += sectionTokens
|
|
153
|
+
} else if (section.priority === 'critical') {
|
|
154
|
+
// Critical sections are always included, even if over budget
|
|
155
|
+
filtered.push({ ...section, tokens: sectionTokens })
|
|
156
|
+
totalTokens += sectionTokens
|
|
157
|
+
} else {
|
|
158
|
+
removed.push(section.name)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return { filtered, removed, totalTokens }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Summarize content to reduce tokens
|
|
167
|
+
*/
|
|
168
|
+
export function summarizeForTokens(content: string, targetTokens: number): string {
|
|
169
|
+
const currentTokens = estimateTokens(content)
|
|
170
|
+
|
|
171
|
+
if (currentTokens <= targetTokens) {
|
|
172
|
+
return content
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Calculate target character count
|
|
176
|
+
const targetChars = targetTokens * CHARS_PER_TOKEN
|
|
177
|
+
|
|
178
|
+
// Split into lines and take priority lines
|
|
179
|
+
const lines = content.split('\n')
|
|
180
|
+
|
|
181
|
+
// Keep headers and first lines of sections
|
|
182
|
+
const priorityLines: string[] = []
|
|
183
|
+
let charCount = 0
|
|
184
|
+
|
|
185
|
+
for (const line of lines) {
|
|
186
|
+
const isHeader = line.startsWith('#') || line.startsWith('**')
|
|
187
|
+
const isImportant = line.includes('CRITICAL') || line.includes('IMPORTANT') || line.includes('TODO')
|
|
188
|
+
|
|
189
|
+
if (isHeader || isImportant) {
|
|
190
|
+
priorityLines.push(line)
|
|
191
|
+
charCount += line.length + 1
|
|
192
|
+
} else if (charCount < targetChars * 0.8) {
|
|
193
|
+
priorityLines.push(line)
|
|
194
|
+
charCount += line.length + 1
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (charCount >= targetChars) {
|
|
198
|
+
break
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (priorityLines.length < lines.length) {
|
|
203
|
+
priorityLines.push('')
|
|
204
|
+
priorityLines.push(`[... ${lines.length - priorityLines.length} lines truncated for context limit ...]`)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return priorityLines.join('\n')
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Create context sections from project state
|
|
212
|
+
*/
|
|
213
|
+
export function createContextSections(
|
|
214
|
+
projectContext: string,
|
|
215
|
+
agentContext: string,
|
|
216
|
+
skillContext: string,
|
|
217
|
+
userPrompt: string
|
|
218
|
+
): ContextSection[] {
|
|
219
|
+
return [
|
|
220
|
+
{ name: 'user-prompt', content: userPrompt, priority: 'critical', tokens: 0 },
|
|
221
|
+
{ name: 'agent-context', content: agentContext, priority: 'high', tokens: 0 },
|
|
222
|
+
{ name: 'project-context', content: projectContext, priority: 'medium', tokens: 0 },
|
|
223
|
+
{ name: 'skill-context', content: skillContext, priority: 'medium', tokens: 0 },
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Format token estimate for display
|
|
229
|
+
*/
|
|
230
|
+
export function formatEstimate(estimate: TokenEstimate): string {
|
|
231
|
+
const lines = [
|
|
232
|
+
'📊 Token Budget',
|
|
233
|
+
'',
|
|
234
|
+
`Total: ${estimate.total.toLocaleString()} tokens`,
|
|
235
|
+
'',
|
|
236
|
+
'Breakdown:',
|
|
237
|
+
` Project: ${estimate.breakdown.projectContext.toLocaleString()}`,
|
|
238
|
+
` Agents: ${estimate.breakdown.agentContext.toLocaleString()}`,
|
|
239
|
+
` Skills: ${estimate.breakdown.skillContext.toLocaleString()}`,
|
|
240
|
+
` Prompt: ${estimate.breakdown.userPrompt.toLocaleString()}`,
|
|
241
|
+
'',
|
|
242
|
+
`Status: ${estimate.withinBudget ? '✅ Within budget' : '⚠️ Over budget'}`,
|
|
243
|
+
]
|
|
244
|
+
|
|
245
|
+
if (estimate.recommendations.length > 0) {
|
|
246
|
+
lines.push('')
|
|
247
|
+
lines.push('Recommendations:')
|
|
248
|
+
for (const rec of estimate.recommendations) {
|
|
249
|
+
lines.push(` - ${rec}`)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return lines.join('\n')
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export default {
|
|
257
|
+
estimateTokens,
|
|
258
|
+
getTokenBudget,
|
|
259
|
+
estimateContext,
|
|
260
|
+
filterContext,
|
|
261
|
+
summarizeForTokens,
|
|
262
|
+
createContextSections,
|
|
263
|
+
formatEstimate,
|
|
264
|
+
}
|
|
@@ -62,17 +62,6 @@ export const COMMANDS: CommandMeta[] = [
|
|
|
62
62
|
requiresProject: true,
|
|
63
63
|
features: ['Agentic type classification', '7-phase workflow', 'Git branch management', 'Task breakdown'],
|
|
64
64
|
},
|
|
65
|
-
{
|
|
66
|
-
name: 'feature',
|
|
67
|
-
group: 'core',
|
|
68
|
-
description: 'DEPRECATED - Use /p:task instead',
|
|
69
|
-
usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
|
|
70
|
-
params: '<description>',
|
|
71
|
-
implemented: true,
|
|
72
|
-
hasTemplate: true,
|
|
73
|
-
requiresProject: true,
|
|
74
|
-
deprecated: true,
|
|
75
|
-
},
|
|
76
65
|
{
|
|
77
66
|
name: 'spec',
|
|
78
67
|
group: 'core',
|
|
@@ -83,28 +72,6 @@ export const COMMANDS: CommandMeta[] = [
|
|
|
83
72
|
hasTemplate: true,
|
|
84
73
|
requiresProject: true,
|
|
85
74
|
},
|
|
86
|
-
{
|
|
87
|
-
name: 'now',
|
|
88
|
-
group: 'core',
|
|
89
|
-
description: 'DEPRECATED - Use /p:task instead',
|
|
90
|
-
usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
|
|
91
|
-
params: '[task]',
|
|
92
|
-
implemented: true,
|
|
93
|
-
hasTemplate: true,
|
|
94
|
-
requiresProject: true,
|
|
95
|
-
deprecated: true,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: 'work',
|
|
99
|
-
group: 'core',
|
|
100
|
-
description: 'DEPRECATED - Use /p:task instead',
|
|
101
|
-
usage: { claude: '/p:task "<description>"', terminal: 'prjct task "<description>"' },
|
|
102
|
-
params: '[task]',
|
|
103
|
-
implemented: true,
|
|
104
|
-
hasTemplate: true,
|
|
105
|
-
requiresProject: true,
|
|
106
|
-
deprecated: true,
|
|
107
|
-
},
|
|
108
75
|
{
|
|
109
76
|
name: 'pause',
|
|
110
77
|
group: 'core',
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* MD-First Architecture - All state in Markdown files.
|
|
5
5
|
*
|
|
6
|
-
* COMMANDS (
|
|
7
|
-
* - Workflow (
|
|
8
|
-
* - Planning (
|
|
6
|
+
* COMMANDS (20 total):
|
|
7
|
+
* - Workflow (4): done, next, pause, resume
|
|
8
|
+
* - Planning (4): init, bug, idea, spec
|
|
9
9
|
* - Shipping (1): ship
|
|
10
10
|
* - Analytics (2): dash, help
|
|
11
|
-
* - Maintenance (
|
|
11
|
+
* - Maintenance (6): cleanup, design, recover, undo, redo, history
|
|
12
12
|
* - Analysis (2): analyze, sync
|
|
13
13
|
* - Setup (3): start, setup, migrateAll
|
|
14
14
|
*/
|
|
@@ -69,10 +69,6 @@ class PrjctCommands {
|
|
|
69
69
|
|
|
70
70
|
// ========== Workflow Commands ==========
|
|
71
71
|
|
|
72
|
-
async work(task: string | null = null, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
73
|
-
return this.workflow.now(task, projectPath)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
72
|
async done(projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
77
73
|
return this.workflow.done(projectPath)
|
|
78
74
|
}
|
|
@@ -95,10 +91,6 @@ class PrjctCommands {
|
|
|
95
91
|
return this.planning.init(idea, projectPath)
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
async feature(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
99
|
-
return this.planning.feature(description, projectPath)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
94
|
async bug(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
103
95
|
return this.planning.bug(description, projectPath)
|
|
104
96
|
}
|
|
@@ -388,43 +388,6 @@ export class CommandRegistry {
|
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
/**
|
|
392
|
-
* Execute without requiring project (for init, setup commands)
|
|
393
|
-
* @deprecated Use execute() - it auto-detects based on command metadata
|
|
394
|
-
*/
|
|
395
|
-
async executeWithoutProject<TParams = void>(
|
|
396
|
-
name: string,
|
|
397
|
-
params: TParams,
|
|
398
|
-
projectPath: string = process.cwd()
|
|
399
|
-
): Promise<CommandResult> {
|
|
400
|
-
const handler = this.handlers.get(name)
|
|
401
|
-
if (handler) {
|
|
402
|
-
const context: ExecutionContext = {
|
|
403
|
-
projectId: '',
|
|
404
|
-
projectPath,
|
|
405
|
-
globalPath: '',
|
|
406
|
-
timestamp: getTimestamp(),
|
|
407
|
-
}
|
|
408
|
-
return handler.execute(params, context)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const handlerFn = this.handlerFns.get(name)
|
|
412
|
-
if (handlerFn) {
|
|
413
|
-
const context: ExecutionContext = {
|
|
414
|
-
projectId: '',
|
|
415
|
-
projectPath,
|
|
416
|
-
globalPath: '',
|
|
417
|
-
timestamp: getTimestamp(),
|
|
418
|
-
}
|
|
419
|
-
return handlerFn(params, context)
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
return {
|
|
423
|
-
success: false,
|
|
424
|
-
error: `Command not found: ${name}`,
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
391
|
/**
|
|
429
392
|
* Clear all registrations (useful for testing)
|
|
430
393
|
*/
|
package/core/index.ts
CHANGED
|
@@ -97,14 +97,12 @@ async function main(): Promise<void> {
|
|
|
97
97
|
const param = parsedArgs.join(' ') || null
|
|
98
98
|
const standardCommands: Record<string, (p: string | null) => Promise<CommandResult>> = {
|
|
99
99
|
// Core workflow
|
|
100
|
-
work: (p) => commands.work(p),
|
|
101
100
|
done: () => commands.done(),
|
|
102
101
|
next: () => commands.next(),
|
|
103
102
|
pause: (p) => commands.pause(p || ''),
|
|
104
103
|
resume: (p) => commands.resume(p),
|
|
105
104
|
// Planning
|
|
106
105
|
init: (p) => commands.init(p),
|
|
107
|
-
feature: (p) => commands.feature(p || ''),
|
|
108
106
|
bug: (p) => commands.bug(p || ''),
|
|
109
107
|
idea: (p) => commands.idea(p || ''),
|
|
110
108
|
spec: (p) => commands.spec(p),
|
|
@@ -146,9 +146,34 @@ async function migrateProjectsCliVersion(): Promise<void> {
|
|
|
146
146
|
.map(dirent => dirent.name)
|
|
147
147
|
|
|
148
148
|
let migrated = 0
|
|
149
|
+
let configsCreated = 0
|
|
149
150
|
|
|
150
151
|
for (const projectId of projectDirs) {
|
|
151
152
|
const projectJsonPath = path.join(projectsDir, projectId, 'project.json')
|
|
153
|
+
const configDir = path.join(projectsDir, projectId, 'config')
|
|
154
|
+
|
|
155
|
+
// Ensure config directory exists for new config files
|
|
156
|
+
if (!fs.existsSync(configDir)) {
|
|
157
|
+
fs.mkdirSync(configDir, { recursive: true })
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Create slash-commands.json if missing (v0.28+ feature)
|
|
161
|
+
const slashCommandsPath = path.join(configDir, 'slash-commands.json')
|
|
162
|
+
if (!fs.existsSync(slashCommandsPath)) {
|
|
163
|
+
const slashCommandsConfig = {
|
|
164
|
+
version: '1.0.0',
|
|
165
|
+
generatedAt: new Date().toISOString(),
|
|
166
|
+
note: 'Run /p:sync to regenerate with full command list',
|
|
167
|
+
commands: {
|
|
168
|
+
'p:task': { description: 'Start any task', category: 'workflow' },
|
|
169
|
+
'p:done': { description: 'Complete subtask', category: 'workflow' },
|
|
170
|
+
'p:ship': { description: 'Ship feature', category: 'shipping' },
|
|
171
|
+
'p:sync': { description: 'Sync project', category: 'planning' },
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
fs.writeFileSync(slashCommandsPath, JSON.stringify(slashCommandsConfig, null, 2))
|
|
175
|
+
configsCreated++
|
|
176
|
+
}
|
|
152
177
|
|
|
153
178
|
if (!fs.existsSync(projectJsonPath)) {
|
|
154
179
|
continue
|
|
@@ -172,6 +197,9 @@ async function migrateProjectsCliVersion(): Promise<void> {
|
|
|
172
197
|
if (migrated > 0) {
|
|
173
198
|
console.log(` ${GREEN}✓${NC} Updated ${migrated} project(s) to v${VERSION}`)
|
|
174
199
|
}
|
|
200
|
+
if (configsCreated > 0) {
|
|
201
|
+
console.log(` ${GREEN}✓${NC} Created ${configsCreated} new config file(s)`)
|
|
202
|
+
}
|
|
175
203
|
} catch {
|
|
176
204
|
// Silently fail - migration is optional
|
|
177
205
|
}
|