@champpaba/claude-agent-kit 2.0.1 → 2.1.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/.claude/CLAUDE.md CHANGED
@@ -103,6 +103,13 @@ Universal, framework-agnostic template for AI-assisted development.
103
103
  - `/cdev {change-id}` - Start/continue multi-agent development
104
104
  - `/cview {change-id}` - View detailed progress for a change
105
105
  - `/cstatus {change-id}` - Quick progress status for a change
106
+ - `/pstatus` - Update PROJECT_STATUS.yml (cross-session context)
107
+
108
+ **Cross-Session Context (v2.1.0):**
109
+ - `PROJECT_STATUS.yml` (project root) - Quick context snapshot for new sessions
110
+ - Contains: infrastructure state, blockers, completed work, next priorities
111
+ - Created by: `cak init` (optional) or manually
112
+ - Updated by: `/pstatus` command or Main Claude prompts
106
113
 
107
114
  **Best Practices (Dynamic):**
108
115
  - `.claude/contexts/domain/project/best-practices/` (auto-generated by `/csetup`)
@@ -378,4 +385,54 @@ Beyond the 6 agent files, these supporting files were also updated:
378
385
 
379
386
  ---
380
387
 
388
+ ## šŸ“Š PROJECT_STATUS.yml Protocol (v2.1.0)
389
+
390
+ **WHY this exists:** New Claude sessions lose context about infrastructure state, blockers, and priorities. This file provides a quick snapshot.
391
+
392
+ ### Session Start Behavior
393
+
394
+ If `PROJECT_STATUS.yml` exists in project root:
395
+ 1. Read it first before other files
396
+ 2. Note: `current_focus`, `blockers`, `infrastructure` state
397
+ 3. If `last_updated` > 7 days (or `_config.stale_warning_days`) → Suggest: "PROJECT_STATUS.yml may be outdated. Run /pstatus?"
398
+
399
+ ### Intelligent Update Prompts
400
+
401
+ Prompt "Update PROJECT_STATUS.yml?" when detecting these patterns:
402
+
403
+ | Event Detected | What to Update |
404
+ |----------------|----------------|
405
+ | After `/openspec:archive` completes | Add to `completed_changes` |
406
+ | User says "waiting for...", "need X from...", "blocked by..." | Add to `blockers` |
407
+ | User mentions blocker resolved | Remove from `blockers` |
408
+ | Infrastructure change (deploy, tunnel, DB migration) | Update `infrastructure` |
409
+ | User discusses priority shift | Update `next_priorities` |
410
+ | `/csetup {change-id}` started | Update `current_focus.active_change` |
411
+
412
+ ### Update Protocol
413
+
414
+ - Always ask before modifying (user confirms)
415
+ - Use `/pstatus` for comprehensive review
416
+ - Keep updates atomic (one section at a time during work)
417
+ - Auto-detect archived changes not listed and suggest additions
418
+
419
+ ### Example Interaction
420
+
421
+ ```
422
+ # Session start
423
+ Claude: *reads PROJECT_STATUS.yml*
424
+ Claude: "I see auth-system is active, tunnel running but waiting for domain."
425
+
426
+ # During work
427
+ User: "Domain is now configured"
428
+ Claude: "Update PROJECT_STATUS.yml?
429
+ - Remove 'domain' from blockers
430
+ - Update cloudflare_tunnel.waiting_for to null"
431
+
432
+ # After archiving
433
+ Claude: "Auth-system archived. Add to completed_changes?"
434
+ ```
435
+
436
+ ---
437
+
381
438
  **šŸ’” Remember:** This template is universal. Use Context7 for framework-specific docs!
@@ -35,6 +35,81 @@ If not found:
35
35
  Please create the change with OpenSpec first
