prjct-cli 0.12.2 → 0.13.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/CLAUDE.md +18 -6
  3. package/core/data/index.ts +19 -5
  4. package/core/data/md-base-manager.ts +203 -0
  5. package/core/data/md-queue-manager.ts +179 -0
  6. package/core/data/md-state-manager.ts +133 -0
  7. package/core/serializers/index.ts +20 -0
  8. package/core/serializers/queue-serializer.ts +210 -0
  9. package/core/serializers/state-serializer.ts +136 -0
  10. package/core/utils/file-helper.ts +12 -0
  11. package/package.json +1 -1
  12. package/packages/web/app/api/projects/[id]/stats/route.ts +6 -29
  13. package/packages/web/app/page.tsx +1 -6
  14. package/packages/web/app/project/[id]/page.tsx +34 -1
  15. package/packages/web/app/project/[id]/stats/page.tsx +11 -5
  16. package/packages/web/app/settings/page.tsx +2 -221
  17. package/packages/web/components/BlockersCard/BlockersCard.tsx +67 -0
  18. package/packages/web/components/BlockersCard/BlockersCard.types.ts +11 -0
  19. package/packages/web/components/BlockersCard/index.ts +2 -0
  20. package/packages/web/components/CommandButton/CommandButton.tsx +10 -3
  21. package/packages/web/lib/projects.ts +28 -27
  22. package/packages/web/lib/services/projects.server.ts +25 -21
  23. package/packages/web/lib/services/stats.server.ts +355 -57
  24. package/packages/web/next-env.d.ts +1 -1
  25. package/packages/web/package.json +0 -4
  26. package/templates/commands/decision.md +226 -0
  27. package/templates/commands/done.md +100 -68
  28. package/templates/commands/feature.md +102 -103
  29. package/templates/commands/idea.md +41 -38
  30. package/templates/commands/now.md +94 -33
  31. package/templates/commands/pause.md +90 -30
  32. package/templates/commands/ship.md +179 -74
  33. package/templates/commands/sync.md +324 -200
  34. package/packages/web/app/api/migrate/route.ts +0 -46
  35. package/packages/web/app/api/settings/route.ts +0 -97
  36. package/packages/web/app/api/v2/projects/[id]/unified/route.ts +0 -57
  37. package/packages/web/components/MigrationGate/MigrationGate.tsx +0 -304
  38. package/packages/web/components/MigrationGate/index.ts +0 -1
  39. package/packages/web/lib/json-loader.ts +0 -630
  40. package/packages/web/lib/services/migration.server.ts +0 -580
