prjct-cli 0.21.0 → 0.23.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.
@@ -1,19 +1,20 @@
1
1
  ---
2
- allowed-tools: [Read, Write, Bash, Glob, Grep]
3
- description: 'Ship feature with automated workflow'
2
+ allowed-tools: [Read, Write, Bash, Glob, Grep, AskUserQuestion]
3
+ description: 'Ship feature with automated PR workflow'
4
4
  ---
5
5
 
6
6
  # /p:ship - Ship Feature
7
7
 
8
- Ship completed work with pre-flight checks, code review, and quality gates.
8
+ Ship completed work with pre-flight checks, code review, PR creation, and CI verification.
9
9
 
10
10
  ## Usage
11
11
  ```
12
- /p:ship [feature] [--blocking] [--skip-review]
12
+ /p:ship [feature] [--blocking] [--skip-review] [--draft]
13
13
  ```
14
14
  - `feature`: Name of the feature being shipped (required)
15
15
  - `--blocking`: Abort if any check fails
16
16
  - `--skip-review`: Skip code review (for trivial changes)
17
+ - `--draft`: Create PR as draft
17
18
 
18
19
  ## Flow
19
20
 
@@ -135,14 +136,171 @@ UPDATE version file with new version
135
136
  BASH: `git log --oneline -20 --pretty=format:"- %s"`
136
137
  INSERT new entry in CHANGELOG.md
137
138
 
138
- ### Step 7: Git Commit & Push
139
+ ### Step 7: Create Pull Request
140
+
141
+ #### 7.1 Check gh CLI
142
+ BASH: `which gh 2>/dev/null`
143
+ IF result empty:
144
+ OUTPUT:
145
+ ```
146
+ ⚠️ GitHub CLI (gh) not installed
147
+
148
+ Install: https://cli.github.com/
149
+ Or: brew install gh
150
+
151
+ After installing, run: gh auth login
152
+ ```
153
+ STOP
154
+
155
+ #### 7.2 Check Authentication
156
+ BASH: `gh auth status 2>&1`
157
+ IF not authenticated:
158
+ OUTPUT: "Run `gh auth login` to authenticate with GitHub"
159
+ STOP
160
+
161
+ #### 7.3 Get Branch Info
162
+ READ: `{globalPath}/storage/state.json`
163
+ IF currentTask AND currentTask.branch:
164
+ SET: {branchName} = currentTask.branch.name
165
+ SET: {baseBranch} = currentTask.branch.baseBranch OR "main"
166
+ ELSE:
167
+ BASH: `git branch --show-current`
168
+ SET: {branchName} = result
169
+ SET: {baseBranch} = "main"
170
+
171
+ IF {branchName} == "main" OR {branchName} == "master":
172
+ OUTPUT:
173
+ ```
174
+ ⚠️ Cannot ship from protected branch: {branchName}
175
+
176
+ Create a feature branch first with /p:now "task name"
177
+ ```
178
+ STOP
179
+
180
+ #### 7.4 Commit Changes
139
181
  BASH: `git add .`
140
- BASH: `git commit -m "feat: Ship {feature} v{newVersion}
182
+ BASH: `git commit -m "feat: {feature}
183
+
184
+ {code review summary if any issues were found}
141
185
 