36
36
  ```
37
37
 
38
+ ### Step 1.5: Read PROJECT_STATUS.yml (v2.1.0)
39
+
40
+ **WHY:** Cross-session context helps understand blockers and infrastructure state before starting work.
41
+
42
+ ```typescript
43
+ const projectStatusPath = 'PROJECT_STATUS.yml'
44
+
45
+ if (fileExists(projectStatusPath)) {
46
+ const projectStatus = parseYaml(Read(projectStatusPath))
47
+
48
+ output(`\nšŸ“Š Project Context (from PROJECT_STATUS.yml)`)
49
+
50
+ // Show current focus
51
+ if (projectStatus.current_focus?.description) {
52
+ output(` Focus: ${projectStatus.current_focus.description}`)
53
+ }
54
+
55
+ // Check for blockers that might affect this change
56
+ if (projectStatus.blockers?.length > 0) {
57
+ const relevantBlockers = projectStatus.blockers.filter(b =>
58
+ b.blocks?.some(blocked =>
59
+ blocked.toLowerCase().includes(changeId.toLowerCase()) ||
60
+ changeId.toLowerCase().includes(blocked.toLowerCase())
61
+ )
62
+ )
63
+
64
+ if (relevantBlockers.length > 0) {
65
+ output(`\n āš ļø Potential blockers for this change:`)
66
+ relevantBlockers.forEach(b => {
67
+ output(` - ${b.id}: ${b.description}`)
68
+ })
69
+ output(`\n Consider resolving blockers before starting.`)
70
+ }
71
+ }
72
+
73
+ // Show infrastructure status summary
74
+ if (projectStatus.infrastructure) {
75
+ const downServices = Object.entries(projectStatus.infrastructure)
76
+ .filter(([_, info]) => info.status === 'down' || info.status === 'degraded')
77
+
78
+ if (downServices.length > 0) {
79
+ output(`\n āš ļø Infrastructure issues:`)
80
+ downServices.forEach(([service, info]) => {
81
+ output(` - ${service}: ${info.status}${info.notes ? ` (${info.notes})` : ''}`)
82
+ })
83
+ }
84
+ }
85
+
86
+ // Check stale status
87
+ const lastUpdated = new Date(projectStatus.last_updated)
88
+ const daysSinceUpdate = Math.floor((Date.now() - lastUpdated) / (1000 * 60 * 60 * 24))
89
+ const staleThreshold = projectStatus._config?.stale_warning_days || 7
90
+
91
+ if (daysSinceUpdate > staleThreshold) {
92
+ output(`\n ā„¹ļø PROJECT_STATUS.yml last updated ${daysSinceUpdate} days ago.`)
93
+ output(` Consider running /pstatus to refresh.`)
94
+ }
95
+
96
+ // Update active change
97
+ if (projectStatus.current_focus?.active_change !== changeId) {
98
+ output(`\n šŸ“ Update current_focus.active_change to "${changeId}"? (yes/no)`)
99
+ const updateFocus = await askUser()
100
+ if (updateFocus) {
101
+ projectStatus.current_focus = projectStatus.current_focus || {}
102
+ projectStatus.current_focus.active_change = changeId
103
+ projectStatus.last_updated = new Date().toISOString().split('T')[0]
104
+ Write(projectStatusPath, toYaml(projectStatus))
105
+ output(` āœ… Updated active_change to "${changeId}"`)
106
+ }
107
+ }
108
+
109
+ output(``) // Blank line
110
+ }
111
+ ```
112
+
38
113
  ### Step 2: Read OpenSpec Files
39
114
 
40
115
  Read in order:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Change Status
3
- description: Quick progress status for a change
3
+ description: Quick progress status for a change (with project context)
4
4
  category: Multi-Agent
5
5
  tags: [status, progress, quick]
6
6
  ---
@@ -9,20 +9,88 @@ tags: [status, progress, quick]
9
9
 
10
10
  ```bash
11
11
  /cstatus {change-id}