@@ -0,0 +1,226 @@
1
+ ---
2
+ allowed-tools: [Read, Write, Bash]
3
+ description: 'Log architectural or important decisions'
4
+ timestamp-rule: 'GetTimestamp() for ALL timestamps'
5
+ architecture: 'MD-first - MD files are source of truth'
6
+ ---
7
+
8
+ # /p:decision - Log Important Decisions
9
+
10
+ ## Architecture: MD-First
11
+
12
+ **Source of Truth**: `planning/decisions.md`
13
+
14
+ MD files are the source of truth. Write directly to MD files.
15
+
16
+ ## Context Variables
17
+ - `{projectId}`: From `.prjct/prjct.config.json`
18
+ - `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
19
+ - `{decisionsPath}`: `{globalPath}/planning/decisions.md`
20
+ - `{memoryPath}`: `{globalPath}/memory/context.jsonl`
21
+ - `{decision}`: User-provided decision (required)
22
+ - `{reasoning}`: User-provided reasoning (optional)
23
+ - `{alternatives}`: User-provided alternatives considered (optional)
24
+
25
+ ## Decision Format
26
+
27
+ Capture WHY decisions were made to avoid repeating mistakes:
28
+
29
+ ```
30
+ /p:decision "Use REST instead of GraphQL"
31
+ --reason "Simpler for this use case, team familiarity"
32
+ --alternatives "GraphQL, gRPC"
33
+ ```
34
+
35
+ Or interactive prompt:
36
+ ```
37
+ Decision: Use REST instead of GraphQL
38
+
39
+ Why did you make this decision?
40
+ > Simpler for this use case, team familiarity
41
+
42
+ What alternatives did you consider?
43
+ > GraphQL, gRPC
44
+ ```
45
+
46
+ ## Step 1: Read Config
47
+
48
+ READ: `.prjct/prjct.config.json`
49
+ EXTRACT: `projectId`
50
+
51
+ IF file not found:
52
+ OUTPUT: "No prjct project. Run /p:init first."
53
+ STOP
54
+
55
+ ## Step 2: Validate Input
56
+
57
+ IF {decision} is empty:
58
+ ASK: "What decision did you make?"
59
+ SET: {decision} = user response
60
+
61
+ IF {reasoning} is empty:
62
+ ASK: "Why did you make this decision?"
63
+ SET: {reasoning} = user response
64
+
65
+ IF {alternatives} is empty:
66
+ ASK: "What alternatives did you consider? (optional, press Enter to skip)"
67
+ SET: {alternatives} = user response OR "none documented"
68
+
69
+ ## Step 3: Generate Decision Entry
70
+
71
+ GENERATE: {decisionId} = "dec_" + 8 random alphanumeric chars
72
+ SET: {now} = GetTimestamp()
73
+
74
+ ## Step 4: Read/Create Decisions File
75
+
76
+ READ: `{decisionsPath}` (or create default if not exists)
77
+
78
+ Default structure:
79
+ ```markdown
80
+ # Decisions
81
+
82
+ Architecture decisions and their reasoning.
83
+
84
+ ## Recent
85
+
86
+ _No decisions logged yet_
87
+
88
+ ## Archive
89
+
90
+ _No archived decisions_
91
+ ```
92
+
93
+ ## Step 5: Update Decisions File (MD)
94
+
95
+ Parse existing content and add new decision under "## Recent" section:
96
+
97
+ ```markdown
98
+ # Decisions
99
+
100
+ Architecture decisions and their reasoning.
101
+
102
+ ## Recent
103
+
104
+ ### {decision}
105
+ - **ID**: {decisionId}
106
+ - **Date**: {now}
107
+ - **Reasoning**: {reasoning}
108
+ - **Alternatives**: {alternatives}
109
+ - **Context**: {current task from now.md if active}
110
+
111
+ {...existing recent decisions}
112
+
113
+ ## Archive
114
+
115
+ {...existing archive}
116
+ ```
117
+
118
+ WRITE: `{decisionsPath}`
119
+
120
+ ## Step 6: Log to Memory
121
+
122
+ APPEND to: `{memoryPath}`
123
+
124
+ Single line (JSONL):
125
+ ```json
126
+ {"timestamp":"{now}","action":"decision_logged","decisionId":"{decisionId}","decision":"{decision}","reasoning":"{reasoning}","alternatives":"{alternatives}"}
127
+ ```
128
+
129
+ ## Output
130
+
131
+ SUCCESS:
132
+ ```
133
+ 📝 Decision logged: {decision}
134
+
135
+ ID: {decisionId}
136
+ Reasoning: {reasoning}
137
+ Alternatives: {alternatives}
138
+
139
+ Next:
140
+ • Continue working on your task
141
+ • /p:recap - Review decisions made
142
+ ```
143
+
144
+ ## Error Handling
145
+
146
+ | Error | Response | Action |
147
+ |-------|----------|--------|
148
+ | No project | "No prjct project" | STOP |
149
+ | No decision provided | Ask for decision | WAIT |
150
+ | Write fails | Log warning | CONTINUE |
151
+
152
+ ## Examples
153
+
154
+ ### Example 1: Full Decision with All Fields
155
+ **Input:** `/p:decision "Use Zustand for state management" --reason "Lighter than Redux, better DX" --alternatives "Redux, MobX, Jotai"`
156
+
157
+ **Output:**
158
+ ```
159
+ 📝 Decision logged: Use Zustand for state management
160
+
161
+ ID: dec_abc12345
162
+ Reasoning: Lighter than Redux, better DX
163
+ Alternatives: Redux, MobX, Jotai
164
+
165
+ Next: Continue working | /p:recap
166
+ ```
167
+
168
+ ### Example 2: Interactive Mode
169
+ **Input:** `/p:decision`
170
+
171
+ **Prompt flow:**
172
+ ```
173
+ What decision did you make?
174
+ > Use PostgreSQL instead of MongoDB
175
+
176
+ Why did you make this decision?
177
+ > Need relational data with joins, better ACID compliance
178
+
179
+ What alternatives did you consider? (Enter to skip)
180
+ > MongoDB, SQLite
181
+ ```
182
+
183
+ **Output:**
184
+ ```
185
+ 📝 Decision logged: Use PostgreSQL instead of MongoDB
186
+
187
+ ID: dec_xyz98765
188
+ Reasoning: Need relational data with joins, better ACID compliance
189
+ Alternatives: MongoDB, SQLite
190
+
191
+ Next: Continue working | /p:recap
192
+ ```
193
+
194
+ ### Example 3: Quick Decision (minimal)
195
+ **Input:** `/p:decision "Skip tests for MVP"`
196
+
197
+ **Prompt:**
198
+ ```
199
+ Why did you make this decision?
200
+ > Time constraint, will add before launch
201
+ ```
202
+
203
+ **Output:**
204
+ ```
205
+ 📝 Decision logged: Skip tests for MVP
206
+
207
+ ID: dec_qrs45678
208
+ Reasoning: Time constraint, will add before launch
209
+ Alternatives: none documented
210
+
211
+ Next: Continue working | /p:recap
212
+ ```
213
+
214
+ ## Use Cases
215
+
216
+ When to log a decision:
217
+ - Choosing between technologies/libraries
218
+ - Architectural pattern selection
219
+ - Trade-off decisions (speed vs quality)
220
+ - Deviation from best practices (and why)
221
+ - Postponing technical debt intentionally
222
+
223
+ This creates institutional memory to avoid:
224
+ - Repeating the same debates
225
+ - Forgetting why something was done a certain way
226
+ - Making inconsistent choices across the codebase
@@ -2,29 +2,38 @@
2
2
  allowed-tools: [Read, Write, Bash]
3
3
  description: 'Complete current task with session metrics'
4
4
  timestamp-rule: 'GetTimestamp() for all timestamps'
5
- architecture: 'JSON-first - Write to data/*.json, views are generated'
5
+ architecture: 'MD-first - MD files are source of truth'
6
6
  ---
7
7
 
8
8
  # /p:done - Complete Current Task with Session Metrics
9
9
 
10
- ## Architecture: JSON-First
10
+ ## Architecture: MD-First
11
11
 
12
- **Source of Truth**: `data/state.json`, `data/queue.json`, `data/metrics.json`
13
- **Generated Views**: `views/now.md`, `views/next.md` (auto-generated)
12
+ **Source of Truth**: `core/now.md`, `core/next.md`, `progress/shipped.md`
14
13
 
15
- All writes go to JSON. After writing, views are auto-regenerated.
14
+ MD files are the source of truth. Write directly to MD files.
16
15
 
17
16
  ## Context Variables
18
17
  - `{projectId}`: From `.prjct/prjct.config.json`
19
18
  - `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