142
186
  🤖 Generated with [p/](https://www.prjct.app/)
143
187
  Designed for [Claude](https://www.anthropic.com/claude)
144
188
  "`
145
- BASH: `git push`
189
+
190
+ #### 7.5 Push Branch
191
+ BASH: `git push -u origin {branchName}`
192
+ IF push fails:
193
+ OUTPUT: "Push failed. Check your git credentials or try: git pull --rebase"
194
+ STOP
195
+
196
+ #### 7.6 Create Pull Request
197
+ SET: {prTitle} = "feat: {feature}"
198
+ SET: {prBody} = """
199
+ ## Summary
200
+ {feature description}
201
+
202
+ ## Changes
203
+ - {totalLines} lines changed in {filesChanged} files
204
+ - Type: {changeType}
205
+
206
+ ## Quality Checks
207
+ - Lint: {lintStatus}
208
+ - Tests: {testStatus}
209
+ - Review: {reviewStatus}
210
+
211
+ {IF issues found:}
212
+ ### Review Notes
213
+ {list of issues found during code review}
214
+ {END IF}
215
+
216
+ ---
217
+ 🤖 Generated with [p/](https://www.prjct.app/)
218
+ Designed for [Claude](https://www.anthropic.com/claude)
219
+ """
220
+
221
+ IF `--draft`:
222
+ SET: {draftFlag} = "--draft"
223
+ ELSE:
224
+ SET: {draftFlag} = ""
225
+
226
+ BASH: `gh pr create --title "{prTitle}" --base {baseBranch} {draftFlag} --body "$(cat <<'EOF'
227
+ {prBody}
228
+ EOF
229
+ )"`
230
+
231
+ IF command fails:
232
+ # PR might already exist
233
+ BASH: `gh pr view --json url,number`
234
+ IF exists:
235
+ EXTRACT: {prUrl}, {prNumber}
236
+ OUTPUT: "PR already exists: {prUrl}"
237
+ ELSE:
238
+ OUTPUT: "Failed to create PR. Check gh auth status."
239
+ STOP
240
+ ELSE:
241
+ EXTRACT: {prUrl} from output
242
+ EXTRACT: {prNumber} from output
243
+
244
+ OUTPUT: "📎 PR created: {prUrl}"
245
+
246
+ #### 7.7 Wait for CI Checks
247
+ OUTPUT: "Waiting for CI checks..."
248
+
249
+ SET: {maxWaitTime} = 600 # 10 minutes
250
+ SET: {checkInterval} = 30 # 30 seconds
251
+ SET: {elapsed} = 0
252
+
253
+ LOOP:
254
+ BASH: `gh pr checks {prNumber} --json name,state,conclusion 2>/dev/null || echo "[]"`
255
+ PARSE: {ciChecks}
256
+
257
+ IF {ciChecks} is empty OR all checks have conclusion:
258
+ # All checks completed
259
+ SET: {failedChecks} = checks where conclusion != "success" AND conclusion != "skipped"
260
+
261
+ IF {failedChecks}.length > 0:
262
+ SET: {ciStatus} = "failed"
263
+ OUTPUT:
264
+ ```
265
+ ❌ CI checks failed:
266
+ {FOR each failed check:}
267
+ - {name}: {conclusion}
268
+ {END FOR}
269
+
270
+ Fix issues and push again. PR: {prUrl}
271
+ ```
272
+ → Continue to Step 8 (don't stop, just record the failure)
273
+ ELSE:
274
+ SET: {ciStatus} = "passed"
275
+ OUTPUT: "✅ All CI checks passed"
276
+ BREAK
277
+
278
+ SET: {pendingCount} = checks where state == "pending" OR state == "queued"
279
+ OUTPUT: "⏳ Waiting for {pendingCount} CI checks..."
280
+
281
+ WAIT: {checkInterval} seconds
282
+ SET: {elapsed} = {elapsed} + {checkInterval}
283
+
284
+ IF {elapsed} >= {maxWaitTime}:
285
+ SET: {ciStatus} = "timeout"
286
+ OUTPUT: "⏰ CI still running after 10 minutes. Check PR: {prUrl}"
287
+ BREAK
288
+
289
+ #### 7.8 Update State with PR Info
290
+ READ: `{globalPath}/storage/state.json`
291
+ IF currentTask:
292
+ UPDATE currentTask.branch:
293
+ ```json
294
+ {
295
+ "branch": {
296
+ ...existing,
297
+ "prUrl": "{prUrl}",
298
+ "prNumber": {prNumber},
299
+ "ciStatus": "{ciStatus}"
300
+ }
301
+ }
302
+ ```
303
+ WRITE: `{globalPath}/storage/state.json`
146
304
 
147
305
  ### Step 8: Update Storage
148
306
  GET timestamp: `bun -e "console.log(new Date().toISOString())" 2>/dev/null || node -e "console.log(new Date().toISOString())"`
@@ -157,7 +315,11 @@ PREPEND new ship object:
157
315
  "version": "{newVersion}",
158
316
  "shippedAt": "{timestamp}",
159
317
  "lint": "{lintStatus}",
160
- "tests": "{testStatus}"
318
+ "tests": "{testStatus}",
319
+ "branch": "{branchName}",
320
+ "prUrl": "{prUrl}",
321
+ "prNumber": {prNumber},
322
+ "ciStatus": "{ciStatus}"
161
323
  }
162
324
  ```
163
325
  WRITE: `{globalPath}/storage/shipped.json`
@@ -172,15 +334,49 @@ Log to memory:
172
334
  APPEND to `{globalPath}/memory/events.jsonl`
173
335
 
174
336
  ### Step 9: Output
337
+
338
+ IF {ciStatus} == "passed":
175
339
  ```
176
- 🚀 Shipped: {feature}
340
+ 🚀 PR Ready: {feature}
177
341
 
178
342
  Version: {oldVersion} → {newVersion}
179
343
  Changes: {changeType} ({totalLines} lines in {filesChanged} files)
180
344
  Quality: Lint {lintStatus} | Tests {testStatus}
181
- Review: {reviewStatus}
345
+ CI: ✅ Passed
346
+
347
+ 📎 PR: {prUrl}
348
+
349
+ Next steps:
350
+ 1. Request review from team
351
+ 2. Merge when approved
352
+
353
+ /p:done to close task | /p:next for more work
354
+ ```
182
355
 
183
- Next: /p:feature | /p:recap
356
+ IF {ciStatus} == "failed":
357
+ ```
358
+ ⚠️ PR Created (CI Failed): {feature}
359
+
360
+ Version: {oldVersion} → {newVersion}
361
+ Quality: Lint {lintStatus} | Tests {testStatus}
362
+ CI: ❌ Failed
363
+
364
+ 📎 PR: {prUrl}
365
+
366
+ Fix CI issues and push again.
367
+ ```
368
+
369
+ IF {ciStatus} == "timeout":
370
+ ```
371
+ 🚀 PR Created: {feature}
372
+
373
+ Version: {oldVersion} → {newVersion}
374
+ Quality: Lint {lintStatus} | Tests {testStatus}
375
+ CI: ⏳ Still running
376
+
377
+ 📎 PR: {prUrl}
378
+
379
+ Check CI status on GitHub.
184
380
  ```
185
381
 
186
382
  ## Error Handling
@@ -189,58 +385,88 @@ Next: /p:feature | /p:recap
189
385
  |-------|----------|--------|
190
386
  | No git repo | "Not a git repository" | STOP |
191
387
  | No changes | "No changes to ship" | STOP |
388
+ | On protected branch | "Cannot ship from main/master" | STOP |
389
+ | gh CLI not installed | Show install instructions | STOP |
390
+ | gh not authenticated | "Run gh auth login" | STOP |
192
391
  | Lint/test fails (blocking) | "Quality checks failed" | STOP |
193
392
  | Lint/test fails (non-blocking) | Show warning | CONTINUE |
194
393
  | Code review finds issues (blocking) | "Fix issues before shipping" | STOP |
195
394
  | Code review finds issues (non-blocking) | Prompt to continue | ASK |
196
- | Push fails | "Push failed. Try: git pull --rebase" | CONTINUE |
395
+ | Push fails | "Push failed. Try: git pull --rebase" | STOP |
396
+ | PR creation fails | Check if PR exists | CONTINUE |
397
+ | CI fails | Show failed checks, record in storage | CONTINUE |
398
+ | CI timeout | Show PR URL, continue | CONTINUE |
197
399
 
198
400
  ## Examples
199
401
 
200
- ### Example 1: Trivial Change (auto-skip review)
402
+ ### Example 1: Successful Ship with PR
201
403
  ```
202
- /p:ship "fix typo"
404
+ /p:ship "add user auth"
203
405
 
204
- Pre-flight: Trivial changes (3 lines in 1 file)
406
+ Pre-flight: Medium changes (87 lines in 5 files)
205
407
  Quality: Lint ✅ | Tests ✅
206
- Review: Skipped (trivial)
408
+ Review: Passed
207
409
 
208
- 🚀 Shipped: fix typo
209
- Version: 1.2.0 1.2.1
210
- ```
410
+ 📎 PR created: https://github.com/user/repo/pull/42
411
+ Waiting for CI checks...
412
+ ⏳ Waiting for 3 CI checks...
413
+ ✅ All CI checks passed
211
414
 
212
- ### Example 2: Medium Change (with review)
213
- ```
214
- /p:ship "add auth"
415
+ 🚀 PR Ready: add user auth
215
416
 
216
- Pre-flight: Medium changes (87 lines in 5 files)
417
+ Version: 1.2.0 1.3.0
418
+ Changes: medium (87 lines in 5 files)
217
419
  Quality: Lint ✅ | Tests ✅
218
- Review: Running...
420
+ CI: ✅ Passed
219
421
 
220
- ## Code Review Results
221
- Found 2 issues (confidence >= 70%):
222
- - [85%] Missing error handling in OAuth callback
223
- File: src/auth/oauth.ts:67
224
- - [72%] Token not validated before use
225
- File: src/auth/validate.ts:23
422
+ 📎 PR: https://github.com/user/repo/pull/42
226
423
 
227
- Continue with ship? (y/n)
424
+ Next steps:
425
+ 1. Request review from team
426
+ 2. Merge when approved
228
427
  ```
229
428
 
230
- ### Example 3: Blocking Mode
429
+ ### Example 2: Ship with CI Failure
231
430
  ```
232
- /p:ship "deploy script" --blocking
431
+ /p:ship "fix login bug"
233
432
 
234
433
  Pre-flight: Small changes (28 lines in 2 files)
235
434
  Quality: Lint ✅ | Tests ✅
236
- Review: Running...
435
+ Review: Passed
436
+
437
+ 📎 PR created: https://github.com/user/repo/pull/43
438
+ Waiting for CI checks...
439
+
440
+ ❌ CI checks failed:
441
+ - build: failure
442
+ - test: failure
443
+
444
+ ⚠️ PR Created (CI Failed): fix login bug
445
+
446
+ 📎 PR: https://github.com/user/repo/pull/43
447
+
448
+ Fix CI issues and push again.
449
+ ```
450
+
451
+ ### Example 3: Blocked on Protected Branch
452
+ ```
453
+ /p:ship "new feature"
454
+
455
+ ⚠️ Cannot ship from protected branch: main
456
+
457
+ Create a feature branch first with /p:now "task name"
458
+ ```
459
+
460
+ ### Example 4: Draft PR
461
+ ```
462
+ /p:ship "work in progress" --draft
463
+
464
+ 📎 PR created (draft): https://github.com/user/repo/pull/44
237
465
 
238
- ## Code Review Results
239
- Found 1 issue (confidence >= 70%):
240
- - [95%] Hardcoded credentials detected
241
- File: scripts/deploy.sh:12
466
+ 🚀 PR Created: work in progress
467
+ CI: Still running
242
468
 
243
- Fix issues before shipping.
469
+ 📎 PR: https://github.com/user/repo/pull/44
244
470
  ```
245
471
 
246
472
  ## References
@@ -0,0 +1,116 @@
1
+ ---
2
+ allowed-tools: [Read, Bash]
3
+ description: 'Push prjct data to Notion databases'
4
+ timestamp-rule: 'GetTimestamp() for all timestamps'
5
+ ---
6
+
7
+ # /p:notion push - Push Data to Notion
8
+
9
+ ## Purpose
10
+
11
+ Manually sync all prjct data to Notion databases:
12
+ - Shipped features → Shipped Features database
13
+ - Ideas → Ideas database
14
+ - Queue tasks → Active Tasks database (optional)
15
+
16
+ ## Prerequisites
17
+
18
+ 1. Notion integration configured (`/p:notion setup`)
19
+ 2. Token stored in `~/.prjct-cli/config/notion.json`
20
+
21
+ ## Flow
22
+
23
+ ### Step 1: Check Config
24
+
25
+ READ: `.prjct/prjct.config.json` → extract `projectId`
26
+ READ: `~/.prjct-cli/projects/{projectId}/project.json`
27
+
28
+ IF `integrations.notion.enabled !== true`:
29
+ OUTPUT: "Notion not configured. Run /p:notion setup first."
30
+ STOP
31
+
32
+ ### Step 2: Load Token
33
+
34
+ READ: `~/.prjct-cli/config/notion.json` → extract `token`
35
+
36
+ IF no token:
37
+ OUTPUT: "Notion token not found. Run /p:notion setup first."
38
+ STOP
39
+
40
+ ### Step 3: Load Data
41
+
42
+ READ: `~/.prjct-cli/projects/{projectId}/storage/shipped.json`
43
+ READ: `~/.prjct-cli/projects/{projectId}/storage/ideas.json`
44
+
45
+ ### Step 4: Push to Notion
46
+
47
+ For each shipped feature:
48
+ ```bash
49
+ curl -X POST "https://api.notion.com/v1/pages" \
50
+ -H "Authorization: Bearer {token}" \
51
+ -H "Notion-Version: 2022-06-28" \
52
+ -H "Content-Type: application/json" \
53
+ -d '{
54
+ "parent": { "database_id": "{databases.shipped}" },
55
+ "properties": {
56
+ "Name": { "title": [{ "text": { "content": "{feature.name}" } }] },
57
+ "Project": { "select": { "name": "{projectName}" } },
58
+ "Type": { "select": { "name": "{feature.type}" } },
59
+ "Version": { "rich_text": [{ "text": { "content": "{feature.version}" } }] },
60
+ "Shipped Date": { "date": { "start": "{feature.shippedAt}" } }
61
+ }
62
+ }'
63
+ ```
64
+
65
+ For each idea:
66
+ ```bash
67
+ curl -X POST "https://api.notion.com/v1/pages" \
68
+ -H "Authorization: Bearer {token}" \
69
+ -H "Notion-Version: 2022-06-28" \
70
+ -H "Content-Type: application/json" \
71
+ -d '{
72
+ "parent": { "database_id": "{databases.ideas}" },
73
+ "properties": {
74
+ "Name": { "title": [{ "text": { "content": "{idea.text}" } }] },
75
+ "Project": { "select": { "name": "{projectName}" } },
76
+ "Status": { "select": { "name": "{idea.status}" } },
77
+ "Created": { "date": { "start": "{idea.addedAt}" } }
78
+ }
79
+ }'
80
+ ```
81
+
82
+ ### Step 5: Report Results
83
+
84
+ ```
85
+ ✅ Notion Push Complete
86
+
87
+ Shipped Features: {shipped.count} synced
88
+ Ideas: {ideas.count} synced
89
+
90
+ View in Notion: {dashboardUrl}
91
+ ```
92
+
93
+ ## Response (Success)
94
+
95
+ ```
96
+ ✅ Notion Push Complete
97
+
98
+ 📦 Shipped: 11 features synced
99
+ 💡 Ideas: 1 idea synced
100
+
101
+ Dashboard: https://notion.so/...
102
+ ```
103
+
104
+ ## Response (No Data)
105
+
106
+ ```
107
+ Nothing to push. Add features or ideas first.
108
+ ```
109
+
110
+ ## Error Handling
111
+
112
+ | Error | Response |
113
+ |-------|----------|
114
+ | Not configured | "Run /p:notion setup first" |
115
+ | Token invalid | "Token expired. Run /p:notion setup again" |
116
+ | API error | Show error, suggest retry |
@@ -76,7 +76,7 @@ Ensure the token starts with "ntn_" or "secret_".
76
76
  ```