12
+ /cstatus # Shows project status only (no change-id)
12
13
  ```
13
14
 
14
15
  ## What It Does
15
16
 
16
17
  Shows quick progress summary:
18
+ - **Project context** (from PROJECT_STATUS.yml if exists)
17
19
  - Progress percentage with bar
18
20
  - Current phase
19
21
  - Time spent/remaining
20
22
  - Quick stats
21
23
 
24
+ ---
25
+
26
+ ## Step 1: Show Project Context (v2.1.0)
27
+
28
+ ```typescript
29
+ const projectStatusPath = 'PROJECT_STATUS.yml'
30
+
31
+ if (fileExists(projectStatusPath)) {
32
+ const projectStatus = parseYaml(Read(projectStatusPath))
33
+
34
+ output(`
35
+ šŸ“Š Project Status
36
+ ā”œā”€ Focus: ${projectStatus.current_focus?.description || 'Not set'}
37
+ ā”œā”€ Active change: ${projectStatus.current_focus?.active_change || 'None'}
38
+ ā”œā”€ Blockers: ${projectStatus.blockers?.length || 0}
39
+ ā”œā”€ Infra: ${summarizeInfraStatus(projectStatus.infrastructure)}
40
+ └─ Updated: ${projectStatus.last_updated}
41
+ `)
42
+
43
+ // Show blockers if any
44
+ if (projectStatus.blockers?.length > 0) {
45
+ output(`
46
+ 🚧 Active Blockers:
47
+ ${projectStatus.blockers.map(b => ` - ${b.id}: ${b.description}`).join('\n')}
48
+ `)
49
+ }
50
+ }
51
+
52
+ // If no change-id provided, stop here
53
+ if (!changeId) {
54
+ output(`
55
+ Commands:
56
+ → Update project status: /pstatus
57
+ → View change status: /cstatus {change-id}
58
+ `)
59
+ return
60
+ }
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Step 2: Show Change Status
66
+
67
+ ```typescript
68
+ // Read change flags
69
+ const flagsPath = `openspec/changes/${changeId}/.claude/flags.json`
70
+
71
+ if (!fileExists(flagsPath)) {
72
+ return output(`āŒ Change ${changeId} not found or not set up. Run /csetup ${changeId} first.`)
73
+ }
74
+
75
+ const flags = JSON.parse(Read(flagsPath))
76
+ ```
77
+
22
78
  ## Output Format
23
79
 
24
80
  ```
25
- šŸ“Š CHANGE-{id}: {type} | {template}
81
+ šŸ“Š Project Status
82
+ ā”œā”€ Focus: Building authentication system
83
+ ā”œā”€ Active change: auth-system
84
+ ā”œā”€ Blockers: 1
85
+ ā”œā”€ Infra: DB āœ… | API āœ… | Tunnel ā³
86
+ └─ Updated: 2025-11-30
87
+
88
+ 🚧 Active Blockers:
89
+ - domain-config: Need domain for Cloudflare public routes
90
+
91
+ ─────────────────────────────────────────
92
+
93
+ šŸ“¦ CHANGE-{id}: {type} | {template}
26
94
 
27
95
  Progress: [ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–‘ā–‘] 64% (7/11 phases)
28
96
 
@@ -51,10 +119,35 @@ Current Phase: #8 Refactor (test-debug)
51
119
  3. Documentation (15 min)
52
120
 
53
121
  Commands:
122
+ → Update project status: /pstatus
54
123
  → Detailed view: /cview {change-id}
55
124
  → Continue dev: /cdev {change-id}
56
125
  ```
57
126
 
