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,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write, Bash]
|
|
3
|
-
description: 'Resume paused session'
|
|
2
|
+
allowed-tools: [Read, Write, Bash, AskUserQuestion]
|
|
3
|
+
description: 'Resume paused or interrupted session'
|
|
4
4
|
timestamp-rule: 'GetTimestamp() for all timestamps'
|
|
5
5
|
architecture: 'Write-Through (JSON → MD → Events)'
|
|
6
6
|
storage-layer: true
|
|
@@ -54,7 +54,7 @@ IF file not found:
|
|
|
54
54
|
STOP
|
|
55
55
|
|
|
56
56
|
PARSE JSON
|
|
57
|
-
EXTRACT: {currentTask}, {pausedTask}
|
|
57
|
+
EXTRACT: {currentTask}, {pausedTask}, {interruptedTask}
|
|
58
58
|
|
|
59
59
|
IF {currentTask} exists AND {currentTask.status} == "active":
|
|
60
60
|
CALCULATE: {elapsed} = time since last start
|
|
@@ -65,47 +65,93 @@ IF {currentTask} exists AND {currentTask.status} == "active":
|
|
|
65
65
|
Session: {currentTask.sessionId}
|
|
66
66
|
Working for: {elapsed}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
p. done to complete | p. pause to pause
|
|
69
69
|
```
|
|
70
70
|
STOP
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
### Handle interruptedTask (priority check)
|
|
73
|
+
IF {interruptedTask} exists AND {pausedTask} exists:
|
|
74
|
+
# Both exist - ask user which to resume
|
|
75
|
+
SET: {interruptedElapsed} = time since interruptedTask.interruptedAt
|
|
76
|
+
SET: {pausedElapsed} = time since pausedTask.pausedAt
|
|
77
|
+
|
|
78
|
+
USE AskUserQuestion:
|
|
79
|
+
```
|
|
80
|
+
question: "Multiple tasks waiting. Which one to resume?"
|
|
81
|
+
header: "Resume Task"
|
|
82
|
+
options:
|
|
83
|
+
- label: "{interruptedTask.description}"
|
|
84
|
+
description: "Interrupted {interruptedElapsed} ago (by {interruptedTask.interruptReason})"
|
|
85
|
+
- label: "{pausedTask.description}"
|
|
86
|
+
description: "Paused {pausedElapsed} ago ({pausedTask.pauseReason})"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
IF choice == interruptedTask.description:
|
|
90
|
+
SET: {taskToResume} = {interruptedTask}
|
|
91
|
+
SET: {resumeType} = "interrupted"
|
|
92
|
+
SET: {clearField} = "interruptedTask"
|
|
93
|
+
ELSE:
|
|
94
|
+
SET: {taskToResume} = {pausedTask}
|
|
95
|
+
SET: {resumeType} = "paused"
|
|
96
|
+
SET: {clearField} = "pausedTask"
|
|
97
|
+
|
|
98
|
+
ELSE IF {interruptedTask} exists:
|
|
99
|
+
# Only interrupted task exists
|
|
100
|
+
SET: {taskToResume} = {interruptedTask}
|
|
101
|
+
SET: {resumeType} = "interrupted"
|
|
102
|
+
SET: {clearField} = "interruptedTask"
|
|
103
|
+
|
|
104
|
+
ELSE IF {pausedTask} exists:
|
|
105
|
+
# Only paused task exists
|
|
106
|
+
SET: {taskToResume} = {pausedTask}
|
|
107
|
+
SET: {resumeType} = "paused"
|
|
108
|
+
SET: {clearField} = "pausedTask"
|
|
109
|
+
|
|
110
|
+
ELSE:
|
|
73
111
|
OUTPUT:
|
|
74
112
|
```
|
|
75
|
-
⚠️ No paused session to resume.
|
|
113
|
+
⚠️ No paused or interrupted session to resume.
|
|
76
114
|
|
|
77
115
|
Start a new task:
|
|
78
|
-
•
|
|
116
|
+
• p. task <task>
|
|
79
117
|
```
|
|
80
118
|
STOP
|
|
81
119
|
|
|
82
|
-
## Step 3: Calculate
|
|
120
|
+
## Step 3: Calculate Away Duration
|
|
83
121
|
|
|
84
122
|
SET: {now} = GetTimestamp()
|
|
85
|
-
|
|
86
|
-
|
|
123
|
+
|
|
124
|
+
IF {resumeType} == "interrupted":
|
|
125
|
+
SET: {awayDurationSeconds} = seconds between {taskToResume.interruptedAt} and {now}
|
|
126
|
+
ELSE:
|
|
127
|
+
SET: {awayDurationSeconds} = seconds between {taskToResume.pausedAt} and {now}
|
|
128
|
+
|
|
129
|
+
SET: {awayFormatted} = format as "Xh Ym" or "Xm"
|
|
87
130
|
|
|
88
131
|
## Step 4: Update Storage (SOURCE OF TRUTH)
|
|
89
132
|
|
|
90
133
|
### Prepare resumed task
|
|
91
134
|
```json
|
|
92
135
|
{
|
|
93
|
-
"id": "{
|
|
94
|
-
"description": "{
|
|
136
|
+
"id": "{taskToResume.id}",
|
|
137
|
+
"description": "{taskToResume.description}",
|
|
95
138
|
"status": "active",
|
|
96
|
-
"startedAt": "{
|
|
139
|
+
"startedAt": "{taskToResume.startedAt}",
|
|
97
140
|
"resumedAt": "{now}",
|
|
98
|
-
"sessionId": "{
|
|
99
|
-
"duration": {
|
|
100
|
-
"estimate": "{
|
|
101
|
-
"estimateSeconds": {
|
|
141
|
+
"sessionId": "{taskToResume.sessionId}",
|
|
142
|
+
"duration": {taskToResume.duration},
|
|
143
|
+
"estimate": "{taskToResume.estimate}",
|
|
144
|
+
"estimateSeconds": {taskToResume.estimateSeconds},
|
|
145
|
+
"subtasks": {taskToResume.subtasks},
|
|
146
|
+
"currentSubtaskIndex": {taskToResume.currentSubtaskIndex},
|
|
147
|
+
"parentDescription": "{taskToResume.parentDescription}"
|
|
102
148
|
}
|
|
103
149
|
```
|
|
104
150
|
|
|
105
151
|
### Update state.json
|
|
106
152
|
READ: `{statePath}`
|
|
107
153
|
SET: state.currentTask = resumed task object
|
|
108
|
-
SET: state.
|
|
154
|
+
SET: state.{clearField} = null # Clear pausedTask or interruptedTask based on which was resumed
|
|
109
155
|
SET: state.lastUpdated = {now}
|
|
110
156
|
WRITE: `{statePath}`
|
|
111
157
|
|
|
@@ -116,12 +162,13 @@ WRITE: `{nowContextPath}`
|
|
|
116
162
|
```markdown
|
|
117
163
|
# NOW
|
|
118
164
|
|
|
119
|
-
**{
|
|
165
|
+
**{taskToResume.description}**
|
|
120
166
|
|
|
121
|
-
Started: {
|
|
167
|
+
Started: {taskToResume.startedAt}
|
|
122
168
|
Resumed: {now}
|
|
123
|
-
Session: {
|
|
124
|
-
{IF
|
|
169
|
+
Session: {taskToResume.sessionId}
|
|
170
|
+
{IF taskToResume.estimate: Estimate: {taskToResume.estimate}}
|
|
171
|
+
{IF taskToResume.subtasks: Subtask: {currentSubtask.description}}
|
|
125
172
|
```
|
|
126
173
|
|
|
127
174
|
## Step 6: Queue Sync Event (FOR BACKEND)
|
|
@@ -133,10 +180,11 @@ APPEND event:
|
|
|
133
180
|
"type": "task.resumed",
|
|
134
181
|
"path": ["state"],
|
|
135
182
|
"data": {
|
|
136
|
-
"taskId": "{
|
|
137
|
-
"description": "{
|
|
183
|
+
"taskId": "{taskToResume.id}",
|
|
184
|
+
"description": "{taskToResume.description}",
|
|
138
185
|
"resumedAt": "{now}",
|
|
139
|
-
"
|
|
186
|
+
"awayDuration": {awayDurationSeconds},
|
|
187
|
+
"resumeType": "{resumeType}"
|
|
140
188
|
},
|
|
141
189
|
"timestamp": "{now}",
|
|
142
190
|
"projectId": "{projectId}"
|
|
@@ -148,22 +196,54 @@ WRITE: `{syncPath}`
|
|
|
148
196
|
|
|
149
197
|
APPEND to: `{memoryPath}`
|
|
150
198
|
|
|
151
|
-
|
|
199
|
+
IF {resumeType} == "interrupted":
|
|
200
|
+
```json
|
|
201
|
+
{"timestamp":"{now}","action":"task_resumed_from_interrupt","taskId":"{taskToResume.id}","sessionId":"{taskToResume.sessionId}","task":"{taskToResume.description}","awayDuration":{awayDurationSeconds}}
|
|
202
|
+
```
|
|
203
|
+
ELSE:
|
|
152
204
|
```json
|
|
153
|
-
{"timestamp":"{now}","action":"task_resumed","taskId":"{
|
|
205
|
+
{"timestamp":"{now}","action":"task_resumed","taskId":"{taskToResume.id}","sessionId":"{taskToResume.sessionId}","task":"{taskToResume.description}","pauseDuration":{awayDurationSeconds}}
|
|
154
206
|
```
|
|
155
207
|
|
|
156
208
|
## Output
|
|
157
209
|
|
|
158
|
-
|
|
210
|
+
### Resumed from pause (with workflow):
|
|
211
|
+
IF {taskToResume.workflow} exists:
|
|
212
|
+
```
|
|
213
|
+
▶️ Resumed: {taskToResume.description}
|
|
214
|
+
|
|
215
|
+
Session: {taskToResume.sessionId}
|
|
216
|
+
Was paused: {awayFormatted}
|
|
217
|
+
Phase: {taskToResume.workflow.phase} ({checkpointCount}/11 checkpoints)
|
|
218
|
+
|
|
219
|
+
Next step based on phase:
|
|
220
|
+
- implement: Continue coding, then p. test
|
|
221
|
+
- test: Run p. test
|
|
222
|
+
- review: Run p. review
|
|
223
|
+
- merge: Run p. merge
|
|
224
|
+
- register: Run p. verify
|
|
159
225
|
```
|
|
160
|
-
▶️ Resumed: {pausedTask.description}
|
|
161
226
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
227
|
+
### Resumed from pause (legacy, no workflow):
|
|
228
|
+
```
|
|
229
|
+
▶️ Resumed: {taskToResume.description}
|
|
165
230
|
|
|
166
|
-
|
|
231
|
+
Session: {taskToResume.sessionId}
|
|
232
|
+
Was paused: {awayFormatted}
|
|
233
|
+
Total active: {taskToResume.duration} (before this stretch)
|
|
234
|
+
|
|
235
|
+
p. done when finished | p. pause for another break
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Resumed from interrupt (bug):
|
|
239
|
+
```
|
|
240
|
+
▶️ Resumed: {taskToResume.description}
|
|
241
|
+
|
|
242
|
+
Session: {taskToResume.sessionId}
|
|
243
|
+
Interrupted: {awayFormatted} ago (for bug fix)
|
|
244
|
+
Phase: {taskToResume.workflow.phase}
|
|
245
|
+
|
|
246
|
+
Continue where you left off.
|
|
167
247
|
```
|
|
168
248
|
|
|
169
249
|
## Error Handling
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: [Bash, Read, Write, Task, AskUserQuestion]
|
|
3
|
+
description: 'Code review with MCP agent and GitHub approvals'
|
|
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:review
|
|
11
|
+
|
|
12
|
+
Run MCP code review agent and wait for GitHub PR approvals.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/p:review [--skip-mcp] # Skip MCP agent review
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Context Variables
|
|
21
|
+
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
22
|
+
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
23
|
+
- `{statePath}`: `{globalPath}/storage/state.json`
|
|
24
|
+
- `{memoryPath}`: `{globalPath}/memory/events.jsonl`
|
|
25
|
+
- `{syncPath}`: `{globalPath}/sync/pending.json`
|
|
26
|
+
|
|
27
|
+
## Step 1: Validate Project
|
|
28
|
+
|
|
29
|
+
READ: `.prjct/prjct.config.json`
|
|
30
|
+
EXTRACT: `projectId`
|
|
31
|
+
|
|
32
|
+
IF file not found:
|
|
33
|
+
OUTPUT: "No prjct project. Run /p:init first."
|
|
34
|
+
STOP
|
|
35
|
+
|
|
36
|
+
## Step 2: Validate Workflow Phase
|
|
37
|
+
|
|
38
|
+
READ: `{globalPath}/storage/state.json`
|
|
39
|
+
|
|
40
|
+
IF currentTask is null:
|
|
41
|
+
OUTPUT: "No active task. Use p. task to start one."
|
|
42
|
+
STOP
|
|
43
|
+
|
|
44
|
+
IF currentTask.workflow exists:
|
|
45
|
+
IF currentTask.workflow.phase != "test":
|
|
46
|
+
OUTPUT:
|
|
47
|
+
```
|
|
48
|
+
Cannot start review. Current phase: {currentTask.workflow.phase}
|
|
49
|
+
|
|
50
|
+
Required phase: test
|
|
51
|
+
|
|
52
|
+
Workflow: analyze → branch → implement → test → review → merge → ship → verify
|
|
53
|
+
|
|
54
|
+
Run p. test first to advance to test phase.
|
|
55
|
+
```
|
|
56
|
+
STOP
|
|
57
|
+
|
|
58
|
+
## Step 3: Run MCP Code Review (unless --skip-mcp)
|
|
59
|
+
|
|
60
|
+
IF NOT --skip-mcp:
|
|
61
|
+
OUTPUT: "Running MCP code review..."
|
|
62
|
+
|
|
63
|
+
### Get changed files
|
|
64
|
+
BASH: `git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only`
|
|
65
|
+
SET: {changedFiles} = result
|
|
66
|
+
|
|
67
|
+
### Analyze with MCP agent
|
|
68
|
+
FOR each file in {changedFiles}:
|
|
69
|
+
READ: file
|
|
70
|
+
ANALYZE for:
|
|
71
|
+
- Security issues (hardcoded secrets, injection vulnerabilities)
|
|
72
|
+
- Logic errors
|
|
73
|
+
- Missing error handling
|
|
74
|
+
- Performance issues
|
|
75
|
+
- Code style violations
|
|
76
|
+
|
|
77
|
+
ASSIGN confidence score (0-100):
|
|
78
|
+
- 90-100: Definite bug/security issue
|
|
79
|
+
- 70-89: Likely problem
|
|
80
|
+
- 50-69: Maybe a problem
|
|
81
|
+
- 0-49: Nitpick/style
|
|
82
|
+
|
|
83
|
+
SET: {issues} = issues with confidence >= 70
|
|
84
|
+
SET: {mcpScore} = 100 - (count of high-confidence issues * 10)
|
|
85
|
+
|
|
86
|
+
IF {issues}.length > 0:
|
|
87
|
+
OUTPUT:
|
|
88
|
+
```
|
|
89
|
+
## MCP Code Review Results
|
|
90
|
+
|
|
91
|
+
Found {issues.length} issues (confidence >= 70%):
|
|
92
|
+
|
|
93
|
+
{FOR each issue:}
|
|
94
|
+
- [{confidence}%] {description}
|
|
95
|
+
File: {file}:{line}
|
|
96
|
+
{END FOR}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
USE AskUserQuestion:
|
|
100
|
+
```
|
|
101
|
+
question: "Code review found {issues.length} issues. How to proceed?"
|
|
102
|
+
header: "Review Issues"
|
|
103
|
+
options:
|
|
104
|
+
- label: "Fix issues first"
|
|
105
|
+
description: "Return to implement phase to fix"
|
|
106
|
+
- label: "Proceed anyway"
|
|
107
|
+
description: "Continue with PR creation"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
IF choice == "Fix issues first":
|
|
111
|
+
OUTPUT: "Returning to implement phase. Fix issues and run p. test again."
|
|
112
|
+
STOP
|
|
113
|
+
ELSE:
|
|
114
|
+
OUTPUT: "✓ MCP review passed. No high-confidence issues found."
|
|
115
|
+
SET: {mcpScore} = 100
|
|
116
|
+
|
|
117
|
+
## Step 4: Create/Check PR
|
|
118
|
+
|
|
119
|
+
### Check if PR exists
|
|
120
|
+
BASH: `gh pr view --json url,number,state 2>/dev/null`
|
|
121
|
+
|
|
122
|
+
IF PR exists:
|
|
123
|
+
SET: {prUrl} = result.url
|
|
124
|
+
SET: {prNumber} = result.number
|
|
125
|
+
SET: {prState} = result.state
|
|
126
|
+
OUTPUT: "PR exists: {prUrl}"
|
|
127
|
+
ELSE:
|
|
128
|
+
OUTPUT: "Creating PR..."
|
|
129
|
+
|
|
130
|
+
SET: {branchName} = currentTask.branch.name
|
|
131
|
+
SET: {baseBranch} = currentTask.branch.baseBranch OR "main"
|
|
132
|
+
|
|
133
|
+
BASH: `git push -u origin {branchName} 2>&1`
|
|
134
|
+
|
|
135
|
+
SET: {prTitle} = "{currentTask.type}: {currentTask.description}"
|
|
136
|
+
SET: {prBody} = """
|
|
137
|
+
## Summary
|
|
138
|
+
{currentTask.description}
|
|
139
|
+
|
|
140
|
+
## Workflow Phase
|
|
141
|
+
- [x] Analyze
|
|
142
|
+
- [x] Branch
|
|
143
|
+
- [x] Implement
|
|
144
|
+
- [x] Test
|
|
145
|
+
- [ ] Review ← current
|
|
146
|
+
- [ ] Merge
|
|
147
|
+
- [ ] Ship
|
|
148
|
+
- [ ] Verify
|
|
149
|
+
|
|
150
|
+
## MCP Review Score
|
|
151
|
+
{mcpScore}/100
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
🤖 Generated with [p/](https://www.prjct.app/)
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
BASH: `gh pr create --title "{prTitle}" --base {baseBranch} --body "$(cat <<'PREOF'
|
|
158
|
+
{prBody}
|
|
159
|
+
PREOF
|
|
160
|
+
)"`
|
|
161
|
+
|
|
162
|
+
EXTRACT: {prUrl}, {prNumber} from output
|
|
163
|
+
|
|
164
|
+
## Step 5: Check GitHub Approvals
|
|
165
|
+
|
|
166
|
+
OUTPUT: "Checking for approvals..."
|
|
167
|
+
|
|
168
|
+
BASH: `gh pr view {prNumber} --json reviews,reviewDecision`
|
|
169
|
+
SET: {reviews} = result.reviews
|
|
170
|
+
SET: {decision} = result.reviewDecision
|
|
171
|
+
|
|
172
|
+
IF {decision} == "APPROVED":
|
|
173
|
+
SET: {approved} = true
|
|
174
|
+
SET: {approvals} = reviews where state == "APPROVED"
|
|
175
|
+
OUTPUT: "✓ PR approved by {approvals.length} reviewer(s)"
|
|
176
|
+
ELSE IF {decision} == "CHANGES_REQUESTED":
|
|
177
|
+
OUTPUT:
|
|
178
|
+
```
|
|
179
|
+
⚠️ Changes requested
|
|
180
|
+
|
|
181
|
+
{FOR each review where state == "CHANGES_REQUESTED":}
|
|
182
|
+
- {review.author}: {review.body}
|
|
183
|
+
{END FOR}
|
|
184
|
+
|
|
185
|
+
Address feedback, push changes, and run p. review again.
|
|
186
|
+
```
|
|
187
|
+
STOP
|
|
188
|
+
ELSE:
|
|
189
|
+
OUTPUT:
|
|
190
|
+
```
|
|
191
|
+
⏳ Waiting for approvals
|
|
192
|
+
|
|
193
|
+
PR: {prUrl}
|
|
194
|
+
|
|
195
|
+
Request review from team members, then run p. review again.
|
|
196
|
+
```
|
|
197
|
+
STOP
|
|
198
|
+
|
|
199
|
+
## Step 6: Update Workflow Phase
|
|
200
|
+
|
|
201
|
+
SET: {now} = GetTimestamp()
|
|
202
|
+
|
|
203
|
+
SET: currentTask.workflow.phase = "review"
|
|
204
|
+
SET: currentTask.workflow.checkpoints.review = {
|
|
205
|
+
"completedAt": "{now}",
|
|
206
|
+
"data": {
|
|
207
|
+
"mcpScore": {mcpScore},
|
|
208
|
+
"approvals": {approvals},
|
|
209
|
+
"prUrl": "{prUrl}",
|
|
210
|
+
"prNumber": {prNumber}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
SET: currentTask.workflow.lastCheckpoint = "review"
|
|
214
|
+
SET: currentTask.branch.prUrl = "{prUrl}"
|
|
215
|
+
SET: currentTask.branch.prNumber = {prNumber}
|
|
216
|
+
|
|
217
|
+
WRITE: `{statePath}`
|
|
218
|
+
|
|
219
|
+
## Step 7: Log Events
|
|
220
|
+
|
|
221
|
+
APPEND to `{memoryPath}`:
|
|
222
|
+
```json
|
|
223
|
+
{"timestamp":"{now}","action":"phase_advanced","taskId":"{currentTask.id}","from":"test","to":"review"}
|
|
224
|
+
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"review","data":{"mcpScore":{mcpScore},"approvals":{approvals.length}}}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
APPEND to `{syncPath}`:
|
|
228
|
+
```json
|
|
229
|
+
{"type":"workflow.phase_advanced","data":{"taskId":"{currentTask.id}","from":"test","to":"review","prUrl":"{prUrl}"},"timestamp":"{now}"}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Output
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
✓ Review Complete
|
|
236
|
+
|
|
237
|
+
Task: {currentTask.description}
|
|
238
|
+
MCP Score: {mcpScore}/100
|
|
239
|
+
Approvals: {approvals.length}
|
|
240
|
+
PR: {prUrl}
|
|
241
|
+
|
|
242
|
+
Phase: review (5/11 checkpoints)
|
|
243
|
+
|
|
244
|
+
Workflow:
|
|
245
|
+
1. analyze ✓
|
|
246
|
+
2. branch ✓
|
|
247
|
+
3. implement ✓
|
|
248
|
+
4. test ✓
|
|
249
|
+
5. review ✓
|
|
250
|
+
6. merge ← next
|
|
251
|
+
|
|
252
|
+
Next: p. merge to merge PR
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Error Handling
|
|
256
|
+
|
|
257
|
+
| Error | Response | Action |
|
|
258
|
+
|-------|----------|--------|
|
|
259
|
+
| No project | "No prjct project" | STOP |
|
|
260
|
+
| No active task | "No active task" | STOP |
|
|
261
|
+
| Wrong phase | Show required phase | STOP |
|
|
262
|
+
| MCP issues found | Ask user | WAIT |
|
|
263
|
+
| Changes requested | Show feedback | STOP |
|
|
264
|
+
| No approvals | Show PR URL | STOP |
|
|
265
|
+
| gh CLI missing | "Install gh CLI" | STOP |
|
|
266
|
+
|
|
267
|
+
## Natural Language Triggers
|
|
268
|
+
|
|
269
|
+
- `p. review` -> /p:review
|
|
270
|
+
- `p. code review` -> /p:review
|
|
271
|
+
- `p. pr` -> /p:review
|
|
272
|
+
|
|
273
|
+
## References
|
|
274
|
+
|
|
275
|
+
- Architecture: `~/.prjct-cli/docs/architecture.md`
|
|
276
|
+
- Workflow: `~/.prjct-cli/docs/workflow.md`
|