77
77
  Now share a Notion page with your integration:
78
78
 
79
- 1. Open a Notion page where you want the databases
79
+ 1. Create a new page in Notion named "prjct: {projectName}"
80
80
  2. Click "..." → "Connect to" → select "prjct-cli"
81
81
  3. Copy the page URL or ID
82
82
 
@@ -87,18 +87,25 @@ Parse page ID from URL:
87
87
  - `https://notion.so/workspace/Page-Title-abc123...` → `abc123...`
88
88
  - Just the 32-character ID is also valid
89
89
 
90
- ### Step 5: Create Databases
90
+ ### Step 5: Create Project Databases
91
91
 
92
- Create 4 databases under the parent page:
92
+ Create 4 databases + 1 dashboard under the parent page.
93
+ Each project gets its own set of databases (not shared).
93
94
 
94
- | Database | Description |
95
- |----------|-------------|
96
- | prjct: Shipped Features | Track shipped features with metrics |
97
- | prjct: Roadmap | Feature planning and progress |
98
- | prjct: Ideas | Captured ideas and status |
99
- | prjct: Active Tasks | Current task queue |
95
+ | Created | Name | Description |
96
+ |---------|------|-------------|
97
+ | Dashboard | {projectName}: Dashboard | Metrics + links to all DBs |
98
+ | Database | {projectName}: Shipped Features | Track shipped features with metrics |
99
+ | Database | {projectName}: Roadmap | Feature planning and progress |
100
+ | Database | {projectName}: Ideas | Captured ideas and status |
101
+ | Database | {projectName}: Active Tasks | Current task queue |
100
102
 