58
- ## Implementation
127
+ ---
128
+
129
+ ## Helper: summarizeInfraStatus()
130
+
131
+ ```typescript
132
+ function summarizeInfraStatus(infrastructure) {
133
+ if (!infrastructure) return 'Not configured'
134
+
135
+ return Object.entries(infrastructure)
136
+ .map(([service, info]) => {
137
+ const icon = info.status === 'healthy' ? 'āœ…' :
138
+ info.status === 'degraded' ? 'āš ļø' :
139
+ info.status === 'down' ? 'āŒ' :
140
+ info.status === 'waiting' ? 'ā³' : 'ā“'
141
+ return `${service} ${icon}`
142
+ })
143
+ .join(' | ')
144
+ }
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Implementation Notes
59
150
 
60
- Read `openspec/changes/{change-id}/.claude/flags.json` and format output using helper functions.
151
+ 1. **Always show project status first** (if PROJECT_STATUS.yml exists)
152
+ 2. **Then show change status** (if change-id provided)
153
+ 3. **Include /pstatus in commands** to encourage keeping status updated
@@ -0,0 +1,431 @@
1
+ ---
2
+ name: Project Status
3
+ description: Update PROJECT_STATUS.yml for cross-session context
4
+ category: Multi-Agent
5
+ tags: [status, context, cross-session]
6
+ ---
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ /pstatus
12
+ /pstatus quick # Quick update (outdated sections only)
13
+ /pstatus full # Full review (all sections)
14
+ /pstatus blockers # Update blockers section only
15
+ ```
16
+
17
+ ## What It Does
18
+
19
+ Interactive update of `PROJECT_STATUS.yml` - the cross-session context file that helps Claude understand project state in new sessions.
20
+
21
+ **WHY this exists:** New Claude sessions lose context about infrastructure, blockers, and priorities. This command helps maintain that context.
22
+
23
+ ---
24
+
25
+ ## Step 1: Check File Exists
26
+
27
+ ```typescript
28
+ const statusPath = 'PROJECT_STATUS.yml'
29
+
30
+ if (!fileExists(statusPath)) {
31
+ output(`
32
+ šŸ“Š PROJECT_STATUS.yml not found
33
+
34
+ This file provides cross-session context for Claude.
35
+ It helps new sessions understand:
36
+ - Infrastructure state (DB, API, tunnels)
37
+ - Blockers (waiting for domain, API keys)
38
+ - Completed work & next priorities
39
+
40
+ Create it now? (yes/no)
41
+ `)
42
+
43
+ const answer = await askUser()
44
+ if (answer === 'yes') {
45
+ // Copy from template
46
+ copy('.claude/templates/PROJECT_STATUS.template.yml', statusPath)
47
+ output('āœ… Created PROJECT_STATUS.yml - please fill in your project details')
48
+ return
49
+ } else {
50
+ return output('Skipped. Run /pstatus again when ready.')
51
+ }
52
+ }
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Step 2: Read Current Status
58
+
59
+ ```typescript
60
+ const status = parseYaml(Read(statusPath))
61
+ const lastUpdated = new Date(status.last_updated)
62
+ const daysSinceUpdate = Math.floor((Date.now() - lastUpdated) / (1000 * 60 * 60 * 24))
63
+
64
+ output(`
65
+ šŸ“Š PROJECT_STATUS.yml
66
+
67
+ Last updated: ${status.last_updated} (${daysSinceUpdate} days ago)
68
+ Current focus: ${status.current_focus?.description || 'Not set'}
69
+ Active change: ${status.current_focus?.active_change || 'None'}
70
+ Blockers: ${status.blockers?.length || 0}
71
+ Completed changes: ${status.completed_changes?.length || 0}
72
+ `)
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Step 3: Select Update Mode
78
+
79
+ ```typescript
80
+ // If mode provided via argument, use it
81
+ // Otherwise, ask user
82
+
83
+ const mode = args[0] || await askUserQuestion({
84
+ questions: [{
85
+ question: 'What would you like to update?',
86
+ header: 'Mode',
87
+ options: [
88
+ { label: 'Quick Update', description: 'Only sections that seem outdated' },
89
+ { label: 'Full Review', description: 'Walk through all sections' },
90
+ { label: 'Specific Section', description: 'Update one section only' }
91
+ ],
92
+ multiSelect: false
93
+ }]
94
+ })
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Step 4: Section-by-Section Updates
100
+
101
+ ### 4.1 Update `last_updated`
102
+
103
+ ```typescript
104
+ // Always update timestamp
105
+ status.last_updated = new Date().toISOString().split('T')[0]
106
+ ```
107
+
108
+ ### 4.2 Update `current_focus`
109
+
110
+ ```typescript
111
+ output(`
112
+ šŸ“ Current Focus
113
+ Description: "${status.current_focus?.description || 'Not set'}"
114
+ Active change: ${status.current_focus?.active_change || 'None'}
115
+ `)
116
+
117
+ const updateFocus = await askUserQuestion({
118
+ questions: [{
119
+ question: 'Update current focus?',
120
+ header: 'Focus',
121
+ options: [
122
+ { label: 'Keep as is', description: 'No changes needed' },
123
+ { label: 'Update description', description: 'Change what you are working on' },
124
+ { label: 'Set active change', description: 'Link to OpenSpec change' },
125
+ { label: 'Clear active change', description: 'Not working on a change' }
126
+ ],
127
+ multiSelect: false
128
+ }]
129
+ })
130
+
131
+ // Handle user selection...
132
+ ```
133
+
134
+ ### 4.3 Update `completed_changes`
135
+
136
+ ```typescript
137
+ output(`
138
+ āœ… Completed Changes (${status.completed_changes?.length || 0})
139
+ ${status.completed_changes?.map(c => ` - ${c.id} (${c.date}): ${c.summary}`).join('\n') || ' (none)'}
140
+ `)
141
+
142
+ // Auto-detect archived changes not in list
143
+ const archivedChanges = listFiles('openspec/changes/archive/')
144
+ const missingChanges = archivedChanges.filter(dir => {
145
+ const id = path.basename(dir)
146
+ return !status.completed_changes?.some(c => c.id === id)
147
+ })
148
+
149
+ if (missingChanges.length > 0) {
150
+ output(`
151
+ šŸ“¦ Found ${missingChanges.length} archived change(s) not in completed_changes:
152
+ ${missingChanges.map(c => ` - ${path.basename(c)}`).join('\n')}
153
+
154
+ Add them? (yes/no)
155
+ `)
156
+
157
+ const addMissing = await askUser()
158
+ if (addMissing) {
159
+ for (const changePath of missingChanges) {
160
+ const id = path.basename(changePath)
161
+ // Try to read proposal.md for summary
162
+ const proposalPath = `${changePath}/proposal.md`
163
+ let summary = 'No summary available'
164
+ if (fileExists(proposalPath)) {
165
+ const proposal = Read(proposalPath)
166
+ // Extract first sentence or title
167
+ summary = extractSummary(proposal)
168
+ }
169
+
170
+ status.completed_changes = status.completed_changes || []
171
+ status.completed_changes.push({
172
+ id,
173
+ date: new Date().toISOString().split('T')[0],
174
+ summary
175
+ })
176
+ output(` āœ… Added: ${id}`)
177
+ }
178
+ }
179
+ }
180
+ ```
181
+
182
+ ### 4.4 Update `infrastructure`
183
+
184
+ ```typescript
185
+ output(`
186
+ šŸ—ļø Infrastructure Status
187
+ ${Object.entries(status.infrastructure || {}).map(([service, info]) =>
188
+ ` ${service}: ${info.status}${info.waiting_for ? ` (waiting: ${info.waiting_for})` : ''}${info.notes ? ` - ${info.notes}` : ''}`
189
+ ).join('\n') || ' (none configured)'}
190
+ `)
191
+
192
+ const updateInfra = await askUserQuestion({
193
+ questions: [{
194
+ question: 'Update infrastructure status?',
195
+ header: 'Infra',
196
+ options: [
197
+ { label: 'Keep as is', description: 'No changes needed' },
198
+ { label: 'Update status', description: 'Change service status' },
199
+ { label: 'Add service', description: 'Track new infrastructure' },
200
+ { label: 'Remove service', description: 'Stop tracking a service' }
201
+ ],
202
+ multiSelect: false
203
+ }]
204
+ })
205
+
206
+ // Handle user selection...
207
+ // For status update, walk through each service:
208
+ if (updateInfra === 'Update status') {
209
+ for (const [service, info] of Object.entries(status.infrastructure || {})) {
210
+ output(`\n${service}: Currently "${info.status}"`)
211
+ const newStatus = await askUserQuestion({
212
+ questions: [{
213
+ question: `Update ${service} status?`,
214
+ header: service,
215
+ options: [
216
+ { label: 'healthy', description: 'Working normally' },
217
+ { label: 'degraded', description: 'Working with issues' },
218
+ { label: 'down', description: 'Not working' },
219
+ { label: 'waiting', description: 'Pending external action' },
220
+ { label: 'Keep current', description: `Stay as "${info.status}"` }
221
+ ],
222
+ multiSelect: false
223
+ }]
224
+ })
225
+
226
+ if (newStatus !== 'Keep current') {
227
+ status.infrastructure[service].status = newStatus
228
+
229
+ // If changed to healthy, clear waiting_for
230
+ if (newStatus === 'healthy') {
231
+ status.infrastructure[service].waiting_for = null
232
+ }
233
+
234
+ // If changed to waiting, ask what for
235
+ if (newStatus === 'waiting') {
236
+ output('What is it waiting for?')
237
+ status.infrastructure[service].waiting_for = await askUser()
238
+ }
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### 4.5 Update `blockers`
245
+
246
+ ```typescript
247
+ output(`
248
+ 🚧 Blockers (${status.blockers?.length || 0})
249
+ ${status.blockers?.map(b => ` - ${b.id}: ${b.description} (blocks: ${b.blocks?.join(', ') || 'nothing specified'})`).join('\n') || ' (none)'}
250
+ `)
251
+
252
+ const updateBlockers = await askUserQuestion({
253
+ questions: [{
254
+ question: 'Update blockers?',
255
+ header: 'Blockers',
256
+ options: [
257
+ { label: 'Keep as is', description: 'No changes needed' },
258
+ { label: 'Add blocker', description: 'New external dependency' },
259
+ { label: 'Remove blocker', description: 'Blocker resolved' },
260
+ { label: 'Update blocker', description: 'Change existing blocker' }
261
+ ],
262
+ multiSelect: false
263
+ }]
264
+ })
265
+
266
+ // Handle user selection...
267
+ ```
268
+
269
+ ### 4.6 Update `next_priorities`
270
+
271
+ ```typescript
272
+ output(`
273
+ šŸŽÆ Next Priorities
274
+ ${status.next_priorities?.map((p, i) => ` ${i + 1}. ${p.id}: ${p.reason}`).join('\n') || ' (none set)'}
275
+ `)
276
+
277
+ const updatePriorities = await askUserQuestion({
278
+ questions: [{
279
+ question: 'Update priorities?',
280
+ header: 'Priorities',
281
+ options: [
282
+ { label: 'Keep as is', description: 'No changes needed' },
283
+ { label: 'Add priority', description: 'New item to work on' },
284
+ { label: 'Remove priority', description: 'Completed or deprioritized' },
285
+ { label: 'Reorder', description: 'Change priority order' }
286
+ ],
287
+ multiSelect: false
288
+ }]
289
+ })
290
+
291
+ // Handle user selection...
292
+ ```
293
+
294
+ ### 4.7 Update `notes`
295
+
296
+ ```typescript
297
+ output(`
298
+ šŸ“ Notes
299
+ ${status.notes || ' (empty)'}
300
+ `)
301
+
302
+ const updateNotes = await askUserQuestion({
303
+ questions: [{
304
+ question: 'Update notes?',
305
+ header: 'Notes',
306
+ options: [
307
+ { label: 'Keep as is', description: 'No changes needed' },
308
+ { label: 'Replace', description: 'Replace all notes' },
309
+ { label: 'Append', description: 'Add to existing notes' },
310
+ { label: 'Clear', description: 'Remove all notes' }
311
+ ],
312
+ multiSelect: false
313
+ }]
314
+ })
315
+
316
+ // Handle user selection...
317
+ ```
318
+
319
+ ---
320
+
321
+ ## Step 5: Write Changes
322
+
323
+ ```typescript
324
+ // Show diff
325
+ output(`
326
+ šŸ“ Changes to be written:
327
+
328
+ ${generateYamlDiff(originalStatus, status)}
329
+ `)
330
+
331
+ const confirm = await askUserQuestion({
332
+ questions: [{
333
+ question: 'Save changes?',
334
+ header: 'Confirm',
335
+ options: [
336
+ { label: 'Yes', description: 'Write changes to PROJECT_STATUS.yml' },
337
+ { label: 'No', description: 'Discard changes' }
338
+ ],
339
+ multiSelect: false
340
+ }]
341
+ })
342
+
343
+ if (confirm === 'Yes') {
344
+ Write(statusPath, toYaml(status))
345
+ output(`
346
+ āœ… PROJECT_STATUS.yml updated!
347
+
348
+ Last updated: ${status.last_updated}
349
+ Changes saved: ${countChanges(originalStatus, status)} section(s)
350
+ `)
351
+ } else {
352
+ output('Changes discarded.')
353
+ }
354
+ ```
355
+
356
+ ---
357
+
358
+ ## Quick Mode Behavior
359
+
360
+ When `/pstatus quick` is used:
361
+
362
+ 1. Check `last_updated` - if > 7 days, suggest full review
363
+ 2. Auto-detect archived changes not in `completed_changes`
364
+ 3. Show current blockers - ask if any resolved
365
+ 4. Skip unchanged sections
366
+ 5. Update timestamp and save
367
+
368
+ ---
369
+
370
+ ## Output Example
371
+
372
+ ```
373
+ šŸ“Š PROJECT_STATUS.yml Review
374
+
375
+ Last updated: 2025-11-25 (6 days ago)
376
+ Current focus: "Building authentication system"
377
+ Active change: auth-system
378
+
379
+ šŸ“¦ Found 1 archived change not in completed_changes:
380
+ - infrastructure-cicd
381
+
382
+ Add it? (yes)
383
+ āœ… Added: infrastructure-cicd
384
+
385
+ 🚧 Blockers (1)
386
+ - domain-config: Need domain for Cloudflare (blocks: production-launch)
387
+
388
+ Any blockers resolved? (no)
389
+
390
+ šŸŽÆ Priorities look current.
391
+
392
+ šŸ“ Changes to be written:
393
+ + completed_changes: infrastructure-cicd
394
+ ~ last_updated: 2025-11-25 → 2025-12-01
395
+
396
+ Save changes? (yes)
397
+
398
+ āœ… PROJECT_STATUS.yml updated!
399
+ ```
400
+
401
+ ---
402
+
403
+ ## Integration with Other Commands
404
+
405
+ | Command | Integration |
406
+ |---------|-------------|
407
+ | `/csetup` | Reads PROJECT_STATUS.yml for context, updates `current_focus.active_change` |
408
+ | `/cstatus` | Shows both change status AND project status summary |
409
+ | `/openspec:archive` | Prompts to add to `completed_changes` |
410
+
411
+ ---
412
+
413
+ ## Blocker Detection Patterns
414
+
415
+ Main Claude should recognize these phrases and suggest adding blockers:
416
+
417
+ | Pattern | Example |
418
+ |---------|---------|
419
+ | "waiting for..." | "waiting for domain configuration" |
420
+ | "need X from..." | "need API key from client" |
421
+ | "blocked by..." | "blocked by DevOps team" |
422
+ | "pending..." | "pending approval" |
423
+ | "can't proceed until..." | "can't proceed until payment gateway ready" |
424
+
425
+ When detected, prompt:
426
+ ```
427
+ This sounds like an external blocker. Add to PROJECT_STATUS.yml?
428
+ - id: {suggested-id}
429
+ - description: {extracted-description}
430
+ - blocks: [{related-work}]
431
+ ```