prjct-cli 0.25.2 → 0.27.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.
- package/CHANGELOG.md +214 -0
- package/CLAUDE.md +109 -110
- package/core/infrastructure/command-installer.ts +27 -0
- package/package.json +1 -1
- package/templates/agentic/agents/uxui.md +8 -0
- package/templates/agentic/skill-integration.md +311 -0
- package/templates/agentic/subagent-generation.md +28 -12
- package/templates/commands/bug.md +72 -17
- package/templates/commands/done.md +158 -8
- package/templates/commands/git.md +21 -5
- package/templates/commands/merge.md +202 -0
- package/templates/commands/p.md +32 -0
- package/templates/commands/pause.md +40 -7
- package/templates/commands/resume.md +113 -33
- package/templates/commands/review.md +276 -0
- package/templates/commands/ship.md +193 -17
- package/templates/commands/sync.md +442 -47
- package/templates/commands/task.md +168 -542
- package/templates/commands/test.md +75 -3
- package/templates/commands/verify.md +204 -0
- package/templates/config/skill-mappings.json +87 -0
- package/templates/global/CLAUDE.md +193 -36
- package/templates/global/docs/commands.md +29 -31
- package/templates/subagents/domain/backend.md +1 -0
- package/templates/subagents/domain/devops.md +1 -0
- package/templates/subagents/domain/frontend.md +1 -0
- package/templates/subagents/domain/testing.md +1 -0
- package/templates/subagents/workflow/prjct-planner.md +1 -0
- package/templates/subagents/workflow/prjct-shipper.md +1 -0
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write, Bash]
|
|
3
|
-
description: 'Complete
|
|
2
|
+
allowed-tools: [Read, Write, Bash, AskUserQuestion]
|
|
3
|
+
description: 'Complete subtask or mark implement phase done'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# /p:done - Complete
|
|
6
|
+
# /p:done - Complete Subtask
|
|
7
7
|
|
|
8
|
-
Mark current
|
|
8
|
+
Mark current subtask as complete and progress to next. Does NOT complete the workflow - use p. verify after shipping.
|
|
9
|
+
|
|
10
|
+
**Note**: In workflow mode, p. done advances subtasks within the implement phase. To complete the full workflow:
|
|
11
|
+
```
|
|
12
|
+
p. task → (implement) → p. done (subtasks) → p. test → p. review → p. merge → p. ship → p. verify
|
|
13
|
+
```
|
|
9
14
|
|
|
10
15
|
## Usage
|
|
11
16
|
```
|
|
@@ -22,7 +27,7 @@ SET: `{globalPath}` = `~/.prjct-cli/projects/{projectId}`
|
|
|
22
27
|
|
|
23
28
|
READ: `{globalPath}/storage/state.json`
|
|
24
29
|
IF no `currentTask` OR status != "active":
|
|
25
|
-
OUTPUT: "No active task. Use
|
|
30
|
+
OUTPUT: "No active task. Use p. task to start one."
|
|
26
31
|
STOP
|
|
27
32
|
|
|
28
33
|
EXTRACT: `{task}` = currentTask.description
|
|
@@ -30,6 +35,80 @@ EXTRACT: `{startedAt}` = currentTask.startedAt
|
|
|
30
35
|
EXTRACT: `{sessionId}` = currentTask.sessionId
|
|
31
36
|
EXTRACT: `{estimate}` = currentTask.estimate (optional)
|
|
32
37
|
|
|
38
|
+
### Step 1.5: Handle Subtask Completion (AGENTIC)
|
|
39
|
+
|
|
40
|
+
IF currentTask.subtasks exists AND currentTask.subtasks.length > 0:
|
|
41
|
+
SET: {currentIndex} = currentTask.currentSubtaskIndex
|
|
42
|
+
SET: {currentSubtask} = currentTask.subtasks[{currentIndex}]
|
|
43
|
+
SET: {totalSubtasks} = currentTask.subtasks.length
|
|
44
|
+
SET: {nextIndex} = {currentIndex} + 1
|
|
45
|
+
SET: {hasMoreSubtasks} = {nextIndex} < {totalSubtasks}
|
|
46
|
+
|
|
47
|
+
IF {hasMoreSubtasks}:
|
|
48
|
+
SET: {nextSubtask} = currentTask.subtasks[{nextIndex}]
|
|
49
|
+
SET: {completedCount} = subtasks where status == "completed" + 1
|
|
50
|
+
SET: {remainingCount} = {totalSubtasks} - {completedCount}
|
|
51
|
+
|
|
52
|
+
USE AskUserQuestion:
|
|
53
|
+
```
|
|
54
|
+
question: "Subtask '{currentSubtask.description}' done. What's next?"
|
|
55
|
+
header: "Subtask Complete"
|
|
56
|
+
options:
|
|
57
|
+
- label: "Next: {nextSubtask.description}"
|
|
58
|
+
description: "{remainingCount} subtasks remaining"
|
|
59
|
+
- label: "Complete entire feature"
|
|
60
|
+
description: "Finish '{currentTask.parentDescription}' now"
|
|
61
|
+
- label: "More work needed"
|
|
62
|
+
description: "Continue on this subtask"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
IF choice starts with "Next:":
|
|
66
|
+
SET: {now} = GetTimestamp()
|
|
67
|
+
# Mark current subtask complete
|
|
68
|
+
SET: currentTask.subtasks[{currentIndex}].status = "completed"
|
|
69
|
+
SET: currentTask.subtasks[{currentIndex}].completedAt = "{now}"
|
|
70
|
+
# Start next subtask
|
|
71
|
+
SET: currentTask.subtasks[{nextIndex}].status = "active"
|
|
72
|
+
SET: currentTask.currentSubtaskIndex = {nextIndex}
|
|
73
|
+
SET: currentTask.description = "{nextSubtask.description}"
|
|
74
|
+
|
|
75
|
+
WRITE: `{globalPath}/storage/state.json`
|
|
76
|
+
|
|
77
|
+
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
78
|
+
{"timestamp":"{now}","action":"subtask_completed","subtaskId":"{currentSubtask.id}","nextSubtaskId":"{nextSubtask.id}"}
|
|
79
|
+
|
|
80
|
+
OUTPUT:
|
|
81
|
+
```
|
|
82
|
+
✅ {currentSubtask.description}
|
|
83
|
+
|
|
84
|
+
Now: {nextSubtask.description}
|
|
85
|
+
Progress: {completedCount}/{totalSubtasks} subtasks
|
|
86
|
+
|
|
87
|
+
p. done when finished
|
|
88
|
+
```
|
|
89
|
+
STOP
|
|
90
|
+
|
|
91
|
+
IF choice == "Complete entire feature":
|
|
92
|
+
# Mark all remaining as skipped, continue to normal done flow
|
|
93
|
+
FOR each subtask in currentTask.subtasks:
|
|
94
|
+
IF subtask.status == "pending":
|
|
95
|
+
SET: subtask.status = "skipped"
|
|
96
|
+
SET: currentTask.subtasks[{currentIndex}].status = "completed"
|
|
97
|
+
OUTPUT: "Completing feature: {currentTask.parentDescription}"
|
|
98
|
+
# Continue to Step 2
|
|
99
|
+
|
|
100
|
+
IF choice == "More work needed":
|
|
101
|
+
OUTPUT: "Continuing: {currentSubtask.description}"
|
|
102
|
+
STOP
|
|
103
|
+
|
|
104
|
+
ELSE:
|
|
105
|
+
# Last subtask - mark complete and continue to normal done flow
|
|
106
|
+
SET: {now} = GetTimestamp()
|
|
107
|
+
SET: currentTask.subtasks[{currentIndex}].status = "completed"
|
|
108
|
+
SET: currentTask.subtasks[{currentIndex}].completedAt = "{now}"
|
|
109
|
+
OUTPUT: "Final subtask done. Completing feature..."
|
|
110
|
+
# Continue to Step 2
|
|
111
|
+
|
|
33
112
|
### Step 2: Calculate Metrics
|
|
34
113
|
GET timestamp: `bun -e "console.log(new Date().toISOString())" 2>/dev/null || node -e "console.log(new Date().toISOString())"`
|
|
35
114
|
SET: `{now}` = result
|
|
@@ -82,7 +161,76 @@ APPEND to `{globalPath}/progress/sessions/{YYYY-MM}/{date}.jsonl`:
|
|
|
82
161
|
{"ts":"{now}","type":"task_complete","task":"{task}","duration":"{duration}"}
|
|
83
162
|
```
|
|
84
163
|
|
|
85
|
-
### Step
|
|
164
|
+
### Step 5.5: Handle Bug Completion Resume (AGENTIC)
|
|
165
|
+
|
|
166
|
+
IF currentTask.type == "bug" AND state.interruptedTask exists:
|
|
167
|
+
USE AskUserQuestion:
|
|
168
|
+
```
|
|
169
|
+
question: "Bug fixed! Resume '{state.interruptedTask.description}'?"
|
|
170
|
+
header: "Bug Complete"
|
|
171
|
+
options:
|
|
172
|
+
- label: "Resume previous task"
|
|
173
|
+
description: "Return to '{state.interruptedTask.description}'"
|
|
174
|
+
- label: "Pick from queue"
|
|
175
|
+
description: "See what else is waiting"
|
|
176
|
+
- label: "Done for now"
|
|
177
|
+
description: "No active task"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
IF choice == "Resume previous task":
|
|
181
|
+
SET: {now} = GetTimestamp()
|
|
182
|
+
SET: currentTask = state.interruptedTask
|
|
183
|
+
SET: currentTask.status = "active"
|
|
184
|
+
SET: currentTask.resumedAt = "{now}"
|
|
185
|
+
SET: state.interruptedTask = null
|
|
186
|
+
|
|
187
|
+
WRITE: `{globalPath}/storage/state.json`
|
|
188
|
+
|
|
189
|
+
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
190
|
+
{"timestamp":"{now}","action":"task_resumed_from_interrupt","taskId":"{currentTask.id}"}
|
|
191
|
+
|
|
192
|
+
OUTPUT:
|
|
193
|
+
```
|
|
194
|
+
✅ Bug fixed ({duration})
|
|
195
|
+
|
|
196
|
+
Resumed: {currentTask.description}
|
|
197
|
+
|
|
198
|
+
p. done when finished
|
|
199
|
+
```
|
|
200
|
+
STOP
|
|
201
|
+
|
|
202
|
+
IF choice == "Pick from queue":
|
|
203
|
+
SET: state.interruptedTask = null
|
|
204
|
+
READ: `{globalPath}/storage/queue.json`
|
|
205
|
+
SET: {topTasks} = first 3 from queue.tasks
|
|
206
|
+
|
|
207
|
+
OUTPUT:
|
|
208
|
+
```
|
|
209
|
+
✅ Bug fixed ({duration})
|
|
210
|
+
|
|
211
|
+
Previous task saved. Queue:
|
|
212
|
+
{FOR each in topTasks: "- {task.description}"}
|
|
213
|
+
|
|
214
|
+
p. task <description> to start
|
|
215
|
+
```
|
|
216
|
+
STOP
|
|
217
|
+
|
|
218
|
+
IF choice == "Done for now":
|
|
219
|
+
OUTPUT:
|
|
220
|
+
```
|
|
221
|
+
✅ Bug fixed ({duration})
|
|
222
|
+
|
|
223
|
+
'{state.interruptedTask.description}' saved for later.
|
|
224
|
+
|
|
225
|
+
p. resume to return | p. task for new work
|
|
226
|
+
```
|
|
227
|
+
STOP
|
|
228
|
+
|
|
229
|
+
### Step 6: Output with Queue Suggestion
|
|
230
|
+
|
|
231
|
+
READ: `{globalPath}/storage/queue.json`
|
|
232
|
+
SET: {queueCount} = queue.tasks.length
|
|
233
|
+
SET: {topTask} = queue.tasks[0] if exists
|
|
86
234
|
|
|
87
235
|
WITH estimate:
|
|
88
236
|
```
|
|
@@ -90,8 +238,9 @@ WITH estimate:
|
|
|
90
238
|
|
|
91
239
|
Estimate: {estimate} | Actual: {duration} | Accuracy: {accuracy}%
|
|
92
240
|
Files: {filesChanged} | +{linesAdded}/-{linesRemoved} | Commits: {commits}
|
|
241
|
+
{IF queueCount > 0: "Queue: {queueCount} tasks | Next: {topTask.description}"}
|
|
93
242
|
|
|
94
|
-
|
|
243
|
+
p. task | p. ship | p. next
|
|
95
244
|
```
|
|
96
245
|
|
|
97
246
|
WITHOUT estimate:
|
|
@@ -99,8 +248,9 @@ WITHOUT estimate:
|
|
|
99
248
|
✅ {task} ({duration})
|
|
100
249
|
|
|
101
250
|
Files: {filesChanged} | +{linesAdded}/-{linesRemoved} | Commits: {commits}
|
|
251
|
+
{IF queueCount > 0: "Queue: {queueCount} tasks | Next: {topTask.description}"}
|
|
102
252
|
|
|
103
|
-
|
|
253
|
+
p. task | p. ship | p. next
|
|
104
254
|
```
|
|
105
255
|
|
|
106
256
|
## Error Handling
|
|
@@ -97,16 +97,32 @@ IF {currentBranch} == "main" OR {currentBranch} == "master":
|
|
|
97
97
|
2. Resolve: conflicts if any
|
|
98
98
|
3. Git: `push`
|
|
99
99
|
|
|
100
|
-
## Commit Message Format
|
|
100
|
+
## Commit Message Format (CRITICAL - ALWAYS USE)
|
|
101
|
+
|
|
102
|
+
**Every commit MUST include the prjct signature:**
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
{type}: {description}
|
|
106
|
+
|
|
107
|
+
{details if any}
|
|
108
|
+
|
|
109
|
+
🤖 Generated with [p/](https://www.prjct.app/)
|
|
110
|
+
Designed for [Claude](https://www.anthropic.com/claude)
|
|
101
111
|
|
|
102
112
|
```
|
|
113
|
+
|
|
114
|
+
**NON-NEGOTIABLE: The `🤖 Generated with [p/]` line MUST appear in ALL commits.**
|
|
115
|
+
|
|
116
|
+
Use HEREDOC for proper formatting:
|
|
117
|
+
```bash
|
|
118
|
+
git commit -m "$(cat <<'EOF'
|
|
103
119
|
{type}: {description}
|
|
104
120
|
|
|
105
|
-
|
|
106
|
-
|
|
121
|
+
🤖 Generated with [p/](https://www.prjct.app/)
|
|
122
|
+
Designed for [Claude](https://www.anthropic.com/claude)
|
|
107
123
|
|
|
108
|
-
|
|
109
|
-
|
|
124
|
+
EOF
|
|
125
|
+
)"
|
|
110
126
|
```
|
|
111
127
|
|
|
112
128
|
## Response
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: [Bash, Read, Write, AskUserQuestion]
|
|
3
|
+
description: 'Merge PR to main branch'
|
|
4
|
+
timestamp-rule: 'GetTimestamp() for ALL timestamps'
|
|
5
|
+
architecture: 'Write-Through (JSON -> MD -> Events)'
|
|
6
|
+
storage-layer: true
|
|
7
|
+
source-of-truth: 'storage/state.json'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /p:merge
|
|
11
|
+
|
|
12
|
+
Merge approved PR to main branch.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/p:merge [--squash|--rebase|--merge] # Merge strategy (default: squash)
|
|
18
|
+
[--delete-branch] # Delete branch after merge
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Context Variables
|
|
22
|
+
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
23
|
+
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
24
|
+
- `{statePath}`: `{globalPath}/storage/state.json`
|
|
25
|
+
- `{memoryPath}`: `{globalPath}/memory/events.jsonl`
|
|
26
|
+
- `{syncPath}`: `{globalPath}/sync/pending.json`
|
|
27
|
+
|
|
28
|
+
## Step 1: Validate Project
|
|
29
|
+
|
|
30
|
+
READ: `.prjct/prjct.config.json`
|
|
31
|
+
EXTRACT: `projectId`
|
|
32
|
+
|
|
33
|
+
IF file not found:
|
|
34
|
+
OUTPUT: "No prjct project. Run /p:init first."
|
|
35
|
+
STOP
|
|
36
|
+
|
|
37
|
+
## Step 2: Validate Workflow Phase
|
|
38
|
+
|
|
39
|
+
READ: `{globalPath}/storage/state.json`
|
|
40
|
+
|
|
41
|
+
IF currentTask is null:
|
|
42
|
+
OUTPUT: "No active task. Use p. task to start one."
|
|
43
|
+
STOP
|
|
44
|
+
|
|
45
|
+
IF currentTask.workflow exists:
|
|
46
|
+
IF currentTask.workflow.phase != "review":
|
|
47
|
+
OUTPUT:
|
|
48
|
+
```
|
|
49
|
+
Cannot merge. Current phase: {currentTask.workflow.phase}
|
|
50
|
+
|
|
51
|
+
Required phase: review
|
|
52
|
+
|
|
53
|
+
Workflow: analyze → branch → implement → test → review → merge → ship → verify
|
|
54
|
+
|
|
55
|
+
Complete code review first with p. review
|
|
56
|
+
```
|
|
57
|
+
STOP
|
|
58
|
+
|
|
59
|
+
## Step 3: Verify PR Status
|
|
60
|
+
|
|
61
|
+
SET: {prNumber} = currentTask.branch.prNumber
|
|
62
|
+
|
|
63
|
+
IF {prNumber} is null:
|
|
64
|
+
OUTPUT: "No PR found. Run p. review first to create PR."
|
|
65
|
+
STOP
|
|
66
|
+
|
|
67
|
+
### Check PR is approved
|
|
68
|
+
BASH: `gh pr view {prNumber} --json reviewDecision,mergeable,state`
|
|
69
|
+
SET: {decision} = result.reviewDecision
|
|
70
|
+
SET: {mergeable} = result.mergeable
|
|
71
|
+
SET: {state} = result.state
|
|
72
|
+
|
|
73
|
+
IF {state} == "MERGED":
|
|
74
|
+
OUTPUT: "PR already merged."
|
|
75
|
+
-> Skip to Step 5 (update workflow)
|
|
76
|
+
|
|
77
|
+
IF {decision} != "APPROVED":
|
|
78
|
+
OUTPUT:
|
|
79
|
+
```
|
|
80
|
+
⚠️ PR not approved yet
|
|
81
|
+
|
|
82
|
+
Current status: {decision}
|
|
83
|
+
|
|
84
|
+
Get approvals and run p. merge again.
|
|
85
|
+
```
|
|
86
|
+
STOP
|
|
87
|
+
|
|
88
|
+
IF {mergeable} != "MERGEABLE":
|
|
89
|
+
OUTPUT:
|
|
90
|
+
```
|
|
91
|
+
⚠️ PR has conflicts or is not mergeable
|
|
92
|
+
|
|
93
|
+
Status: {mergeable}
|
|
94
|
+
|
|
95
|
+
Resolve conflicts and run p. merge again.
|
|
96
|
+
```
|
|
97
|
+
STOP
|
|
98
|
+
|
|
99
|
+
## Step 4: Merge PR
|
|
100
|
+
|
|
101
|
+
### Parse merge strategy
|
|
102
|
+
SET: {strategy} = "squash" # default
|
|
103
|
+
IF --rebase: {strategy} = "rebase"
|
|
104
|
+
IF --merge: {strategy} = "merge"
|
|
105
|
+
|
|
106
|
+
OUTPUT: "Merging PR #{prNumber} with {strategy} strategy..."
|
|
107
|
+
|
|
108
|
+
BASH: `gh pr merge {prNumber} --{strategy} --auto 2>&1`
|
|
109
|
+
|
|
110
|
+
IF command fails:
|
|
111
|
+
OUTPUT: "Merge failed. Check PR status on GitHub."
|
|
112
|
+
STOP
|
|
113
|
+
|
|
114
|
+
### Delete branch if requested
|
|
115
|
+
IF --delete-branch OR currentTask.branch.createdByPrjct:
|
|
116
|
+
BASH: `git branch -d {currentTask.branch.name} 2>/dev/null`
|
|
117
|
+
BASH: `git push origin --delete {currentTask.branch.name} 2>/dev/null`
|
|
118
|
+
OUTPUT: "Deleted branch: {currentTask.branch.name}"
|
|
119
|
+
|
|
120
|
+
### Switch to base branch
|
|
121
|
+
BASH: `git checkout {currentTask.branch.baseBranch}`
|
|
122
|
+
BASH: `git pull origin {currentTask.branch.baseBranch}`
|
|
123
|
+
|
|
124
|
+
## Step 5: Update Workflow Phase
|
|
125
|
+
|
|
126
|
+
SET: {now} = GetTimestamp()
|
|
127
|
+
|
|
128
|
+
### Get merge commit
|
|
129
|
+
BASH: `git rev-parse HEAD`
|
|
130
|
+
SET: {mergeCommit} = result
|
|
131
|
+
|
|
132
|
+
SET: currentTask.workflow.phase = "merge"
|
|
133
|
+
SET: currentTask.workflow.checkpoints.merge = {
|
|
134
|
+
"completedAt": "{now}",
|
|
135
|
+
"data": {
|
|
136
|
+
"mergeCommit": "{mergeCommit}",
|
|
137
|
+
"prNumber": {prNumber},
|
|
138
|
+
"strategy": "{strategy}"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
SET: currentTask.workflow.lastCheckpoint = "merge"
|
|
142
|
+
|
|
143
|
+
WRITE: `{statePath}`
|
|
144
|
+
|
|
145
|
+
## Step 6: Log Events
|
|
146
|
+
|
|
147
|
+
APPEND to `{memoryPath}`:
|
|
148
|
+
```json
|
|
149
|
+
{"timestamp":"{now}","action":"phase_advanced","taskId":"{currentTask.id}","from":"review","to":"merge"}
|
|
150
|
+
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"merge","data":{"mergeCommit":"{mergeCommit}"}}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
APPEND to `{syncPath}`:
|
|
154
|
+
```json
|
|
155
|
+
{"type":"workflow.phase_advanced","data":{"taskId":"{currentTask.id}","from":"review","to":"merge","mergeCommit":"{mergeCommit}"},"timestamp":"{now}"}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Output
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
✓ PR Merged
|
|
162
|
+
|
|
163
|
+
Task: {currentTask.description}
|
|
164
|
+
PR: #{prNumber}
|
|
165
|
+
Merge commit: {mergeCommit}
|
|
166
|
+
Strategy: {strategy}
|
|
167
|
+
|
|
168
|
+
Phase: merge (6/11 checkpoints)
|
|
169
|
+
|
|
170
|
+
Workflow:
|
|
171
|
+
1. analyze ✓
|
|
172
|
+
2. branch ✓
|
|
173
|
+
3. implement ✓
|
|
174
|
+
4. test ✓
|
|
175
|
+
5. review ✓
|
|
176
|
+
6. merge ✓
|
|
177
|
+
7-10. ship ← next
|
|
178
|
+
|
|
179
|
+
Next: p. ship to release
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Error Handling
|
|
183
|
+
|
|
184
|
+
| Error | Response | Action |
|
|
185
|
+
|-------|----------|--------|
|
|
186
|
+
| No project | "No prjct project" | STOP |
|
|
187
|
+
| No active task | "No active task" | STOP |
|
|
188
|
+
| Wrong phase | Show required phase | STOP |
|
|
189
|
+
| No PR | "Run p. review first" | STOP |
|
|
190
|
+
| Not approved | "Get approvals first" | STOP |
|
|
191
|
+
| Conflicts | "Resolve conflicts" | STOP |
|
|
192
|
+
| Merge fails | Show error | STOP |
|
|
193
|
+
|
|
194
|
+
## Natural Language Triggers
|
|
195
|
+
|
|
196
|
+
- `p. merge` -> /p:merge
|
|
197
|
+
- `p. merge pr` -> /p:merge
|
|
198
|
+
|
|
199
|
+
## References
|
|
200
|
+
|
|
201
|
+
- Architecture: `~/.prjct-cli/docs/architecture.md`
|
|
202
|
+
- Workflow: `~/.prjct-cli/docs/workflow.md`
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 'prjct CLI - Developer momentum tool'
|
|
3
|
+
allowed-tools: [Read, Write, Edit, Bash, Glob, Grep, Task, AskUserQuestion, TodoWrite]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# prjct Command Router
|
|
7
|
+
|
|
8
|
+
Route `p. <command>` to the appropriate prjct command.
|
|
9
|
+
|
|
10
|
+
## Instructions
|
|
11
|
+
|
|
12
|
+
**ARGUMENTS**: $ARGUMENTS
|
|
13
|
+
|
|
14
|
+
1. Parse ARGUMENTS: first word = `command`, rest = `commandArgs`
|
|
15
|
+
2. Read the template file: `~/.claude/commands/p/{command}.md`
|
|
16
|
+
3. Execute that template with `commandArgs` as the task description
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
If ARGUMENTS = "task fix the login bug":
|
|
21
|
+
- command = "task"
|
|
22
|
+
- commandArgs = "fix the login bug"
|
|
23
|
+
- Read: `~/.claude/commands/p/task.md`
|
|
24
|
+
- Execute with: "fix the login bug"
|
|
25
|
+
|
|
26
|
+
## Available Commands
|
|
27
|
+
|
|
28
|
+
`task` `done` `ship` `sync` `init` `idea` `dash` `next` `pause` `resume` `bug` `spec` `suggest` `git` `test` `cleanup` `design` `analyze` `undo` `redo`
|
|
29
|
+
|
|
30
|
+
## Action
|
|
31
|
+
|
|
32
|
+
NOW read the command template and execute it.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write, Bash]
|
|
2
|
+
allowed-tools: [Read, Write, Bash, AskUserQuestion]
|
|
3
3
|
description: 'Pause current session with reason'
|
|
4
4
|
timestamp-rule: 'GetTimestamp() for all timestamps'
|
|
5
5
|
architecture: 'Write-Through (JSON → MD → Events)'
|
|
@@ -89,15 +89,42 @@ IF {currentTask} is null OR {currentTask.status} != "active":
|
|
|
89
89
|
OUTPUT: "⚠️ No active session to pause."
|
|
90
90
|
STOP
|
|
91
91
|
|
|
92
|
-
## Step 3: Get Pause Reason
|
|
92
|
+
## Step 3: Get Pause Reason (AGENTIC)
|
|
93
93
|
|
|
94
94
|
IF {reason} not provided:
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
USE AskUserQuestion:
|
|
96
|
+
```
|
|
97
|
+
question: "Why are you pausing '{currentTask.description}'?"
|
|
98
|
+
header: "Pause Reason"
|
|
99
|
+
options:
|
|
100
|
+
- label: "Blocked"
|
|
101
|
+
description: "Waiting on external dependency"
|
|
102
|
+
- label: "Switching task"
|
|
103
|
+
description: "Starting a different, higher priority task"
|
|
104
|
+
- label: "Taking a break"
|
|
105
|
+
description: "Stepping away temporarily"
|
|
106
|
+
- label: "Researching"
|
|
107
|
+
description: "Need to investigate more before continuing"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
SET: {reason} = choice mapped to (blocked, switch, break, research)
|
|
97
111
|
|
|
98
112
|
IF {reason} == "blocked":
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
USE AskUserQuestion:
|
|
114
|
+
```
|
|
115
|
+
question: "What's blocking you?"
|
|
116
|
+
header: "Blocker"
|
|
117
|
+
options:
|
|
118
|
+
- label: "Waiting for review"
|
|
119
|
+
description: "Code review or approval needed"
|
|
120
|
+
- label: "Waiting for API/credentials"
|
|
121
|
+
description: "External access or keys needed"
|
|
122
|
+
- label: "Waiting for clarification"
|
|
123
|
+
description: "Need more info on requirements"
|
|
124
|
+
- label: "Technical blocker"
|
|
125
|
+
description: "Dependency or infrastructure issue"
|
|
126
|
+
```
|
|
127
|
+
SET: {blockerNote} = choice (user can also provide custom text)
|
|
101
128
|
|
|
102
129
|
## Step 4: Calculate Duration So Far
|
|
103
130
|
|
|
@@ -120,10 +147,16 @@ SET: {durationFormatted} = format as "Xh Ym" or "Xm"
|
|
|
120
147
|
"pauseReason": "{reason}",
|
|
121
148
|
"pauseNote": "{blockerNote}",
|
|
122
149
|
"estimate": "{currentTask.estimate}",
|
|
123
|
-
"estimateSeconds": {currentTask.estimateSeconds}
|
|
150
|
+
"estimateSeconds": {currentTask.estimateSeconds},
|
|
151
|
+
"workflow": "{currentTask.workflow}",
|
|
152
|
+
"subtasks": "{currentTask.subtasks}",
|
|
153
|
+
"currentSubtaskIndex": {currentTask.currentSubtaskIndex},
|
|
154
|
+
"branch": "{currentTask.branch}"
|
|
124
155
|
}
|
|
125
156
|
```
|
|
126
157
|
|
|
158
|
+
**Note**: The workflow field is preserved so the task can resume at the correct phase.
|
|
159
|
+
|
|
127
160
|
### Update state.json
|
|
128
161
|
READ: `{statePath}`
|
|
129
162
|
SET: state.pausedTask = paused task object
|