20
- - `{dataPath}`: `{globalPath}/data`
21
- - `{statePath}`: `{dataPath}/state.json`
22
- - `{queuePath}`: `{dataPath}/queue.json`
23
- - `{metricsJsonPath}`: `{dataPath}/metrics.json`
19
+ - `{nowPath}`: `{globalPath}/core/now.md`
20
+ - `{nextPath}`: `{globalPath}/core/next.md`
24
21
  - `{sessionPath}`: `{globalPath}/sessions/current.json`
25
22
  - `{archiveDir}`: `{globalPath}/sessions/archive`
26
23
  - `{memoryPath}`: `{globalPath}/memory/context.jsonl`
27
24
 
25
+ ## Accuracy Calculation
26
+
27
+ When task had an estimate, calculate accuracy:
28
+ - `{accuracy}` = 100 - |((actual - estimate) / estimate) * 100|
29
+ - Cap accuracy at 100% (can't be more than 100%)
30
+ - If actual < estimate: bonus (under-budget)
31
+ - If actual > estimate: penalty (over-budget)
32
+
33
+ **Example:**
34
+ - Estimate: 2h (7200s), Actual: 2h 15m (8100s)
35
+ - Accuracy = 100 - |((8100-7200)/7200)*100| = 100 - 12.5 = 87.5%
36
+
28
37
  ## Step 1: Read Config
29
38
 
30
39
  READ: `.prjct/prjct.config.json`
@@ -36,11 +45,16 @@ IF file not found:
36
45
 
37
46
  ## Step 2: Check Session State
38
47
 
39
- ### Read state.json (source of truth)
40
- READ: `{statePath}`
48
+ ### Read now.md (source of truth)
49
+ READ: `{nowPath}`
41
50
 
42
- IF file exists AND has currentTask:
43
- EXTRACT: {task} = state.currentTask
51
+ IF file exists AND has task content:
52
+ PARSE MD format:
53
+ - Look for `**Task description**` (bold text = current task)
54
+ - Look for `Started: {timestamp}`
55
+ - Look for `Session: {sessionId}`
56
+ - Look for `Estimate: {estimate}` (optional)
57
+ EXTRACT: {task}, {startedAt}, {sessionId}, {estimate}
44
58
  GOTO Step 3 (Session Completion)
45
59
 
46
60
  ### Try structured session (for detailed metrics)
@@ -50,9 +64,9 @@ IF file exists:
50
64
  PARSE as JSON
51
65
  EXTRACT: {session} object
52
66
  ELSE:
53
- CREATE session from state.currentTask data
67
+ CREATE session from now.md data
54
68
 
55
- IF no currentTask in state.json:
69
+ IF no task in now.md:
56
70
  OUTPUT: "⚠️ No active task to complete. Use /p:now to start one."
57
71
  STOP
58
72
 
@@ -78,6 +92,15 @@ PARSE output for:
78
92
  - {linesAdded}: insertions
79
93
  - {linesRemoved}: deletions
80
94
 
95
+ ### Calculate Accuracy (if estimate exists)
96
+ IF {session.estimateSeconds} exists AND > 0:
97
+ {accuracy} = 100 - Math.abs(((duration - estimateSeconds) / estimateSeconds) * 100)
98
+ {accuracy} = Math.max(0, Math.min(100, {accuracy})) // Cap between 0-100
99
+ {accuracyLabel} = accuracy >= 80 ? "✅" : accuracy >= 50 ? "⚠️" : "❌"
100
+ ELSE:
101
+ {accuracy} = null
102
+ {accuracyLabel} = null
103
+
81
104
  ### Update Session Object
82
105
  ```json
83
106
  {
@@ -89,6 +112,9 @@ PARSE output for:
89
112
  "pausedAt": null,
90
113
  "completedAt": "{now}",
91
114
  "duration": {duration},
115
+ "estimate": "{session.estimate}",
116
+ "estimateSeconds": {session.estimateSeconds},
117
+ "accuracy": {accuracy},
92
118
  "metrics": {
93
119
  "filesChanged": {filesChanged},
94
120
  "linesAdded": {linesAdded},
@@ -115,20 +141,19 @@ BASH: `mkdir -p {archiveDir}/{yearMonth}`
115
141
  WRITE: `{archiveDir}/{yearMonth}/{session.id}.json`
116
142
  Content: Updated session object from Step 3
117
143
 
118
- ## Step 5: Clear Current State (JSON)
144
+ ## Step 5: Clear Current State (MD)
119
145
 
120
- ### Clear state.json (SOURCE OF TRUTH)
121
- READ: `{statePath}`
146
+ ### Clear now.md (SOURCE OF TRUTH)
122
147
 
123
- UPDATE state.json:
124
- ```json
125
- {
126
- "currentTask": null,
127
- "lastUpdated": "{now}"
128
- }
129
- ```
148
+ WRITE: `{nowPath}`
149
+
150
+ ```markdown
151
+ # NOW
130
152
 
131
- WRITE: `{statePath}`
153
+ _No active task_
154
+
155
+ Use `/p:now <task>` to start working.
156
+ ```
132
157
 
133
158
  ### Clear session.json
134
159
  WRITE: `{sessionPath}`
@@ -137,60 +162,46 @@ Content:
137
162
  {}
138
163
  ```
139
164
 
140
- ## Step 6: Update Metrics (JSON)
165
+ ## Step 6: Log Completion
141
166
 
142
- READ: `{metricsJsonPath}` (or create default if not exists)
143
-
144
- ### Update metrics.json
145
- ```json
146
- {
147
- "velocity": {
148
- "tasksPerDay": {calculated},
149
- "avgTaskDuration": {calculated}
150
- },
151
- "allTime": {
152
- "totalTasks": {increment by 1},
153
- "totalTime": {add duration},
154
- "daysActive": {recalculate}
155
- },
156
- "recentTasks": [
157
- {
158
- "task": "{session.task}",
159
- "duration": {duration},
160
- "completedAt": "{now}",
161
- "metrics": {
162
- "filesChanged": {filesChanged},
163
- "linesAdded": {linesAdded},
164
- "linesRemoved": {linesRemoved},
165
- "commits": {commits}
166
- }
167
- },
168
- ...existing recent tasks (keep last 10)
169
- ],
170
- "lastUpdated": "{now}"
171
- }
172
- ```
173
-
174
- WRITE: `{metricsJsonPath}`
175
-
176
- ## Step 7: Generate Views
177
-
178
- BASH: `cd {projectRoot} && npx prjct-generate-views --project={projectId}`
179
-
180
- Note: This regenerates views/now.md, views/next.md from JSON automatically.
167
+ Metrics are calculated from session history and memory log.
168
+ No separate metrics.json needed - all data is in MD files and JSONL logs.
181
169
 
182
170
  ## Step 8: Log to Memory
183
171
 
184
172
  APPEND to: `{memoryPath}`
185
173
 
186
174
  Single line (JSONL format):
175
+
176
+ IF {accuracy} exists:
177
+ ```json
178
+ {"timestamp":"{now}","action":"session_completed","sessionId":"{session.id}","task":"{session.task}","duration":{duration},"estimate":{estimateSeconds},"accuracy":{accuracy},"metrics":{"files":{filesChanged},"added":{linesAdded},"removed":{linesRemoved},"commits":{commits}}}
179
+ ```
180
+
181
+ ELSE:
187
182
  ```json
188
183
  {"timestamp":"{now}","action":"session_completed","sessionId":"{session.id}","task":"{session.task}","duration":{duration},"metrics":{"files":{filesChanged},"added":{linesAdded},"removed":{linesRemoved},"commits":{commits}}}
189
184
  ```
190
185
 
191
186
  ## Output
192
187
 
193
- SUCCESS:
188
+ SUCCESS (with estimate):
189
+ ```
190
+ ✅ {session.task} ({durationFormatted})
191
+
192
+ Estimate: {estimate} | Actual: {durationFormatted} | {accuracyLabel} Accuracy: {accuracy}%
193
+
194
+ Session: {session.id}
195
+ Files: {filesChanged} | +{linesAdded}/-{linesRemoved}
196
+ Commits: {commits}
197
+
198
+ Next:
199
+ • /p:now - Start next task
200
+ • /p:ship - Ship completed work
201
+ • /p:progress - View metrics
202
+ ```
203
+
204
+ SUCCESS (without estimate):
194
205
  ```
195
206
  ✅ {session.task} ({durationFormatted})
196
207
 
@@ -216,7 +227,7 @@ Next:
216
227
 
217
228
  ## Examples
218
229
 
219
- ### Example 1: Full Session Completion
230
+ ### Example 1: Full Session Completion (with estimate)
220
231
  **Session:**
221
232
  ```json
222
233
  {
@@ -224,6 +235,8 @@ Next:
224
235
  "task": "implement authentication",
225
236
  "status": "active",
226
237
  "startedAt": "2025-12-07T10:00:00.000Z",
238
+ "estimate": "2h",
239
+ "estimateSeconds": 7200,
227
240
  "timeline": [
228
241
  {"type": "start", "at": "2025-12-07T10:00:00.000Z"}
229
242
  ]
@@ -234,7 +247,26 @@ Next:
234
247
  - 3 commits
235
248
  - 5 files changed
236
249
  - +120/-30 lines
250
+ - Actual duration: 2h 15m (8100s)
251
+ - Accuracy: 100 - |((8100-7200)/7200)*100| = 87.5%
252
+
253
+ **Output:**
254
+ ```
255
+ ✅ implement authentication (2h 15m)
256
+
257
+ Estimate: 2h | Actual: 2h 15m | ✅ Accuracy: 88%
258
+
259
+ Session: sess_abc12345
260
+ Files: 5 | +120/-30
261
+ Commits: 3
262
+
263
+ Next:
264
+ • /p:now - Start next task
265
+ • /p:ship - Ship completed work
266
+ • /p:progress - View metrics
267
+ ```
237
268
 
269
+ ### Example 1b: Session Completion (without estimate)
238
270
  **Output:**
239
271
  ```
240
272
  ✅ implement authentication (2h 15m)