101
- Each database has project-specific columns for multi-project support.
103
+ The dashboard shows:
104
+ - Total features shipped
105
+ - Ideas pendientes
106
+ - Tareas activas
107
+ - Progreso del roadmap
108
+ - Links a cada database
102
109
 
103
110
  ### Step 6: Save Config
104
111
 
@@ -150,17 +157,18 @@ Or create `~/.prjct-cli/config/notion.json`:
150
157
  ✅ Notion Connected
151
158
 
152
159
  Workspace: {workspaceName}
153
- Created: 4 databases
160
+ Project: {projectName}
161
+ Created: 1 dashboard + 4 databases
154
162
 
155
- Databases:
156
- prjct: Shipped Features
157
- prjct: Roadmap
158
- prjct: Ideas
159
- prjct: Active Tasks
163
+ • {projectName}: Dashboard (with metrics)
164
+ {projectName}: Shipped Features
165
+ {projectName}: Roadmap
166
+ {projectName}: Ideas
167
+ {projectName}: Active Tasks
160
168
 
161
169
  Auto-sync enabled:
162
- • On /p:ship → Shipped Features
163
- • On /p:idea → Ideas
170
+ • On /p:ship → Shipped Features + Dashboard metrics
171
+ • On /p:idea → Ideas + Dashboard metrics
164
172
 
165
173
  To sync all existing data: /p:notion sync
166
174
  ```