prjct-cli 0.13.3 → 0.15.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 +122 -0
- package/bin/prjct +10 -13
- package/core/agentic/memory-system/semantic-memories.ts +2 -1
- package/core/agentic/plan-mode/plan-mode.ts +2 -1
- package/core/agentic/prompt-builder.ts +22 -43
- package/core/agentic/services.ts +5 -5
- package/core/agentic/smart-context.ts +7 -2
- package/core/command-registry/core-commands.ts +54 -29
- package/core/command-registry/optional-commands.ts +64 -0
- package/core/command-registry/setup-commands.ts +18 -3
- package/core/commands/analysis.ts +21 -68
- package/core/commands/analytics.ts +247 -213
- package/core/commands/base.ts +1 -1
- package/core/commands/index.ts +41 -36
- package/core/commands/maintenance.ts +300 -31
- package/core/commands/planning.ts +233 -22
- package/core/commands/setup.ts +3 -8
- package/core/commands/shipping.ts +14 -18
- package/core/commands/types.ts +8 -6
- package/core/commands/workflow.ts +105 -100
- package/core/context/generator.ts +317 -0
- package/core/context-sync.ts +7 -350
- package/core/data/index.ts +13 -32
- package/core/data/md-ideas-manager.ts +155 -0
- package/core/data/md-queue-manager.ts +4 -3
- package/core/data/md-shipped-manager.ts +90 -0
- package/core/data/md-state-manager.ts +11 -7
- package/core/domain/agent-generator.ts +23 -63
- package/core/events/index.ts +143 -0
- package/core/index.ts +17 -14
- package/core/infrastructure/capability-installer.ts +13 -149
- package/core/infrastructure/migrator/project-scanner.ts +2 -1
- package/core/infrastructure/path-manager.ts +4 -6
- package/core/infrastructure/setup.ts +3 -0
- package/core/infrastructure/uuid-migration.ts +750 -0
- package/core/outcomes/recorder.ts +2 -1
- package/core/plugin/loader.ts +4 -7
- package/core/plugin/registry.ts +3 -3
- package/core/schemas/index.ts +23 -25
- package/core/schemas/state.ts +1 -0
- package/core/serializers/ideas-serializer.ts +187 -0
- package/core/serializers/index.ts +16 -0
- package/core/serializers/shipped-serializer.ts +108 -0
- package/core/session/utils.ts +3 -9
- package/core/storage/ideas-storage.ts +273 -0
- package/core/storage/index.ts +204 -0
- package/core/storage/queue-storage.ts +297 -0
- package/core/storage/shipped-storage.ts +223 -0
- package/core/storage/state-storage.ts +235 -0
- package/core/storage/storage-manager.ts +175 -0
- package/package.json +1 -1
- package/packages/web/app/api/projects/[id]/momentum/route.ts +257 -0
- package/packages/web/app/api/sessions/current/route.ts +132 -0
- package/packages/web/app/api/sessions/history/route.ts +96 -14
- package/packages/web/app/globals.css +5 -0
- package/packages/web/app/layout.tsx +2 -0
- package/packages/web/app/project/[id]/code/layout.tsx +18 -0
- package/packages/web/app/project/[id]/code/page.tsx +408 -0
- package/packages/web/app/project/[id]/page.tsx +359 -389
- package/packages/web/app/project/[id]/reports/page.tsx +59 -0
- package/packages/web/app/project/[id]/reports/print/page.tsx +58 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +0 -1
- package/packages/web/components/AgentsCard/AgentsCard.tsx +64 -34
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +1 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +135 -11
- package/packages/web/components/BentoCard/BentoCard.constants.ts +3 -3
- package/packages/web/components/BentoCard/BentoCard.tsx +2 -1
- package/packages/web/components/BentoGrid/BentoGrid.tsx +2 -2
- package/packages/web/components/BlockersCard/BlockersCard.tsx +65 -57
- package/packages/web/components/BlockersCard/BlockersCard.types.ts +1 -0
- package/packages/web/components/CommandBar/CommandBar.tsx +67 -0
- package/packages/web/components/CommandBar/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +35 -5
- package/packages/web/components/DateGroup/DateGroup.tsx +1 -1
- package/packages/web/components/EmptyState/EmptyState.tsx +39 -21
- package/packages/web/components/EmptyState/EmptyState.types.ts +1 -0
- package/packages/web/components/EventRow/EventRow.tsx +4 -4
- package/packages/web/components/EventRow/EventRow.utils.ts +3 -3
- package/packages/web/components/HeroSection/HeroSection.tsx +52 -15
- package/packages/web/components/HeroSection/HeroSection.types.ts +4 -4
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -3
- package/packages/web/components/IdeasCard/IdeasCard.tsx +94 -27
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +1 -0
- package/packages/web/components/MasonryGrid/MasonryGrid.tsx +18 -0
- package/packages/web/components/MasonryGrid/index.ts +1 -0
- package/packages/web/components/MomentumWidget/MomentumWidget.tsx +119 -0
- package/packages/web/components/MomentumWidget/MomentumWidget.types.ts +16 -0
- package/packages/web/components/MomentumWidget/index.ts +2 -0
- package/packages/web/components/NowCard/NowCard.tsx +81 -56
- package/packages/web/components/NowCard/NowCard.types.ts +1 -0
- package/packages/web/components/PageHeader/PageHeader.tsx +24 -0
- package/packages/web/components/PageHeader/index.ts +1 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +2 -2
- package/packages/web/components/ProjectAvatar/ProjectAvatar.tsx +2 -2
- package/packages/web/components/ProjectColorDot/ProjectColorDot.tsx +37 -0
- package/packages/web/components/ProjectColorDot/index.ts +1 -0
- package/packages/web/components/ProjectSelectorModal/ProjectSelectorModal.tsx +104 -0
- package/packages/web/components/ProjectSelectorModal/index.ts +1 -0
- package/packages/web/components/Providers/Providers.tsx +4 -1
- package/packages/web/components/QueueCard/QueueCard.tsx +78 -25
- package/packages/web/components/QueueCard/QueueCard.types.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +3 -3
- package/packages/web/components/RecoverCard/RecoverCard.tsx +72 -0
- package/packages/web/components/RecoverCard/RecoverCard.types.ts +16 -0
- package/packages/web/components/RecoverCard/index.ts +2 -0
- package/packages/web/components/RoadmapCard/RoadmapCard.tsx +101 -33
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +1 -0
- package/packages/web/components/ShipsCard/ShipsCard.tsx +71 -28
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +2 -0
- package/packages/web/components/SparklineChart/SparklineChart.tsx +20 -18
- package/packages/web/components/StatsMasonry/StatsMasonry.tsx +95 -0
- package/packages/web/components/StatsMasonry/index.ts +1 -0
- package/packages/web/components/StreakCard/StreakCard.tsx +37 -35
- package/packages/web/components/TasksCounter/TasksCounter.tsx +1 -1
- package/packages/web/components/TechStackBadges/TechStackBadges.tsx +12 -4
- package/packages/web/components/TerminalDock/DockToggleTab.tsx +29 -0
- package/packages/web/components/TerminalDock/TerminalDock.tsx +386 -0
- package/packages/web/components/TerminalDock/TerminalDockTab.tsx +130 -0
- package/packages/web/components/TerminalDock/TerminalTabBar.tsx +142 -0
- package/packages/web/components/TerminalDock/index.ts +2 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +8 -3
- package/packages/web/components/VelocityCard/VelocityCard.tsx +49 -47
- package/packages/web/components/WeeklyReports/PrintableReport.tsx +259 -0
- package/packages/web/components/WeeklyReports/ReportPreviewCard.tsx +187 -0
- package/packages/web/components/WeeklyReports/WeekCalendar.tsx +288 -0
- package/packages/web/components/WeeklyReports/WeeklyReports.tsx +149 -0
- package/packages/web/components/WeeklyReports/index.ts +4 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +16 -4
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +1 -0
- package/packages/web/components/charts/SessionsChart.tsx +6 -3
- package/packages/web/components/ui/dialog.tsx +143 -0
- package/packages/web/components/ui/drawer.tsx +135 -0
- package/packages/web/components/ui/select.tsx +187 -0
- package/packages/web/context/GlobalTerminalContext.tsx +538 -0
- package/packages/web/lib/commands.ts +81 -0
- package/packages/web/lib/generate-week-report.ts +285 -0
- package/packages/web/lib/parse-prjct-files.ts +56 -55
- package/packages/web/lib/project-colors.ts +58 -0
- package/packages/web/lib/projects.ts +58 -5
- package/packages/web/lib/services/projects.server.ts +11 -1
- package/packages/web/next-env.d.ts +1 -1
- package/packages/web/package.json +5 -1
- package/templates/commands/analyze.md +39 -3
- package/templates/commands/ask.md +58 -3
- package/templates/commands/bug.md +117 -26
- package/templates/commands/dash.md +95 -158
- package/templates/commands/done.md +130 -148
- package/templates/commands/feature.md +125 -103
- package/templates/commands/git.md +18 -3
- package/templates/commands/idea.md +121 -38
- package/templates/commands/init.md +124 -20
- package/templates/commands/migrate-all.md +63 -28
- package/templates/commands/migrate.md +140 -0
- package/templates/commands/next.md +115 -5
- package/templates/commands/now.md +146 -82
- package/templates/commands/pause.md +89 -74
- package/templates/commands/redo.md +6 -4
- package/templates/commands/resume.md +141 -59
- package/templates/commands/setup.md +18 -3
- package/templates/commands/ship.md +103 -231
- package/templates/commands/spec.md +98 -8
- package/templates/commands/suggest.md +22 -2
- package/templates/commands/sync.md +192 -203
- package/templates/commands/undo.md +6 -4
- package/templates/mcp-config.json +20 -1
- package/core/data/agents-manager.ts +0 -76
- package/core/data/analysis-manager.ts +0 -83
- package/core/data/base-manager.ts +0 -156
- package/core/data/ideas-manager.ts +0 -81
- package/core/data/outcomes-manager.ts +0 -96
- package/core/data/project-manager.ts +0 -75
- package/core/data/roadmap-manager.ts +0 -118
- package/core/data/shipped-manager.ts +0 -65
- package/core/data/state-manager.ts +0 -214
- package/core/state/index.ts +0 -25
- package/core/state/manager.ts +0 -376
- package/core/state/types.ts +0 -185
- package/core/utils/project-capabilities.ts +0 -156
- package/core/view-generator.ts +0 -536
- package/packages/web/app/project/[id]/stats/loading.tsx +0 -43
- package/packages/web/app/project/[id]/stats/page.tsx +0 -253
- package/templates/agent-assignment.md +0 -72
- package/templates/analysis/project-analysis.md +0 -78
- package/templates/checklists/accessibility.md +0 -33
- package/templates/commands/build.md +0 -17
- package/templates/commands/decision.md +0 -226
- package/templates/commands/fix.md +0 -79
- package/templates/commands/help.md +0 -61
- package/templates/commands/progress.md +0 -14
- package/templates/commands/recap.md +0 -14
- package/templates/commands/roadmap.md +0 -52
- package/templates/commands/status.md +0 -17
- package/templates/commands/task.md +0 -63
- package/templates/commands/work.md +0 -44
- package/templates/commands/workflow.md +0 -12
|
@@ -2,23 +2,32 @@
|
|
|
2
2
|
allowed-tools: [Read, Write, Bash]
|
|
3
3
|
description: 'Set or show current task with session tracking'
|
|
4
4
|
timestamp-rule: 'GetTimestamp() for ALL timestamps'
|
|
5
|
-
architecture: '
|
|
5
|
+
architecture: 'Write-Through (JSON → MD → Events)'
|
|
6
|
+
storage-layer: true
|
|
7
|
+
source-of-truth: 'storage/state.json'
|
|
8
|
+
claude-context: 'context/now.md'
|
|
9
|
+
backend-sync: 'sync/pending.json'
|
|
6
10
|
---
|
|
7
11
|
|
|
8
12
|
# /p:now - Current Task with Session Tracking
|
|
9
13
|
|
|
10
|
-
## Architecture:
|
|
14
|
+
## Architecture: Write-Through Pattern
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
```
|
|
17
|
+
User Action → Storage (JSON) → Context (MD) → Sync Events
|
|
18
|
+
```
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
**Source of Truth**: `storage/state.json`
|
|
21
|
+
**Claude Context**: `context/now.md` (generated)
|
|
22
|
+
**Backend Sync**: `sync/pending.json` (events)
|
|
15
23
|
|
|
16
24
|
## Context Variables
|
|
17
25
|
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
18
26
|
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
19
|
-
- `{
|
|
20
|
-
- `{
|
|
21
|
-
- `{
|
|
27
|
+
- `{statePath}`: `{globalPath}/storage/state.json`
|
|
28
|
+
- `{nowContextPath}`: `{globalPath}/context/now.md`
|
|
29
|
+
- `{syncPath}`: `{globalPath}/sync/pending.json`
|
|
30
|
+
- `{memoryPath}`: `{globalPath}/memory/events.jsonl`
|
|
22
31
|
- `{task}`: User-provided task (optional)
|
|
23
32
|
- `{estimate}`: User-provided time estimate (optional, e.g., "2h", "30m", "1d")
|
|
24
33
|
|
|
@@ -35,6 +44,48 @@ If no estimate provided, gently remind:
|
|
|
35
44
|
💡 Tip: Add estimate next time with /p:now "task" 2h
|
|
36
45
|
```
|
|
37
46
|
|
|
47
|
+
## Agent Detection (Optional)
|
|
48
|
+
|
|
49
|
+
When starting a task, auto-detect the best agent based on keywords:
|
|
50
|
+
|
|
51
|
+
| Keywords | Agent | Domain |
|
|
52
|
+
|----------|-------|--------|
|
|
53
|
+
| UI, frontend, React, component, CSS, style | `fe` | Frontend |
|
|
54
|
+
| API, backend, database, server, endpoint | `be` | Backend |
|
|
55
|
+
| design, UX, layout, wireframe | `ux` | UX Design |
|
|
56
|
+
| test, QA, bug, coverage, spec | `qa` | Testing |
|
|
57
|
+
| docs, README, documentation | `docs` | Documentation |
|
|
58
|
+
| (default) | `general` | General |
|
|
59
|
+
|
|
60
|
+
**Usage**: Agent is logged for analytics but doesn't affect workflow.
|
|
61
|
+
|
|
62
|
+
## Step 0: Detect Abandoned Sessions (BEFORE anything else)
|
|
63
|
+
|
|
64
|
+
READ: `{statePath}` (`storage/state.json`)
|
|
65
|
+
|
|
66
|
+
IF file exists AND has `currentTask`:
|
|
67
|
+
SET: {existingTask} = currentTask object
|
|
68
|
+
SET: {lastActivity} = existingTask.startedAt or last timeline entry
|
|
69
|
+
SET: {hoursAgo} = hours between {lastActivity} and now
|
|
70
|
+
|
|
71
|
+
IF {hoursAgo} >= 8: // Session considered abandoned after 8 hours
|
|
72
|
+
OUTPUT:
|
|
73
|
+
```
|
|
74
|
+
⚠️ Found abandoned session from {hoursAgo}h ago
|
|
75
|
+
|
|
76
|
+
Task: {existingTask.description}
|
|
77
|
+
Session: {existingTask.sessionId}
|
|
78
|
+
Started: {existingTask.startedAt}
|
|
79
|
+
|
|
80
|
+
Options:
|
|
81
|
+
1. Resume previous task → /p:resume
|
|
82
|
+
2. Close previous as partial → /p:recover close
|
|
83
|
+
3. View full context → /p:recover
|
|
84
|
+
|
|
85
|
+
Choose an option before starting a new task.
|
|
86
|
+
```
|
|
87
|
+
STOP
|
|
88
|
+
|
|
38
89
|
## Step 1: Read Config
|
|
39
90
|
|
|
40
91
|
READ: `.prjct/prjct.config.json`
|
|
@@ -46,46 +97,36 @@ IF file not found:
|
|
|
46
97
|
|
|
47
98
|
## Step 2: Check Current State
|
|
48
99
|
|
|
49
|
-
### Read
|
|
50
|
-
READ: `{
|
|
51
|
-
|
|
52
|
-
IF file exists AND has content:
|
|
53
|
-
PARSE MD format:
|
|
54
|
-
- Look for `**Task description**` (bold text = current task)
|
|
55
|
-
- Look for `Started: {timestamp}`
|
|
56
|
-
- Look for `Session: {sessionId}`
|
|
57
|
-
EXTRACT: {currentTask}, {startedAt}, {sessionId}
|
|
58
|
-
|
|
59
|
-
### Check for active session (for detailed tracking)
|
|
60
|
-
READ: `{sessionPath}`
|
|
100
|
+
### Read state.json (source of truth)
|
|
101
|
+
READ: `{statePath}`
|
|
61
102
|
|
|
62
103
|
IF file exists:
|
|
63
|
-
PARSE
|
|
64
|
-
EXTRACT: {
|
|
104
|
+
PARSE JSON
|
|
105
|
+
EXTRACT: {currentTask}, {pausedTask} if present
|
|
65
106
|
|
|
66
107
|
## Step 3: Handle Cases
|
|
67
108
|
|
|
68
109
|
### Case A: No task provided - Show current
|
|
69
110
|
IF {task} is empty OR not provided:
|
|
70
|
-
IF {currentTask} exists AND {status} == "active":
|
|
71
|
-
CALCULATE: {elapsed} = time since {startedAt}
|
|
111
|
+
IF {currentTask} exists AND {currentTask.status} == "active":
|
|
112
|
+
CALCULATE: {elapsed} = time since {currentTask.startedAt}
|
|
72
113
|
OUTPUT:
|
|
73
114
|
```
|
|
74
|
-
🎯 {currentTask}
|
|
115
|
+
🎯 {currentTask.description}
|
|
75
116
|
|
|
76
|
-
Session: {sessionId}
|
|
77
|
-
Started: {startedAt} ({elapsed} ago)
|
|
117
|
+
Session: {currentTask.sessionId}
|
|
118
|
+
Started: {currentTask.startedAt} ({elapsed} ago)
|
|
78
119
|
Status: active
|
|
79
120
|
|
|
80
121
|
/p:done to complete | /p:pause to pause
|
|
81
122
|
```
|
|
82
123
|
STOP
|
|
83
|
-
ELSE IF {
|
|
124
|
+
ELSE IF {pausedTask} exists:
|
|
84
125
|
OUTPUT:
|
|
85
126
|
```
|
|
86
|
-
⏸️ Paused: {
|
|
127
|
+
⏸️ Paused: {pausedTask.description}
|
|
87
128
|
|
|
88
|
-
Duration so far: {duration}
|
|
129
|
+
Duration so far: {pausedTask.duration}
|
|
89
130
|
|
|
90
131
|
/p:resume to continue | /p:done to complete
|
|
91
132
|
```
|
|
@@ -97,31 +138,54 @@ IF {task} is empty OR not provided:
|
|
|
97
138
|
### Case B: Task provided - Create/Update session
|
|
98
139
|
IF {task} is provided:
|
|
99
140
|
|
|
100
|
-
## Check for existing active
|
|
101
|
-
IF {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
141
|
+
## Check for existing active task
|
|
142
|
+
IF {currentTask} exists AND {currentTask.status} == "active":
|
|
143
|
+
IF {currentTask.description} != {task}:
|
|
144
|
+
OUTPUT:
|
|
145
|
+
```
|
|
146
|
+
⚠️ Already working on: {currentTask.description}
|
|
105
147
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
148
|
+
Options:
|
|
149
|
+
• /p:done - Complete current task first
|
|
150
|
+
• /p:pause - Pause and switch
|
|
151
|
+
• /p:now (same task) - Continue current
|
|
152
|
+
```
|
|
153
|
+
STOP
|
|
112
154
|
|
|
113
155
|
## If same task, just continue
|
|
114
|
-
IF {currentTask} == {task}:
|
|
156
|
+
IF {currentTask} AND {currentTask.description} == {task}:
|
|
115
157
|
OUTPUT: "🎯 Continuing: {task}"
|
|
116
158
|
STOP
|
|
117
159
|
|
|
118
|
-
## Create new
|
|
119
|
-
GENERATE: {
|
|
160
|
+
## Create new task
|
|
161
|
+
GENERATE: {taskId} = UUID v4
|
|
162
|
+
GENERATE: {sessionId} = UUID v4
|
|
120
163
|
SET: {startedAt} = GetTimestamp()
|
|
121
164
|
|
|
122
|
-
|
|
165
|
+
## Step 4: Write to Storage (SOURCE OF TRUTH)
|
|
166
|
+
|
|
167
|
+
### Prepare task object
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"id": "{taskId}",
|
|
171
|
+
"description": "{task}",
|
|
172
|
+
"status": "active",
|
|
173
|
+
"startedAt": "{startedAt}",
|
|
174
|
+
"sessionId": "{sessionId}",
|
|
175
|
+
"estimate": "{estimate OR null}",
|
|
176
|
+
"estimateSeconds": {estimateInSeconds OR null}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Write state.json
|
|
181
|
+
READ existing `{statePath}` or create empty object
|
|
182
|
+
SET: state.currentTask = new task object
|
|
183
|
+
SET: state.lastUpdated = {startedAt}
|
|
184
|
+
WRITE: `{statePath}`
|
|
185
|
+
|
|
186
|
+
## Step 5: Generate Context (FOR CLAUDE)
|
|
123
187
|
|
|
124
|
-
WRITE: `{
|
|
188
|
+
WRITE: `{nowContextPath}`
|
|
125
189
|
|
|
126
190
|
IF {estimate} provided:
|
|
127
191
|
```markdown
|
|
@@ -144,53 +208,39 @@ IF {task} is provided:
|
|
|
144
208
|
Session: {sessionId}
|
|
145
209
|
```
|
|
146
210
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
211
|
+
## Step 6: Queue Sync Event (FOR BACKEND)
|
|
212
|
+
|
|
213
|
+
READ: `{syncPath}` or create empty array
|
|
214
|
+
APPEND event:
|
|
150
215
|
```json
|
|
151
216
|
{
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
"duration": 0,
|
|
160
|
-
"estimate": "{estimate OR null}",
|
|
161
|
-
"estimateSeconds": {estimateInSeconds OR null},
|
|
162
|
-
"metrics": {
|
|
163
|
-
"filesChanged": 0,
|
|
164
|
-
"linesAdded": 0,
|
|
165
|
-
"linesRemoved": 0,
|
|
166
|
-
"commits": 0,
|
|
167
|
-
"snapshots": []
|
|
217
|
+
"type": "task.started",
|
|
218
|
+
"path": ["state"],
|
|
219
|
+
"data": {
|
|
220
|
+
"taskId": "{taskId}",
|
|
221
|
+
"description": "{task}",
|
|
222
|
+
"startedAt": "{startedAt}",
|
|
223
|
+
"sessionId": "{sessionId}"
|
|
168
224
|
},
|
|
169
|
-
"
|
|
170
|
-
|
|
171
|
-
]
|
|
225
|
+
"timestamp": "{startedAt}",
|
|
226
|
+
"projectId": "{projectId}"
|
|
172
227
|
}
|
|
173
228
|
```
|
|
229
|
+
WRITE: `{syncPath}`
|
|
174
230
|
|
|
175
|
-
|
|
176
|
-
IF {estimate} provided:
|
|
177
|
-
- "30m" → 1800 seconds
|
|
178
|
-
- "2h" → 7200 seconds
|
|
179
|
-
- "1d" → 28800 seconds (8 hours)
|
|
180
|
-
- "2h30m" → 9000 seconds
|
|
231
|
+
## Step 7: Log to Memory (AUDIT TRAIL)
|
|
181
232
|
|
|
182
|
-
### Log to memory
|
|
183
233
|
APPEND to: `{memoryPath}`
|
|
184
234
|
Single line (JSONL):
|
|
185
235
|
|
|
186
236
|
IF {estimate} provided:
|
|
187
237
|
```json
|
|
188
|
-
{"timestamp":"{startedAt}","action":"
|
|
238
|
+
{"timestamp":"{startedAt}","action":"task_started","taskId":"{taskId}","sessionId":"{sessionId}","task":"{task}","estimate":"{estimate}","estimateSeconds":{estimateInSeconds}}
|
|
189
239
|
```
|
|
190
240
|
|
|
191
241
|
ELSE:
|
|
192
242
|
```json
|
|
193
|
-
{"timestamp":"{startedAt}","action":"
|
|
243
|
+
{"timestamp":"{startedAt}","action":"task_started","taskId":"{taskId}","sessionId":"{sessionId}","task":"{task}"}
|
|
194
244
|
```
|
|
195
245
|
|
|
196
246
|
## Output
|
|
@@ -223,9 +273,23 @@ Started: now
|
|
|
223
273
|
| Error | Response | Action |
|
|
224
274
|
|-------|----------|--------|
|
|
225
275
|
| No project | "No prjct project" | STOP |
|
|
226
|
-
| Active
|
|
276
|
+
| Active task exists | Show options | STOP |
|
|
227
277
|
| Write fails | "Failed to create session" | STOP |
|
|
228
278
|
|
|
279
|
+
## File Structure Reference
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
~/.prjct-cli/projects/{projectId}/
|
|
283
|
+
├── storage/
|
|
284
|
+
│ └── state.json # Source of truth (current + paused tasks)
|
|
285
|
+
├── context/
|
|
286
|
+
│ └── now.md # Generated for Claude
|
|
287
|
+
├── sync/
|
|
288
|
+
│ └── pending.json # Events for backend
|
|
289
|
+
└── memory/
|
|
290
|
+
└── events.jsonl # Audit trail
|
|
291
|
+
```
|
|
292
|
+
|
|
229
293
|
## Examples
|
|
230
294
|
|
|
231
295
|
### Example 1: Show Current Task
|
|
@@ -234,7 +298,7 @@ User: /p:now
|
|
|
234
298
|
Output:
|
|
235
299
|
🎯 Implement user authentication
|
|
236
300
|
|
|
237
|
-
Session:
|
|
301
|
+
Session: 550e8400-e29b-41d4-a716-446655440000
|
|
238
302
|
Started: 2 hours ago
|
|
239
303
|
Status: active
|
|
240
304
|
|
|
@@ -247,7 +311,7 @@ User: /p:now "Add login form"
|
|
|
247
311
|
Output:
|
|
248
312
|
🎯 Add login form
|
|
249
313
|
|
|
250
|
-
Session:
|
|
314
|
+
Session: 7c9e6679-7425-40de-944b-e07fc1f90ae7
|
|
251
315
|
Started: now
|
|
252
316
|
|
|
253
317
|
💡 Tip: Add estimate next time with /p:now "task" 2h
|
|
@@ -255,20 +319,20 @@ Started: now
|
|
|
255
319
|
/p:done when finished | /p:pause to take a break
|
|
256
320
|
```
|
|
257
321
|
|
|
258
|
-
### Example
|
|
322
|
+
### Example 3: Start New Task (with estimate)
|
|
259
323
|
```
|
|
260
324
|
User: /p:now "Add login form" 2h
|
|
261
325
|
Output:
|
|
262
326
|
🎯 Add login form
|
|
263
327
|
|
|
264
|
-
Session:
|
|
328
|
+
Session: 7c9e6679-7425-40de-944b-e07fc1f90ae7
|
|
265
329
|
Started: now
|
|
266
330
|
Estimate: 2h
|
|
267
331
|
|
|
268
332
|
/p:done when finished | /p:pause to take a break
|
|
269
333
|
```
|
|
270
334
|
|
|
271
|
-
### Example
|
|
335
|
+
### Example 4: Task Conflict
|
|
272
336
|
```
|
|
273
337
|
User: /p:now "Something else"
|
|
274
338
|
Output:
|
|
@@ -2,21 +2,32 @@
|
|
|
2
2
|
allowed-tools: [Read, Write, Bash]
|
|
3
3
|
description: 'Pause current session with reason'
|
|
4
4
|
timestamp-rule: 'GetTimestamp() for all timestamps'
|
|
5
|
-
architecture: '
|
|
5
|
+
architecture: 'Write-Through (JSON → MD → Events)'
|
|
6
|
+
storage-layer: true
|
|
7
|
+
source-of-truth: 'storage/state.json'
|
|
8
|
+
claude-context: 'context/now.md'
|
|
9
|
+
backend-sync: 'sync/pending.json'
|
|
6
10
|
---
|
|
7
11
|
|
|
8
12
|
# /p:pause - Pause Current Session
|
|
9
13
|
|
|
10
|
-
## Architecture:
|
|
14
|
+
## Architecture: Write-Through Pattern
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
```
|
|
17
|
+
User Action → Storage (JSON) → Context (MD) → Sync Events
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Source of Truth**: `storage/state.json`
|
|
21
|
+
**Claude Context**: `context/now.md` (generated)
|
|
22
|
+
**Backend Sync**: `sync/pending.json` (events)
|
|
13
23
|
|
|
14
24
|
## Context Variables
|
|
15
25
|
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
16
26
|
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
17
|
-
- `{
|
|
18
|
-
- `{
|
|
19
|
-
- `{
|
|
27
|
+
- `{statePath}`: `{globalPath}/storage/state.json`
|
|
28
|
+
- `{nowContextPath}`: `{globalPath}/context/now.md`
|
|
29
|
+
- `{syncPath}`: `{globalPath}/sync/pending.json`
|
|
30
|
+
- `{memoryPath}`: `{globalPath}/memory/events.jsonl`
|
|
20
31
|
- `{reason}`: User-provided reason (optional)
|
|
21
32
|
|
|
22
33
|
## Pause Reasons
|
|
@@ -48,33 +59,35 @@ IF file not found:
|
|
|
48
59
|
OUTPUT: "No prjct project. Run /p:init first."
|
|
49
60
|
STOP
|
|
50
61
|
|
|
51
|
-
## Step 2: Check
|
|
62
|
+
## Step 2: Check Current State
|
|
52
63
|
|
|
53
|
-
|
|
64
|
+
### Read state.json (source of truth)
|
|
65
|
+
READ: `{statePath}`
|
|
54
66
|
|
|
55
|
-
IF file not found OR
|
|
67
|
+
IF file not found OR no currentTask:
|
|
56
68
|
OUTPUT: "⚠️ No active session to pause. Use /p:now to start one."
|
|
57
69
|
STOP
|
|
58
70
|
|
|
59
|
-
PARSE
|
|
71
|
+
PARSE JSON
|
|
72
|
+
EXTRACT: {currentTask}, {pausedTask}
|
|
60
73
|
|
|
61
|
-
IF {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
IF {currentTask} is null OR {currentTask.status} != "active":
|
|
75
|
+
IF {pausedTask} exists:
|
|
76
|
+
CALCULATE: {elapsed} = time since {pausedTask.pausedAt}
|
|
77
|
+
OUTPUT:
|
|
78
|
+
```
|
|
79
|
+
⏸️ Already paused: {pausedTask.description}
|
|
66
80
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
Paused: {elapsed} ago
|
|
82
|
+
Duration so far: {pausedTask.duration}
|
|
83
|
+
Reason: {pausedTask.pauseReason}
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
STOP
|
|
85
|
+
/p:resume to continue | /p:done to complete
|
|
86
|
+
```
|
|
87
|
+
STOP
|
|
88
|
+
ELSE:
|
|
89
|
+
OUTPUT: "⚠️ No active session to pause."
|
|
90
|
+
STOP
|
|
78
91
|
|
|
79
92
|
## Step 3: Get Pause Reason
|
|
80
93
|
|
|
@@ -89,73 +102,90 @@ IF {reason} == "blocked":
|
|
|
89
102
|
## Step 4: Calculate Duration So Far
|
|
90
103
|
|
|
91
104
|
SET: {now} = GetTimestamp()
|
|
92
|
-
|
|
93
|
-
For each event in {session.timeline}:
|
|
94
|
-
Track start/resume/pause times
|
|
95
|
-
Calculate total active time up to now
|
|
96
|
-
|
|
97
|
-
SET: {duration} = total active seconds
|
|
105
|
+
SET: {durationSeconds} = seconds between {currentTask.startedAt} and {now}
|
|
98
106
|
SET: {durationFormatted} = format as "Xh Ym" or "Xm"
|
|
99
107
|
|
|
100
|
-
## Step 5: Update
|
|
108
|
+
## Step 5: Update Storage (SOURCE OF TRUTH)
|
|
101
109
|
|
|
102
|
-
|
|
110
|
+
### Prepare paused task
|
|
103
111
|
```json
|
|
104
112
|
{
|
|
105
|
-
"id": "{
|
|
106
|
-
"
|
|
107
|
-
"task": "{session.task}",
|
|
113
|
+
"id": "{currentTask.id}",
|
|
114
|
+
"description": "{currentTask.description}",
|
|
108
115
|
"status": "paused",
|
|
109
|
-
"startedAt": "{
|
|
116
|
+
"startedAt": "{currentTask.startedAt}",
|
|
110
117
|
"pausedAt": "{now}",
|
|
118
|
+
"sessionId": "{currentTask.sessionId}",
|
|
119
|
+
"duration": {durationSeconds},
|
|
111
120
|
"pauseReason": "{reason}",
|
|
112
121
|
"pauseNote": "{blockerNote}",
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"metrics": {session.metrics},
|
|
116
|
-
"timeline": [
|
|
117
|
-
...{session.timeline},
|
|
118
|
-
{"type": "pause", "at": "{now}", "reason": "{reason}", "note": "{blockerNote}"}
|
|
119
|
-
]
|
|
122
|
+
"estimate": "{currentTask.estimate}",
|
|
123
|
+
"estimateSeconds": {currentTask.estimateSeconds}
|
|
120
124
|
}
|
|
121
125
|
```
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
### Update state.json
|
|
128
|
+
READ: `{statePath}`
|
|
129
|
+
SET: state.pausedTask = paused task object
|
|
130
|
+
SET: state.currentTask = null
|
|
131
|
+
SET: state.lastUpdated = {now}
|
|
132
|
+
WRITE: `{statePath}`
|
|
133
|
+
|
|
134
|
+
## Step 6: Generate Context (FOR CLAUDE)
|
|
125
135
|
|
|
126
|
-
|
|
136
|
+
WRITE: `{nowContextPath}`
|
|
127
137
|
|
|
128
|
-
WRITE: `{nowPath}`
|
|
129
|
-
Content:
|
|
130
138
|
```markdown
|
|
131
139
|
# NOW
|
|
132
140
|
|
|
133
|
-
⏸️ **{
|
|
141
|
+
⏸️ **{currentTask.description}** (paused)
|
|
134
142
|
|
|
135
|
-
Started: {
|
|
143
|
+
Started: {currentTask.startedAt}
|
|
136
144
|
Paused: {now}
|
|
137
145
|
Duration: {durationFormatted}
|
|
138
146
|
Reason: {reason}
|
|
139
|
-
Session: {
|
|
147
|
+
Session: {currentTask.sessionId}
|
|
140
148
|
{IF blockerNote: Note: {blockerNote}}
|
|
141
149
|
```
|
|
142
150
|
|
|
143
|
-
## Step 7:
|
|
151
|
+
## Step 7: Queue Sync Event (FOR BACKEND)
|
|
152
|
+
|
|
153
|
+
READ: `{syncPath}` or create empty array
|
|
154
|
+
APPEND event:
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"type": "task.paused",
|
|
158
|
+
"path": ["state"],
|
|
159
|
+
"data": {
|
|
160
|
+
"taskId": "{currentTask.id}",
|
|
161
|
+
"description": "{currentTask.description}",
|
|
162
|
+
"pausedAt": "{now}",
|
|
163
|
+
"duration": {durationSeconds},
|
|
164
|
+
"reason": "{reason}",
|
|
165
|
+
"note": "{blockerNote}"
|
|
166
|
+
},
|
|
167
|
+
"timestamp": "{now}",
|
|
168
|
+
"projectId": "{projectId}"
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
WRITE: `{syncPath}`
|
|
172
|
+
|
|
173
|
+
## Step 8: Log to Memory (AUDIT TRAIL)
|
|
144
174
|
|
|
145
175
|
APPEND to: `{memoryPath}`
|
|
146
176
|
|
|
147
177
|
Single line (JSONL):
|
|
148
178
|
```json
|
|
149
|
-
{"timestamp":"{now}","action":"
|
|
179
|
+
{"timestamp":"{now}","action":"task_paused","taskId":"{currentTask.id}","sessionId":"{currentTask.sessionId}","task":"{currentTask.description}","duration":{durationSeconds},"reason":"{reason}","note":"{blockerNote}"}
|
|
150
180
|
```
|
|
151
181
|
|
|
152
182
|
## Output
|
|
153
183
|
|
|
154
184
|
SUCCESS:
|
|
155
185
|
```
|
|
156
|
-
⏸️ Paused: {
|
|
186
|
+
⏸️ Paused: {currentTask.description}
|
|
157
187
|
|
|
158
|
-
Session: {
|
|
188
|
+
Session: {currentTask.sessionId}
|
|
159
189
|
Active time: {durationFormatted}
|
|
160
190
|
Reason: {reason}
|
|
161
191
|
{IF blockerNote: Note: {blockerNote}}
|
|
@@ -186,7 +216,7 @@ Next:
|
|
|
186
216
|
```
|
|
187
217
|
⏸️ Paused: implement auth
|
|
188
218
|
|
|
189
|
-
Session:
|
|
219
|
+
Session: 550e8400-e29b-41d4-a716-446655440000
|
|
190
220
|
Active time: 2h 30m
|
|
191
221
|
Reason: blocked
|
|
192
222
|
Note: Waiting for API credentials from vendor
|
|
@@ -203,7 +233,7 @@ Next:
|
|
|
203
233
|
```
|
|
204
234
|
⏸️ Paused: implement auth
|
|
205
235
|
|
|
206
|
-
Session:
|
|
236
|
+
Session: 550e8400-e29b-41d4-a716-446655440000
|
|
207
237
|
Active time: 2h 30m
|
|
208
238
|
Reason: break
|
|
209
239
|
|
|
@@ -218,25 +248,10 @@ Next:
|
|
|
218
248
|
```
|
|
219
249
|
⏸️ Paused: implement auth
|
|
220
250
|
|
|
221
|
-
Session:
|
|
251
|
+
Session: 550e8400-e29b-41d4-a716-446655440000
|
|
222
252
|
Active time: 2h 30m
|
|
223
253
|
Reason: switch
|
|
224
254
|
|
|
225
255
|
Next:
|
|
226
256
|
• /p:now <task> - Start the urgent task
|
|
227
257
|
```
|
|
228
|
-
|
|
229
|
-
### Example 4: No Reason (Interactive)
|
|
230
|
-
**Input:** `/p:pause`
|
|
231
|
-
|
|
232
|
-
**Output:**
|
|
233
|
-
```
|
|
234
|
-
Why are you pausing?
|
|
235
|
-
|
|
236
|
-
1. blocked - Waiting on something external
|
|
237
|
-
2. switch - Starting a different task
|
|
238
|
-
3. break - Taking a break
|
|
239
|
-
4. research - Need to investigate
|
|
240
|
-
|
|
241
|
-
Select [1-4]:
|
|
242
|
-
```
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
allowed-tools: [Read, Write, Bash]
|
|
3
3
|
description: 'Redo previously undone changes'
|
|
4
4
|
timestamp-rule: 'GetTimestamp() for ALL timestamps'
|
|
5
|
+
architecture: 'Write-Through (JSON → MD → Events)'
|
|
6
|
+
storage-layer: true
|
|
5
7
|
---
|
|
6
8
|
|
|
7
9
|
# /p:redo - Redo Previously Undone Snapshot
|
|
@@ -13,7 +15,7 @@ Restores a previously undone snapshot. Only works if you have recently used /p:u
|
|
|
13
15
|
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
14
16
|
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
15
17
|
- `{snapshotDir}`: `{globalPath}/snapshots`
|
|
16
|
-
- `{memoryPath}`: `{globalPath}/memory/
|
|
18
|
+
- `{memoryPath}`: `{globalPath}/memory/events.jsonl`
|
|
17
19
|
- `{redoStackPath}`: `{snapshotDir}/redo-stack.json`
|
|
18
20
|
|
|
19
21
|
## Step 1: Read Config
|
|
@@ -30,14 +32,14 @@ IF file not found:
|
|
|
30
32
|
READ: `{redoStackPath}`
|
|
31
33
|
|
|
32
34
|
IF file not found OR empty OR equals "[]":
|
|
33
|
-
OUTPUT: "
|
|
35
|
+
OUTPUT: "Nothing to redo. Use /p:undo first."
|
|
34
36
|
STOP
|
|
35
37
|
|
|
36
38
|
PARSE as JSON array
|
|
37
39
|
GET last item as {redoSnapshot}
|
|
38
40
|
|
|
39
41
|
IF array is empty:
|
|
40
|
-
OUTPUT: "
|
|
42
|
+
OUTPUT: "Nothing to redo. Use /p:undo first."
|
|
41
43
|
STOP
|
|
42
44
|
|
|
43
45
|
EXTRACT from {redoSnapshot}:
|
|
@@ -131,7 +133,7 @@ Files affected: 5
|
|
|
131
133
|
|
|
132
134
|
### Example 2: Nothing to Redo
|
|
133
135
|
```
|
|
134
|
-
|
|
136
|
+
Nothing to redo. Use /p:undo first.
|
|
135
137
|
```
|
|
136
138
|
|
|
137
139
|
## Notes
|