prjct-cli 0.35.3 → 0.36.1
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 +43 -0
- package/README.md +63 -618
- package/bin/prjct.ts +116 -17
- package/core/cli/start.ts +387 -0
- package/core/commands/analysis.ts +58 -32
- package/core/commands/command-data.ts +11 -50
- package/core/commands/commands.ts +18 -21
- package/core/commands/context.ts +238 -0
- package/core/commands/register.ts +7 -5
- package/core/commands/setup.ts +1 -17
- package/core/index.ts +103 -39
- package/core/infrastructure/ai-provider.ts +312 -0
- package/core/infrastructure/command-installer.ts +49 -5
- package/core/infrastructure/editors-config.ts +20 -6
- package/core/infrastructure/setup.ts +227 -62
- package/core/services/index.ts +2 -0
- package/core/services/skill-service.ts +52 -16
- package/core/services/sync-service.ts +1080 -0
- package/core/types/commands.ts +0 -12
- package/core/types/index.ts +12 -1
- package/core/types/provider.ts +110 -0
- package/core/utils/branding.ts +20 -3
- package/dist/bin/prjct.mjs +1053 -1426
- package/dist/core/infrastructure/command-installer.js +33 -2
- package/dist/core/infrastructure/editors-config.js +13 -3
- package/dist/core/infrastructure/setup.js +293 -73
- package/package.json +10 -16
- package/scripts/postinstall.js +17 -119
- package/templates/agentic/agent-routing.md +22 -88
- package/templates/agentic/agents/uxui.md +42 -197
- package/templates/agentic/context-filtering.md +14 -56
- package/templates/agentic/orchestrator.md +26 -302
- package/templates/agentic/skill-integration.md +37 -289
- package/templates/agentic/subagent-generation.md +31 -104
- package/templates/agentic/task-fragmentation.md +39 -273
- package/templates/agents/AGENTS.md +33 -181
- package/templates/commands/bug.md +22 -520
- package/templates/commands/dash.md +26 -161
- package/templates/commands/done.md +19 -250
- package/templates/commands/enrich.md +21 -732
- package/templates/commands/idea.md +18 -160
- package/templates/commands/init.md +20 -209
- package/templates/commands/merge.md +21 -185
- package/templates/commands/next.md +21 -103
- package/templates/commands/p.md +1 -1
- package/templates/commands/p.toml +37 -0
- package/templates/commands/pause.md +21 -272
- package/templates/commands/resume.md +18 -411
- package/templates/commands/setup.md +0 -1
- package/templates/commands/ship.md +30 -627
- package/templates/commands/sync.md +11 -1448
- package/templates/commands/task.md +17 -439
- package/templates/commands/test.md +30 -259
- package/templates/global/CLAUDE.md +33 -1
- package/templates/global/GEMINI.md +265 -0
- package/templates/global/STORAGE-SPEC.md +256 -0
- package/templates/global/docs/agents.md +88 -0
- package/templates/global/docs/architecture.md +103 -0
- package/templates/global/docs/commands.md +96 -0
- package/templates/global/docs/validation.md +95 -0
- package/CLAUDE.md +0 -211
- package/packages/shared/package.json +0 -29
- package/packages/shared/src/index.ts +0 -10
- package/packages/shared/src/schemas.ts +0 -124
- package/packages/shared/src/types.ts +0 -187
- package/packages/shared/src/unified.ts +0 -174
- package/packages/shared/src/utils.ts +0 -148
- package/packages/shared/tsconfig.json +0 -18
|
@@ -1,650 +1,53 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write, Bash,
|
|
3
|
-
description: 'Ship feature with automated PR workflow'
|
|
2
|
+
allowed-tools: [Read, Write, Bash, AskUserQuestion]
|
|
4
3
|
---
|
|
5
4
|
|
|
6
|
-
#
|
|
5
|
+
# p. ship "$ARGUMENTS"
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
## Usage
|
|
11
|
-
```
|
|
12
|
-
/p:ship [feature] [--blocking] [--skip-review] [--draft]
|
|
13
|
-
```
|
|
14
|
-
- `feature`: Name of the feature being shipped (required)
|
|
15
|
-
- `--blocking`: Abort if any check fails
|
|
16
|
-
- `--skip-review`: Skip code review (for trivial changes)
|
|
17
|
-
- `--draft`: Create PR as draft
|
|
18
|
-
|
|
19
|
-
## Flow
|
|
20
|
-
|
|
21
|
-
### Step 1: Validate Project
|
|
22
|
-
READ: `.prjct/prjct.config.json` → extract `projectId`
|
|
23
|
-
IF missing: "No prjct project. Run /p:init first." → STOP
|
|
24
|
-
|
|
25
|
-
SET: `{globalPath}` = `~/.prjct-cli/projects/{projectId}`
|
|
26
|
-
|
|
27
|
-
### Step 1.5: Validate Workflow Phase
|
|
28
|
-
|
|
29
|
-
READ: `{globalPath}/storage/state.json`
|
|
30
|
-
|
|
31
|
-
IF currentTask exists AND currentTask.workflow exists:
|
|
32
|
-
IF currentTask.workflow.phase != "merge":
|
|
33
|
-
OUTPUT:
|
|
34
|
-
```
|
|
35
|
-
Cannot ship. Current phase: {currentTask.workflow.phase}
|
|
36
|
-
|
|
37
|
-
Required phase: merge
|
|
38
|
-
|
|
39
|
-
Workflow: analyze → branch → implement → test → review → merge → ship → verify
|
|
40
|
-
|
|
41
|
-
Complete previous phases first:
|
|
42
|
-
- p. test (if in implement)
|
|
43
|
-
- p. review (if in test)
|
|
44
|
-
- p. merge (if in review)
|
|
45
|
-
```
|
|
46
|
-
STOP
|
|
47
|
-
|
|
48
|
-
### Step 1.6: Validate Open Tasks (AGENTIC)
|
|
49
|
-
|
|
50
|
-
IF currentTask exists AND status == "active":
|
|
51
|
-
SET: {openTaskDescription} = currentTask.description
|
|
52
|
-
SET: {elapsedTime} = time since currentTask.startedAt (format: "Xh Ym" or "Xm")
|
|
53
|
-
|
|
54
|
-
### Check for related subtasks
|
|
55
|
-
IF currentTask.subtasks exists:
|
|
56
|
-
SET: {pendingSubtasks} = subtasks where status == "pending"
|
|
57
|
-
SET: {pendingCount} = {pendingSubtasks}.length + 1 # +1 for current
|
|
58
|
-
ELSE:
|
|
59
|
-
SET: {pendingCount} = 1
|
|
60
|
-
|
|
61
|
-
USE AskUserQuestion:
|
|
62
|
-
```
|
|
63
|
-
question: "Active task: '{openTaskDescription}' ({elapsedTime}). {pendingCount} task(s) open. Ship anyway?"
|
|
64
|
-
header: "Open Tasks"
|
|
65
|
-
options:
|
|
66
|
-
- label: "Complete all and ship"
|
|
67
|
-
description: "Mark {pendingCount} task(s) as done, then ship"
|
|
68
|
-
- label: "Complete current only"
|
|
69
|
-
description: "Finish '{openTaskDescription}', ship now"
|
|
70
|
-
- label: "Cancel"
|
|
71
|
-
description: "Return to work, ship later"
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
IF choice == "Cancel":
|
|
75
|
-
OUTPUT: "Ship cancelled. Continue working on: {openTaskDescription}"
|
|
76
|
-
STOP
|
|
77
|
-
|
|
78
|
-
IF choice == "Complete all and ship":
|
|
79
|
-
### Mark all subtasks complete
|
|
80
|
-
IF currentTask.subtasks exists:
|
|
81
|
-
SET: {now} = GetTimestamp()
|
|
82
|
-
FOR each subtask in currentTask.subtasks:
|
|
83
|
-
IF subtask.status != "completed":
|
|
84
|
-
SET: subtask.status = "completed"
|
|
85
|
-
SET: subtask.completedAt = "{now}"
|
|
86
|
-
|
|
87
|
-
### Mark current task complete
|
|
88
|
-
SET: {now} = GetTimestamp()
|
|
89
|
-
SET: previousTask = {
|
|
90
|
-
...currentTask,
|
|
91
|
-
"status": "completed",
|
|
92
|
-
"completedAt": "{now}"
|
|
93
|
-
}
|
|
94
|
-
SET: currentTask = null
|
|
95
|
-
WRITE: `{globalPath}/storage/state.json`
|
|
96
|
-
|
|
97
|
-
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
98
|
-
```json
|
|
99
|
-
{"timestamp":"{now}","action":"task_auto_completed","reason":"ship","taskId":"{previousTask.id}"}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
OUTPUT: "✅ Completed: {openTaskDescription}"
|
|
103
|
-
|
|
104
|
-
IF choice == "Complete current only":
|
|
105
|
-
SET: {now} = GetTimestamp()
|
|
106
|
-
SET: previousTask = {
|
|
107
|
-
...currentTask,
|
|
108
|
-
"status": "completed",
|
|
109
|
-
"completedAt": "{now}"
|
|
110
|
-
}
|
|
111
|
-
SET: currentTask = null
|
|
112
|
-
WRITE: `{globalPath}/storage/state.json`
|
|
113
|
-
|
|
114
|
-
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
115
|
-
```json
|
|
116
|
-
{"timestamp":"{now}","action":"task_auto_completed","reason":"ship","taskId":"{previousTask.id}"}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
OUTPUT: "✅ Completed: {openTaskDescription}"
|
|
120
|
-
|
|
121
|
-
### Step 2: Pre-flight Checks
|
|
122
|
-
|
|
123
|
-
#### 2.1 Check for changes
|
|
124
|
-
BASH: `git status --porcelain`
|
|
125
|
-
IF empty: "No changes to ship." → STOP
|
|
126
|
-
|
|
127
|
-
#### 2.2 Analyze change scope
|
|
128
|
-
BASH: `git diff --stat HEAD`
|
|
129
|
-
EXTRACT: {filesChanged}, {insertions}, {deletions}
|
|
130
|
-
SET: {totalLines} = {insertions} + {deletions}
|
|
131
|
-
|
|
132
|
-
#### 2.3 Detect trivial changes
|
|
133
|
-
IF {totalLines} < 10 AND {filesChanged} <= 2:
|
|
134
|
-
SET: {changeType} = "trivial"
|
|
135
|
-
OUTPUT: "Trivial changes detected ({totalLines} lines in {filesChanged} files)"
|
|
136
|
-
ELSE IF {totalLines} < 50:
|
|
137
|
-
SET: {changeType} = "small"
|
|
138
|
-
ELSE IF {totalLines} < 200:
|
|
139
|
-
SET: {changeType} = "medium"
|
|
140
|
-
ELSE:
|
|
141
|
-
SET: {changeType} = "large"
|
|
142
|
-
OUTPUT: "Large change detected ({totalLines} lines). Full review recommended."
|
|
143
|
-
|
|
144
|
-
### Step 3: Quality Checks
|
|
145
|
-
Detect and run the project's existing quality commands (do not assume JS tooling):
|
|
146
|
-
|
|
147
|
-
- **Lint**: run only if the project already has a lint command configured (e.g. `npm run lint`, `pnpm run lint`, `yarn lint`, `bun run lint`)
|
|
148
|
-
- **Tests**: run the repo's test runner:
|
|
149
|
-
- JS: `{packageManager} test` (npm/pnpm/yarn/bun)
|
|
150
|
-
- Python: `pytest`
|
|
151
|
-
- Go: `go test ./...`
|
|
152
|
-
- Rust: `cargo test`
|
|
153
|
-
- .NET: `dotnet test`
|
|
154
|
-
- Java: `mvn test` or `./gradlew test`
|
|
155
|
-
|
|
156
|
-
BASH: `{lintCommand} 2>&1 || echo "LINT_SKIP"` # if detected
|
|
157
|
-
BASH: `{testCommand} 2>&1 || echo "TEST_SKIP"` # if detected
|
|
158
|
-
|
|
159
|
-
IF `--blocking` AND (lint failed OR tests failed):
|
|
160
|
-
OUTPUT: "Quality checks failed. Ship blocked."
|
|
161
|
-
STOP
|
|
162
|
-
|
|
163
|
-
### Step 4: Code Review with Confidence Scoring
|
|
164
|
-
|
|
165
|
-
IF `--skip-review` OR {changeType} == "trivial":
|
|
166
|
-
OUTPUT: "Skipping code review."
|
|
167
|
-
→ Go to Step 5
|
|
168
|
-
ELSE:
|
|
169
|
-
OUTPUT: "Running code review..."
|
|
170
|
-
|
|
171
|
-
#### 4.1 Get changed files
|
|
172
|
-
BASH: `git diff --name-only HEAD`
|
|
173
|
-
SET: {changedFiles} = result
|
|
174
|
-
|
|
175
|
-
#### 4.2 Review each file for issues
|
|
176
|
-
FOR each file in {changedFiles}:
|
|
177
|
-
BASH: `git diff HEAD -- {file}`
|
|
178
|
-
|
|
179
|
-
Analyze diff for:
|
|
180
|
-
- Missing error handling
|
|
181
|
-
- Security issues (hardcoded secrets, SQL injection, XSS)
|
|
182
|
-
- Logic errors
|
|
183
|
-
- Missing null checks
|
|
184
|
-
- Resource leaks
|
|
185
|
-
|
|
186
|
-
FOR each issue found:
|
|
187
|
-
ASSIGN confidence score (0-100):
|
|
188
|
-
- 90-100: Definite bug/security issue
|
|
189
|
-
- 70-89: Likely problem, should fix
|
|
190
|
-
- 50-69: Maybe a problem
|
|
191
|
-
- 0-49: Nitpick/style preference
|
|
192
|
-
|
|
193
|
-
#### 4.3 Filter and report
|
|
194
|
-
SET: {issues} = issues with confidence >= 70
|
|
195
|
-
|
|
196
|
-
IF {issues}.length > 0:
|
|
197
|
-
OUTPUT: """
|
|
198
|
-
## Code Review Results
|
|
199
|
-
|
|
200
|
-
Found {issues.length} issues (confidence >= 70%):
|
|
201
|
-
|
|
202
|
-
{FOR each issue:}
|
|
203
|
-
- [{confidence}%] {description}
|
|
204
|
-
File: {file}:{line}
|
|
205
|
-
{END FOR}
|
|
206
|
-
"""
|
|
207
|
-
|
|
208
|
-
IF `--blocking`:
|
|
209
|
-
OUTPUT: "Fix issues before shipping."
|
|
210
|
-
STOP
|
|
211
|
-
ELSE:
|
|
212
|
-
PROMPT: "Continue with ship? (y/n)"
|
|
213
|
-
IF no: STOP
|
|
214
|
-
ELSE:
|
|
215
|
-
OUTPUT: "Code review passed. No high-confidence issues found."
|
|
216
|
-
|
|
217
|
-
### Step 5: Version Bump
|
|
218
|
-
READ: `package.json` (or Cargo.toml, pyproject.toml)
|
|
219
|
-
EXTRACT: current version
|
|
220
|
-
|
|
221
|
-
BASH: `git log --oneline -10`
|
|
222
|
-
Determine bump type:
|
|
223
|
-
- "BREAKING" or "major:" → major
|
|
224
|
-
- "feat:" or "feature:" → minor
|
|
225
|
-
- else → patch
|
|
226
|
-
|
|
227
|
-
UPDATE version file with new version
|
|
228
|
-
|
|
229
|
-
### Step 6: Update CHANGELOG
|
|
230
|
-
BASH: `git log --oneline -20 --pretty=format:"- %s"`
|
|
231
|
-
INSERT new entry in CHANGELOG.md
|
|
232
|
-
|
|
233
|
-
### Step 7: Create Pull Request
|
|
234
|
-
|
|
235
|
-
#### 7.1 Check gh CLI
|
|
236
|
-
BASH: `which gh 2>/dev/null`
|
|
237
|
-
IF result empty:
|
|
238
|
-
OUTPUT:
|
|
239
|
-
```
|
|
240
|
-
⚠️ GitHub CLI (gh) not installed
|
|
241
|
-
|
|
242
|
-
Install: https://cli.github.com/
|
|
243
|
-
Or: brew install gh
|
|
244
|
-
|
|
245
|
-
After installing, run: gh auth login
|
|
246
|
-
```
|
|
247
|
-
STOP
|
|
248
|
-
|
|
249
|
-
#### 7.2 Check Authentication
|
|
250
|
-
BASH: `gh auth status 2>&1`
|
|
251
|
-
IF not authenticated:
|
|
252
|
-
OUTPUT: "Run `gh auth login` to authenticate with GitHub"
|
|
253
|
-
STOP
|
|
254
|
-
|
|
255
|
-
#### 7.3 Get Branch Info
|
|
256
|
-
READ: `{globalPath}/storage/state.json`
|
|
257
|
-
IF currentTask AND currentTask.branch:
|
|
258
|
-
SET: {branchName} = currentTask.branch.name
|
|
259
|
-
SET: {baseBranch} = currentTask.branch.baseBranch OR "main"
|
|
260
|
-
ELSE:
|
|
261
|
-
BASH: `git branch --show-current`
|
|
262
|
-
SET: {branchName} = result
|
|
263
|
-
SET: {baseBranch} = "main"
|
|
264
|
-
|
|
265
|
-
IF {branchName} == "main" OR {branchName} == "master":
|
|
266
|
-
OUTPUT:
|
|
267
|
-
```
|
|
268
|
-
⚠️ Cannot ship from protected branch: {branchName}
|
|
269
|
-
|
|
270
|
-
Create a feature branch first with /p:now "task name"
|
|
271
|
-
```
|
|
272
|
-
STOP
|
|
273
|
-
|
|
274
|
-
#### 7.4 Commit Changes
|
|
275
|
-
|
|
276
|
-
**CRITICAL: Include BOTH prjct footer AND Claude Code Co-Author**
|
|
277
|
-
|
|
278
|
-
BASH: `git add .`
|
|
279
|
-
|
|
280
|
-
BASH: `git commit -m "$(cat <<'EOF'
|
|
281
|
-
feat: {feature}
|
|
282
|
-
|
|
283
|
-
{code review summary if any issues were found}
|
|
284
|
-
|
|
285
|
-
🤖 Generated with [p/](https://www.prjct.app/)
|
|
286
|
-
Designed for [Claude](https://www.anthropic.com/claude)
|
|
287
|
-
|
|
288
|
-
EOF
|
|
289
|
-
)"`
|
|
290
|
-
|
|
291
|
-
**The commit MUST include:**
|
|
292
|
-
1. `🤖 Generated with [p/](https://www.prjct.app/)` - prjct signature (REQUIRED)
|
|
293
|
-
2. `Designed for [Claude](https://www.anthropic.com/claude)` - attribution
|
|
294
|
-
3. `Co-Authored-By: Claude <noreply@anthropic.com>` - Claude Code standard
|
|
295
|
-
|
|
296
|
-
#### 7.5 Push Branch
|
|
297
|
-
BASH: `git push -u origin {branchName}`
|
|
298
|
-
IF push fails:
|
|
299
|
-
OUTPUT: "Push failed. Check your git credentials or try: git pull --rebase"
|
|
300
|
-
STOP
|
|
301
|
-
|
|
302
|
-
#### 7.6 Create Pull Request
|
|
303
|
-
SET: {prTitle} = "feat: {feature}"
|
|
304
|
-
SET: {prBody} = """
|
|
305
|
-
## Summary
|
|
306
|
-
{feature description}
|
|
307
|
-
|
|
308
|
-
## Changes
|
|
309
|
-
- {totalLines} lines changed in {filesChanged} files
|
|
310
|
-
- Type: {changeType}
|
|
311
|
-
|
|
312
|
-
## Quality Checks
|
|
313
|
-
- Lint: {lintStatus}
|
|
314
|
-
- Tests: {testStatus}
|
|
315
|
-
- Review: {reviewStatus}
|
|
316
|
-
|
|
317
|
-
{IF issues found:}
|
|
318
|
-
### Review Notes
|
|
319
|
-
{list of issues found during code review}
|
|
320
|
-
{END IF}
|
|
321
|
-
|
|
322
|
-
---
|
|
323
|
-
🤖 Generated with [p/](https://www.prjct.app/)
|
|
324
|
-
Designed for [Claude](https://www.anthropic.com/claude)
|
|
325
|
-
"""
|
|
326
|
-
|
|
327
|
-
IF `--draft`:
|
|
328
|
-
SET: {draftFlag} = "--draft"
|
|
329
|
-
ELSE:
|
|
330
|
-
SET: {draftFlag} = ""
|
|
331
|
-
|
|
332
|
-
BASH: `gh pr create --title "{prTitle}" --base {baseBranch} {draftFlag} --body "$(cat <<'EOF'
|
|
333
|
-
{prBody}
|
|
334
|
-
EOF
|
|
335
|
-
)"`
|
|
336
|
-
|
|
337
|
-
IF command fails:
|
|
338
|
-
# PR might already exist
|
|
339
|
-
BASH: `gh pr view --json url,number`
|
|
340
|
-
IF exists:
|
|
341
|
-
EXTRACT: {prUrl}, {prNumber}
|
|
342
|
-
OUTPUT: "PR already exists: {prUrl}"
|
|
343
|
-
ELSE:
|
|
344
|
-
OUTPUT: "Failed to create PR. Check gh auth status."
|
|
345
|
-
STOP
|
|
346
|
-
ELSE:
|
|
347
|
-
EXTRACT: {prUrl} from output
|
|
348
|
-
EXTRACT: {prNumber} from output
|
|
349
|
-
|
|
350
|
-
OUTPUT: "📎 PR created: {prUrl}"
|
|
351
|
-
|
|
352
|
-
#### 7.7 Wait for CI Checks
|
|
353
|
-
OUTPUT: "Waiting for CI checks..."
|
|
354
|
-
|
|
355
|
-
SET: {maxWaitTime} = 600 # 10 minutes
|
|
356
|
-
SET: {checkInterval} = 30 # 30 seconds
|
|
357
|
-
SET: {elapsed} = 0
|
|
358
|
-
|
|
359
|
-
LOOP:
|
|
360
|
-
BASH: `gh pr checks {prNumber} --json name,state,conclusion 2>/dev/null || echo "[]"`
|
|
361
|
-
PARSE: {ciChecks}
|
|
362
|
-
|
|
363
|
-
IF {ciChecks} is empty OR all checks have conclusion:
|
|
364
|
-
# All checks completed
|
|
365
|
-
SET: {failedChecks} = checks where conclusion != "success" AND conclusion != "skipped"
|
|
366
|
-
|
|
367
|
-
IF {failedChecks}.length > 0:
|
|
368
|
-
SET: {ciStatus} = "failed"
|
|
369
|
-
OUTPUT:
|
|
370
|
-
```
|
|
371
|
-
❌ CI checks failed:
|
|
372
|
-
{FOR each failed check:}
|
|
373
|
-
- {name}: {conclusion}
|
|
374
|
-
{END FOR}
|
|
375
|
-
|
|
376
|
-
Fix issues and push again. PR: {prUrl}
|
|
377
|
-
```
|
|
378
|
-
→ Continue to Step 8 (don't stop, just record the failure)
|
|
379
|
-
ELSE:
|
|
380
|
-
SET: {ciStatus} = "passed"
|
|
381
|
-
OUTPUT: "✅ All CI checks passed"
|
|
382
|
-
BREAK
|
|
383
|
-
|
|
384
|
-
SET: {pendingCount} = checks where state == "pending" OR state == "queued"
|
|
385
|
-
OUTPUT: "⏳ Waiting for {pendingCount} CI checks..."
|
|
386
|
-
|
|
387
|
-
WAIT: {checkInterval} seconds
|
|
388
|
-
SET: {elapsed} = {elapsed} + {checkInterval}
|
|
389
|
-
|
|
390
|
-
IF {elapsed} >= {maxWaitTime}:
|
|
391
|
-
SET: {ciStatus} = "timeout"
|
|
392
|
-
OUTPUT: "⏰ CI still running after 10 minutes. Check PR: {prUrl}"
|
|
393
|
-
BREAK
|
|
394
|
-
|
|
395
|
-
#### 7.8 Update State with PR Info
|
|
396
|
-
READ: `{globalPath}/storage/state.json`
|
|
397
|
-
IF currentTask:
|
|
398
|
-
UPDATE currentTask.branch:
|
|
399
|
-
```json
|
|
400
|
-
{
|
|
401
|
-
"branch": {
|
|
402
|
-
...existing,
|
|
403
|
-
"prUrl": "{prUrl}",
|
|
404
|
-
"prNumber": {prNumber},
|
|
405
|
-
"ciStatus": "{ciStatus}"
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
```
|
|
409
|
-
WRITE: `{globalPath}/storage/state.json`
|
|
410
|
-
|
|
411
|
-
### Step 8: Update Storage and Workflow Checkpoints
|
|
412
|
-
GET timestamp: `bun -e "console.log(new Date().toISOString())" 2>/dev/null || node -e "console.log(new Date().toISOString())"`
|
|
413
|
-
GET uuid: `bun -e "console.log(crypto.randomUUID())" 2>/dev/null || node -e "console.log(require('crypto').randomUUID())"`
|
|
414
|
-
|
|
415
|
-
SET: {now} = timestamp
|
|
416
|
-
SET: {shippedId} = uuid
|
|
417
|
-
|
|
418
|
-
### 8.1 Update Workflow Checkpoints (if workflow exists)
|
|
419
|
-
READ: `{globalPath}/storage/state.json`
|
|
420
|
-
|
|
421
|
-
IF currentTask AND currentTask.workflow exists:
|
|
422
|
-
SET: currentTask.workflow.phase = "register"
|
|
423
|
-
|
|
424
|
-
### Set tag checkpoint
|
|
425
|
-
SET: currentTask.workflow.checkpoints.tag = {
|
|
426
|
-
"completedAt": "{now}",
|
|
427
|
-
"data": { "version": "{newVersion}", "tagName": "v{newVersion}" }
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
### Set release checkpoint
|
|
431
|
-
SET: currentTask.workflow.checkpoints.release = {
|
|
432
|
-
"completedAt": "{now}",
|
|
433
|
-
"data": { "prUrl": "{prUrl}", "prNumber": {prNumber} }
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
### Set deploy checkpoint (manual reminder)
|
|
437
|
-
SET: currentTask.workflow.checkpoints.deploy = {
|
|
438
|
-
"completedAt": "{now}",
|
|
439
|
-
"data": { "reminded": true, "manual": true }
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
### Set register checkpoint
|
|
443
|
-
SET: currentTask.workflow.checkpoints.register = {
|
|
444
|
-
"completedAt": "{now}",
|
|
445
|
-
"data": { "shippedId": "{shippedId}", "version": "{newVersion}" }
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
SET: currentTask.workflow.lastCheckpoint = "register"
|
|
449
|
-
|
|
450
|
-
WRITE: `{globalPath}/storage/state.json`
|
|
451
|
-
|
|
452
|
-
### Log workflow events
|
|
453
|
-
APPEND to `{globalPath}/memory/events.jsonl`:
|
|
454
|
-
```json
|
|
455
|
-
{"timestamp":"{now}","action":"phase_advanced","taskId":"{currentTask.id}","from":"merge","to":"register"}
|
|
456
|
-
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"tag","data":{"version":"{newVersion}"}}
|
|
457
|
-
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"release"}
|
|
458
|
-
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"deploy"}
|
|
459
|
-
{"timestamp":"{now}","action":"checkpoint_completed","taskId":"{currentTask.id}","checkpoint":"register"}
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
### 8.2 Update shipped.json
|
|
463
|
-
READ: `{globalPath}/storage/shipped.json` (or create default)
|
|
464
|
-
PREPEND new ship object:
|
|
465
|
-
```json
|
|
466
|
-
{
|
|
467
|
-
"id": "{shippedId}",
|
|
468
|
-
"name": "{feature}",
|
|
469
|
-
"version": "{newVersion}",
|
|
470
|
-
"shippedAt": "{now}",
|
|
471
|
-
"lint": "{lintStatus}",
|
|
472
|
-
"tests": "{testStatus}",
|
|
473
|
-
"branch": "{branchName}",
|
|
474
|
-
"prUrl": "{prUrl}",
|
|
475
|
-
"prNumber": {prNumber},
|
|
476
|
-
"ciStatus": "{ciStatus}",
|
|
477
|
-
"taskId": "{currentTask.id}"
|
|
478
|
-
}
|
|
479
|
-
```
|
|
480
|
-
WRITE: `{globalPath}/storage/shipped.json`
|
|
481
|
-
|
|
482
|
-
### 8.3 Generate context
|
|
483
|
-
WRITE: `{globalPath}/context/shipped.md`
|
|
484
|
-
|
|
485
|
-
### 8.4 Queue sync event
|
|
486
|
-
APPEND to `{globalPath}/sync/pending.json`:
|
|
487
|
-
```json
|
|
488
|
-
{"type":"feature.shipped","data":{"taskId":"{currentTask.id}","version":"{newVersion}","prUrl":"{prUrl}"},"timestamp":"{now}"}
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### 8.5 Deploy reminder
|
|
492
|
-
OUTPUT:
|
|
493
|
-
```
|
|
494
|
-
📦 Deploy Reminder
|
|
495
|
-
|
|
496
|
-
Version {newVersion} is ready to deploy.
|
|
497
|
-
|
|
498
|
-
Remember to deploy to your platform when ready.
|
|
499
|
-
```
|
|
500
|
-
|
|
501
|
-
### Step 9: Output
|
|
502
|
-
|
|
503
|
-
IF {ciStatus} == "passed":
|
|
7
|
+
```bash
|
|
8
|
+
prjct context ship $ARGUMENTS
|
|
504
9
|
```
|
|
505
|
-
🚀 Shipped: {feature}
|
|
506
|
-
|
|
507
|
-
Version: {oldVersion} → {newVersion}
|
|
508
|
-
Changes: {changeType} ({totalLines} lines in {filesChanged} files)
|
|
509
|
-
Quality: Lint {lintStatus} | Tests {testStatus}
|
|
510
|
-
CI: ✅ Passed
|
|
511
|
-
|
|
512
|
-
📎 PR: {prUrl}
|
|
513
|
-
|
|
514
|
-
Phase: register (10/11 checkpoints)
|
|
515
|
-
|
|
516
|
-
Workflow:
|
|
517
|
-
1. analyze ✓
|
|
518
|
-
2. branch ✓
|
|
519
|
-
3. implement ✓
|
|
520
|
-
4. test ✓
|
|
521
|
-
5. review ✓
|
|
522
|
-
6. merge ✓
|
|
523
|
-
7. tag ✓ - v{newVersion}
|
|
524
|
-
8. release ✓
|
|
525
|
-
9. deploy ✓ - (manual)
|
|
526
|
-
10. register ✓
|
|
527
|
-
11. verify ← next
|
|
528
10
|
|
|
529
|
-
|
|
530
|
-
```
|
|
11
|
+
IF `currentTask` active → Ask: "Complete and ship?" or "Cancel"
|
|
531
12
|
|
|
532
|
-
|
|
13
|
+
```bash
|
|
14
|
+
git status --porcelain # No changes? STOP
|
|
15
|
+
git diff --stat HEAD
|
|
533
16
|
```
|
|
534
|
-
⚠️ PR Created (CI Failed): {feature}
|
|
535
17
|
|
|
536
|
-
|
|
537
|
-
Quality: Lint {lintStatus} | Tests {testStatus}
|
|
538
|
-
CI: ❌ Failed
|
|
18
|
+
Run lint/tests if configured
|
|
539
19
|
|
|
540
|
-
|
|
20
|
+
IF not trivial → Review for security issues, error handling
|
|
541
21
|
|
|
542
|
-
|
|
543
|
-
|
|
22
|
+
Version bump (patch default, minor for feat:, major for BREAKING)
|
|
23
|
+
Update CHANGELOG.md
|
|
544
24
|
|
|
545
|
-
|
|
25
|
+
```bash
|
|
26
|
+
gh auth status # Not auth? STOP
|
|
27
|
+
git branch --show-current # On main? STOP
|
|
546
28
|
```
|
|
547
|
-
🚀 PR Created: {feature}
|
|
548
|
-
|
|
549
|
-
Version: {oldVersion} → {newVersion}
|
|
550
|
-
Quality: Lint {lintStatus} | Tests {testStatus}
|
|
551
|
-
CI: ⏳ Still running
|
|
552
29
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
Check CI status on GitHub.
|
|
30
|
+
Commit with footer:
|
|
556
31
|
```
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
| Error | Response | Action |
|
|
561
|
-
|-------|----------|--------|
|
|
562
|
-
| No git repo | "Not a git repository" | STOP |
|
|
563
|
-
| No changes | "No changes to ship" | STOP |
|
|
564
|
-
| On protected branch | "Cannot ship from main/master" | STOP |
|
|
565
|
-
| gh CLI not installed | Show install instructions | STOP |
|
|
566
|
-
| gh not authenticated | "Run gh auth login" | STOP |
|
|
567
|
-
| Lint/test fails (blocking) | "Quality checks failed" | STOP |
|
|
568
|
-
| Lint/test fails (non-blocking) | Show warning | CONTINUE |
|
|
569
|
-
| Code review finds issues (blocking) | "Fix issues before shipping" | STOP |
|
|
570
|
-
| Code review finds issues (non-blocking) | Prompt to continue | ASK |
|
|
571
|
-
| Push fails | "Push failed. Try: git pull --rebase" | STOP |
|
|
572
|
-
| PR creation fails | Check if PR exists | CONTINUE |
|
|
573
|
-
| CI fails | Show failed checks, record in storage | CONTINUE |
|
|
574
|
-
| CI timeout | Show PR URL, continue | CONTINUE |
|
|
575
|
-
|
|
576
|
-
## Examples
|
|
577
|
-
|
|
578
|
-
### Example 1: Successful Ship with PR
|
|
579
|
-
```
|
|
580
|
-
/p:ship "add user auth"
|
|
581
|
-
|
|
582
|
-
Pre-flight: Medium changes (87 lines in 5 files)
|
|
583
|
-
Quality: Lint ✅ | Tests ✅
|
|
584
|
-
Review: Passed
|
|
585
|
-
|
|
586
|
-
📎 PR created: https://github.com/user/repo/pull/42
|
|
587
|
-
Waiting for CI checks...
|
|
588
|
-
⏳ Waiting for 3 CI checks...
|
|
589
|
-
✅ All CI checks passed
|
|
590
|
-
|
|
591
|
-
🚀 PR Ready: add user auth
|
|
592
|
-
|
|
593
|
-
Version: 1.2.0 → 1.3.0
|
|
594
|
-
Changes: medium (87 lines in 5 files)
|
|
595
|
-
Quality: Lint ✅ | Tests ✅
|
|
596
|
-
CI: ✅ Passed
|
|
597
|
-
|
|
598
|
-
📎 PR: https://github.com/user/repo/pull/42
|
|
599
|
-
|
|
600
|
-
Next steps:
|
|
601
|
-
1. Request review from team
|
|
602
|
-
2. Merge when approved
|
|
603
|
-
```
|
|
604
|
-
|
|
605
|
-
### Example 2: Ship with CI Failure
|
|
606
|
-
```
|
|
607
|
-
/p:ship "fix login bug"
|
|
608
|
-
|
|
609
|
-
Pre-flight: Small changes (28 lines in 2 files)
|
|
610
|
-
Quality: Lint ✅ | Tests ✅
|
|
611
|
-
Review: Passed
|
|
612
|
-
|
|
613
|
-
📎 PR created: https://github.com/user/repo/pull/43
|
|
614
|
-
Waiting for CI checks...
|
|
615
|
-
|
|
616
|
-
❌ CI checks failed:
|
|
617
|
-
- build: failure
|
|
618
|
-
- test: failure
|
|
619
|
-
|
|
620
|
-
⚠️ PR Created (CI Failed): fix login bug
|
|
621
|
-
|
|
622
|
-
📎 PR: https://github.com/user/repo/pull/43
|
|
623
|
-
|
|
624
|
-
Fix CI issues and push again.
|
|
32
|
+
🤖 Generated with [p/](https://www.prjct.app/)
|
|
33
|
+
Designed for [Claude](https://www.anthropic.com/claude)
|
|
625
34
|
```
|
|
626
35
|
|
|
627
|
-
|
|
36
|
+
```bash
|
|
37
|
+
git add . && git commit && git push -u origin {branch}
|
|
38
|
+
gh pr create --title "feat: {feature}" --base main
|
|
628
39
|
```
|
|
629
|
-
/p:ship "new feature"
|
|
630
40
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
Create a feature branch first with /p:now "task name"
|
|
41
|
+
**Output**:
|
|
634
42
|
```
|
|
43
|
+
🚀 Shipped: {feature}
|
|
635
44
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
📎 PR created (draft): https://github.com/user/repo/pull/44
|
|
641
|
-
|
|
642
|
-
🚀 PR Created: work in progress
|
|
643
|
-
CI: ⏳ Still running
|
|
45
|
+
Version: {old} → {new}
|
|
46
|
+
PR: {url}
|
|
47
|
+
CI: {status}
|
|
644
48
|
|
|
645
|
-
|
|
49
|
+
Next:
|
|
50
|
+
- CI failed? → Fix and push again
|
|
51
|
+
- Merge ready? → `p. merge` or merge in GitHub
|
|
52
|
+
- New task? → `p. task "description"`
|
|
646
53
|
```
|
|
647
|
-
|
|
648
|
-
## References
|
|
649
|
-
- Architecture details: `~/.prjct-cli/docs/architecture.md`
|
|
650
|
-
- Validation patterns: `~/.prjct-cli/docs/validation.md`
|