planr 0.0.1 → 1.1.15
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/LICENSE.md +21 -0
- package/README.md +144 -0
- package/docs/ARCHITECTURE.md +75 -0
- package/docs/CI.md +54 -0
- package/docs/CLAUDE_CODE.md +33 -0
- package/docs/CLI_REFERENCE.md +124 -0
- package/docs/CODEX.md +48 -0
- package/docs/CURSOR.md +30 -0
- package/docs/GOALS.md +155 -0
- package/docs/HANDOFFS_AND_STORIES.md +121 -0
- package/docs/IMPORT.md +21 -0
- package/docs/INSTALL.md +98 -0
- package/docs/MCP_CONTRACT.md +70 -0
- package/docs/MCP_GUIDE.md +40 -0
- package/docs/NPM.md +40 -0
- package/docs/OPERATING_MODEL.md +250 -0
- package/docs/RELEASE.md +140 -0
- package/docs/SECURITY.md +8 -0
- package/docs/SKILLS.md +278 -0
- package/docs/TASK_GRAPH_MODEL.md +222 -0
- package/docs/TESTING.md +87 -0
- package/docs/TROUBLESHOOTING.md +26 -0
- package/docs/fixtures/mcp-contract.json +92 -0
- package/docs/planr-spec/ADRS.md +160 -0
- package/docs/planr-spec/AI_SPEC.md +138 -0
- package/docs/planr-spec/ANALYTICS_OBSERVABILITY_SPEC.md +124 -0
- package/docs/planr-spec/API_AND_DATA_MODEL.md +517 -0
- package/docs/planr-spec/BACKEND_IMPLEMENTATION_SPEC.md +178 -0
- package/docs/planr-spec/CLIENT_IMPLEMENTATION_SPEC.md +119 -0
- package/docs/planr-spec/DESIGN_SYSTEM_SPEC.md +102 -0
- package/docs/planr-spec/PRODUCT_SPEC.md +193 -0
- package/docs/planr-spec/QA_ACCEPTANCE_TESTS.md +146 -0
- package/docs/planr-spec/README.md +67 -0
- package/docs/planr-spec/REFERENCES.md +29 -0
- package/docs/planr-spec/RELEASE_READINESS.md +95 -0
- package/docs/planr-spec/SAFETY_PRIVACY_SECURITY.md +169 -0
- package/docs/planr-spec/TASKS.md +932 -0
- package/docs/planr-spec/TECH_ARCHITECTURE.md +143 -0
- package/docs/planr-spec/UX_FLOWS.md +235 -0
- package/docs/planr-spec/V1_1_DIFFERENTIATION_CONTRACT.md +177 -0
- package/docs/planr-spec.zip +0 -0
- package/npm/bin/planr.js +54 -0
- package/npm/native/darwin-arm64/planr +0 -0
- package/npm/native/darwin-x86_64/planr +0 -0
- package/npm/native/linux-arm64/planr +0 -0
- package/npm/native/linux-x86_64/planr +0 -0
- package/package.json +27 -8
- package/plugins/planr/.claude-plugin/plugin.json +11 -0
- package/plugins/planr/.codex-plugin/plugin.json +25 -0
- package/plugins/planr/agents/planr-reviewer.md +12 -0
- package/plugins/planr/agents/planr-worker.md +10 -0
- package/plugins/planr/skills/planr/SKILL.md +52 -0
- package/plugins/planr/skills/planr-goal/SKILL.md +69 -0
- package/plugins/planr/skills/planr-loop/SKILL.md +112 -0
- package/plugins/planr/skills/planr-loop/agents/planr-reviewer.toml +17 -0
- package/plugins/planr/skills/planr-loop/agents/planr-worker.toml +14 -0
- package/plugins/planr/skills/planr-plan/SKILL.md +58 -0
- package/plugins/planr/skills/planr-review/SKILL.md +49 -0
- package/plugins/planr/skills/planr-status/SKILL.md +50 -0
- package/plugins/planr/skills/planr-summary/SKILL.md +28 -0
- package/plugins/planr/skills/planr-task-graph/SKILL.md +228 -0
- package/plugins/planr/skills/planr-verify-web/SKILL.md +76 -0
- package/plugins/planr/skills/planr-work/SKILL.md +68 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
# API And Data Model
|
|
2
|
+
|
|
3
|
+
## Storage Locations
|
|
4
|
+
|
|
5
|
+
- SQLite: authoritative map graph state, picks, contexts, logs, runs, events, search indexes.
|
|
6
|
+
- `.planr/project/*.md`: durable project context pack.
|
|
7
|
+
- `.planr/plans/product/<slug>/`: product specification packages.
|
|
8
|
+
- `.planr/plans/build/*.plan.md`: Markdown implementation plans.
|
|
9
|
+
- `.planr/reviews/*.review.md`: optional saved review artifacts.
|
|
10
|
+
- Git: source diffs, commits, branches, and worktrees.
|
|
11
|
+
|
|
12
|
+
## Core Tables
|
|
13
|
+
|
|
14
|
+
### projects
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
id TEXT PRIMARY KEY
|
|
18
|
+
name TEXT NOT NULL
|
|
19
|
+
root_path TEXT NOT NULL
|
|
20
|
+
description TEXT
|
|
21
|
+
status TEXT NOT NULL
|
|
22
|
+
metadata JSON
|
|
23
|
+
created_at DATETIME
|
|
24
|
+
updated_at DATETIME
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### items
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
id TEXT PRIMARY KEY
|
|
31
|
+
project_id TEXT NOT NULL
|
|
32
|
+
parent_item_id TEXT
|
|
33
|
+
title TEXT NOT NULL
|
|
34
|
+
description TEXT
|
|
35
|
+
status TEXT NOT NULL
|
|
36
|
+
work_type TEXT NOT NULL
|
|
37
|
+
priority INTEGER
|
|
38
|
+
worker_id TEXT
|
|
39
|
+
plan_path TEXT
|
|
40
|
+
pick_token TEXT
|
|
41
|
+
picked_at DATETIME
|
|
42
|
+
last_heartbeat_at DATETIME
|
|
43
|
+
progress_percent INTEGER
|
|
44
|
+
progress_note TEXT
|
|
45
|
+
paused_at DATETIME
|
|
46
|
+
timeout_seconds INTEGER
|
|
47
|
+
max_retries INTEGER
|
|
48
|
+
retry_count INTEGER
|
|
49
|
+
retry_backoff TEXT
|
|
50
|
+
retry_delay_ms INTEGER
|
|
51
|
+
pre_condition TEXT
|
|
52
|
+
post_condition TEXT
|
|
53
|
+
approval_status TEXT
|
|
54
|
+
approval_requested_at DATETIME
|
|
55
|
+
approved_by TEXT
|
|
56
|
+
approval_comment TEXT
|
|
57
|
+
started_at DATETIME
|
|
58
|
+
completed_at DATETIME
|
|
59
|
+
result JSON
|
|
60
|
+
error TEXT
|
|
61
|
+
metadata JSON
|
|
62
|
+
created_at DATETIME
|
|
63
|
+
updated_at DATETIME
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Item work types:
|
|
67
|
+
|
|
68
|
+
- generic
|
|
69
|
+
- research
|
|
70
|
+
- plan
|
|
71
|
+
- code
|
|
72
|
+
- review
|
|
73
|
+
- fix
|
|
74
|
+
- test
|
|
75
|
+
- shell
|
|
76
|
+
- release
|
|
77
|
+
|
|
78
|
+
Item statuses:
|
|
79
|
+
|
|
80
|
+
- pending
|
|
81
|
+
- ready
|
|
82
|
+
- picked
|
|
83
|
+
- running
|
|
84
|
+
- in_review
|
|
85
|
+
- blocked
|
|
86
|
+
- closed
|
|
87
|
+
- closed_partial
|
|
88
|
+
- failed
|
|
89
|
+
- cancelled
|
|
90
|
+
|
|
91
|
+
### links
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
id INTEGER PRIMARY KEY
|
|
95
|
+
from_item TEXT NOT NULL
|
|
96
|
+
to_item TEXT NOT NULL
|
|
97
|
+
kind TEXT NOT NULL
|
|
98
|
+
condition TEXT NOT NULL
|
|
99
|
+
metadata JSON
|
|
100
|
+
UNIQUE(from_item, to_item, kind)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Link kinds:
|
|
104
|
+
|
|
105
|
+
- blocks: upstream must complete before downstream is ready.
|
|
106
|
+
- hands_to: upstream result is included in downstream handoff.
|
|
107
|
+
- reviews: review item blocks parent/target closure.
|
|
108
|
+
- relates_to: non-blocking context relationship.
|
|
109
|
+
|
|
110
|
+
### plans
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
id TEXT PRIMARY KEY
|
|
114
|
+
project_id TEXT NOT NULL
|
|
115
|
+
stage TEXT NOT NULL
|
|
116
|
+
path TEXT NOT NULL
|
|
117
|
+
title TEXT NOT NULL
|
|
118
|
+
slug TEXT NOT NULL
|
|
119
|
+
package_manifest JSON
|
|
120
|
+
frontmatter JSON
|
|
121
|
+
parse_status TEXT NOT NULL
|
|
122
|
+
content_hash TEXT NOT NULL
|
|
123
|
+
created_at DATETIME
|
|
124
|
+
updated_at DATETIME
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Plan stages:
|
|
128
|
+
|
|
129
|
+
- product
|
|
130
|
+
- build
|
|
131
|
+
- review
|
|
132
|
+
|
|
133
|
+
### source_links
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
id INTEGER PRIMARY KEY
|
|
137
|
+
source_type TEXT NOT NULL
|
|
138
|
+
source_id TEXT NOT NULL
|
|
139
|
+
item_id TEXT NOT NULL
|
|
140
|
+
section_id TEXT
|
|
141
|
+
relationship TEXT NOT NULL
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Relationships:
|
|
145
|
+
|
|
146
|
+
- scopes
|
|
147
|
+
- implements
|
|
148
|
+
- verifies
|
|
149
|
+
- reviews
|
|
150
|
+
- references
|
|
151
|
+
|
|
152
|
+
### contexts
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
id TEXT PRIMARY KEY
|
|
156
|
+
project_id TEXT NOT NULL
|
|
157
|
+
item_id TEXT
|
|
158
|
+
worker_id TEXT
|
|
159
|
+
kind TEXT NOT NULL
|
|
160
|
+
content TEXT NOT NULL
|
|
161
|
+
tags JSON
|
|
162
|
+
created_at DATETIME
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Kinds:
|
|
166
|
+
|
|
167
|
+
- discovery
|
|
168
|
+
- decision
|
|
169
|
+
- constraint
|
|
170
|
+
- pattern
|
|
171
|
+
- blocker
|
|
172
|
+
- bug
|
|
173
|
+
- risk
|
|
174
|
+
|
|
175
|
+
### runs
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
id TEXT PRIMARY KEY
|
|
179
|
+
project_id TEXT NOT NULL
|
|
180
|
+
item_id TEXT NOT NULL
|
|
181
|
+
worker_id TEXT NOT NULL
|
|
182
|
+
client TEXT NOT NULL
|
|
183
|
+
profile TEXT
|
|
184
|
+
command TEXT
|
|
185
|
+
cwd TEXT
|
|
186
|
+
worktree_path TEXT
|
|
187
|
+
status TEXT NOT NULL
|
|
188
|
+
started_at DATETIME
|
|
189
|
+
ended_at DATETIME
|
|
190
|
+
exit_code INTEGER
|
|
191
|
+
metadata JSON
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Clients:
|
|
195
|
+
|
|
196
|
+
- codex
|
|
197
|
+
- claude-code
|
|
198
|
+
- cursor
|
|
199
|
+
- generic-mcp
|
|
200
|
+
- human
|
|
201
|
+
- ci
|
|
202
|
+
|
|
203
|
+
### logs
|
|
204
|
+
|
|
205
|
+
```text
|
|
206
|
+
id TEXT PRIMARY KEY
|
|
207
|
+
project_id TEXT NOT NULL
|
|
208
|
+
item_id TEXT NOT NULL
|
|
209
|
+
run_id TEXT
|
|
210
|
+
kind TEXT NOT NULL
|
|
211
|
+
summary TEXT NOT NULL
|
|
212
|
+
files JSON
|
|
213
|
+
commands JSON
|
|
214
|
+
tests JSON
|
|
215
|
+
review_findings JSON
|
|
216
|
+
blocked_or_unverified JSON
|
|
217
|
+
created_at DATETIME
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Log kinds:
|
|
221
|
+
|
|
222
|
+
- completion
|
|
223
|
+
- review
|
|
224
|
+
- failure
|
|
225
|
+
- handoff
|
|
226
|
+
- verification
|
|
227
|
+
|
|
228
|
+
### artifacts
|
|
229
|
+
|
|
230
|
+
```text
|
|
231
|
+
id TEXT PRIMARY KEY
|
|
232
|
+
project_id TEXT NOT NULL
|
|
233
|
+
item_id TEXT
|
|
234
|
+
name TEXT NOT NULL
|
|
235
|
+
kind TEXT
|
|
236
|
+
path TEXT
|
|
237
|
+
content TEXT
|
|
238
|
+
mime_type TEXT
|
|
239
|
+
size_bytes INTEGER
|
|
240
|
+
metadata JSON
|
|
241
|
+
created_at DATETIME
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### events
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
id INTEGER PRIMARY KEY
|
|
248
|
+
project_id TEXT
|
|
249
|
+
item_id TEXT
|
|
250
|
+
worker_id TEXT
|
|
251
|
+
event_type TEXT NOT NULL
|
|
252
|
+
payload JSON
|
|
253
|
+
timestamp DATETIME
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Plan Package Contract
|
|
257
|
+
|
|
258
|
+
Product plan packages use this structure:
|
|
259
|
+
|
|
260
|
+
```text
|
|
261
|
+
.planr/plans/product/<slug>/
|
|
262
|
+
README.md
|
|
263
|
+
PRODUCT_SPEC.md
|
|
264
|
+
UX_FLOWS.md
|
|
265
|
+
DESIGN_SYSTEM_SPEC.md
|
|
266
|
+
TECH_ARCHITECTURE.md
|
|
267
|
+
ADRS.md
|
|
268
|
+
AI_SPEC.md
|
|
269
|
+
SAFETY_PRIVACY_SECURITY.md
|
|
270
|
+
API_AND_DATA_MODEL.md
|
|
271
|
+
CLIENT_IMPLEMENTATION_SPEC.md
|
|
272
|
+
BACKEND_IMPLEMENTATION_SPEC.md
|
|
273
|
+
ANALYTICS_OBSERVABILITY_SPEC.md
|
|
274
|
+
QA_ACCEPTANCE_TESTS.md
|
|
275
|
+
RELEASE_READINESS.md
|
|
276
|
+
TASKS.md
|
|
277
|
+
REFERENCES.md
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
- REQ-API-001: Plan packages must include a manifest with generated date, source prompt, assumptions, and included documents.
|
|
281
|
+
- REQ-API-002: Plan work lists are candidate work, not live map items until accepted.
|
|
282
|
+
|
|
283
|
+
## Build Plan Contract
|
|
284
|
+
|
|
285
|
+
Plan files use this minimum shape:
|
|
286
|
+
|
|
287
|
+
```markdown
|
|
288
|
+
---
|
|
289
|
+
name: short-name
|
|
290
|
+
overview: One paragraph.
|
|
291
|
+
todos:
|
|
292
|
+
- id: phase-1
|
|
293
|
+
content: Summary item.
|
|
294
|
+
status: pending
|
|
295
|
+
isProject: false
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
# Plan Title
|
|
299
|
+
|
|
300
|
+
## Scope Decision
|
|
301
|
+
## Ownership Target
|
|
302
|
+
## Existing Leverage
|
|
303
|
+
## Phase 1: ...
|
|
304
|
+
## Out Of Scope
|
|
305
|
+
## Verification
|
|
306
|
+
## Acceptance Criteria
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- REQ-API-010: Plan parsing must preserve unknown frontmatter fields.
|
|
310
|
+
- REQ-API-011: Plan parsing failure must not delete or rewrite the original Markdown.
|
|
311
|
+
- REQ-API-012: Closure status must not be inferred solely from Markdown checkboxes.
|
|
312
|
+
|
|
313
|
+
## CLI API
|
|
314
|
+
|
|
315
|
+
### Project
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
planr project init [--client codex|claude|cursor|all] [--force]
|
|
319
|
+
planr project show [--json]
|
|
320
|
+
planr project list [--json]
|
|
321
|
+
planr doctor [--client codex|claude|cursor|all]
|
|
322
|
+
planr install codex|claude|cursor [--dry-run]
|
|
323
|
+
planr prompt cli|mcp|http [--client codex|claude|cursor|all]
|
|
324
|
+
planr mcp
|
|
325
|
+
planr serve --port 7526
|
|
326
|
+
planr import <file> [--preview] [--confirm]
|
|
327
|
+
planr export --out planr.json [--include-plans] [--include-logs] [--template-name "..."] [--tag tag]
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Plan
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
planr plan new "App idea" [--platform web] [--ai] [--backend]
|
|
334
|
+
planr plan refine <plan-id>
|
|
335
|
+
planr plan split <plan-id> --slice "MVP backend"
|
|
336
|
+
planr plan check <plan-id>
|
|
337
|
+
planr plan show <plan-id>
|
|
338
|
+
planr plan archive <plan-id>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Map
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
planr map show
|
|
345
|
+
planr map build --from <plan-id>
|
|
346
|
+
planr map status
|
|
347
|
+
planr map preview --close <item-id>
|
|
348
|
+
planr map unlocks <item-id>
|
|
349
|
+
planr map lookahead [--from <item-id>]
|
|
350
|
+
planr item create "title" --description "..." [--after item-id] [--timeout-seconds N] [--max-retries N] [--retry-backoff fixed|exponential] [--retry-delay-ms N] [--pre "..."] [--post "..."]
|
|
351
|
+
planr item breakdown <item-id> --into "A, B, C"
|
|
352
|
+
planr item insert "title" --description "..." --after <item-id> [--before <item-id>] [--preview|--confirm]
|
|
353
|
+
planr item amend <item-id> --note "..."
|
|
354
|
+
planr item replan <parent-id> --into "A, B, C" [--preview|--confirm]
|
|
355
|
+
planr link add <from-item> <to-item> --type blocks
|
|
356
|
+
planr pick
|
|
357
|
+
planr pick release <item-id> [--force]
|
|
358
|
+
planr pick heartbeat [item-id]
|
|
359
|
+
planr pick progress <item-id> --percent 0..100 [--note "..."]
|
|
360
|
+
planr pick pause <item-id> [--note "..."]
|
|
361
|
+
planr pick resume <item-id>
|
|
362
|
+
planr pick stale [--older-than-seconds 900] [--release]
|
|
363
|
+
planr recover sweep [--older-than-seconds 900] [--apply]
|
|
364
|
+
planr approval request <item-id> [--reason "..."]
|
|
365
|
+
planr approval approve <item-id> --by "name" [--comment "..."]
|
|
366
|
+
planr approval deny <item-id> --by "name" [--comment "..."]
|
|
367
|
+
planr approval list [--open]
|
|
368
|
+
planr artifact add "name" [--item <item-id>] [--kind evidence] [--path file] [--content "..."]
|
|
369
|
+
planr artifact show <artifact-id>
|
|
370
|
+
planr artifact list [--item <item-id>]
|
|
371
|
+
planr event list [--item <item-id>] [--limit 50]
|
|
372
|
+
planr debug bundle [--item <item-id>] --preview
|
|
373
|
+
planr log add --item <item-id> --summary "..." [--files a,b] [--cmd "..."]
|
|
374
|
+
planr review request <item-id>
|
|
375
|
+
planr review annotate <item-id> --message "..." [--severity info|warning|blocking] [--file path] [--line N] [--author "..."]
|
|
376
|
+
planr review ingest <item-id> (--from feedback.json|--stdin)
|
|
377
|
+
planr review artifact <review-item-id> [--out path]
|
|
378
|
+
planr review evidence <item-id> [--pr-url https://...]
|
|
379
|
+
planr review close <review-item-id> --verdict complete|not-complete|unclear [--close-target]
|
|
380
|
+
planr close [item-id] --summary "..." [--next]
|
|
381
|
+
planr done [item-id] --summary "..." [--files a --files b] [--cmd "..."] [--tests "..."] [--review] [--next]
|
|
382
|
+
planr map lane --critical
|
|
383
|
+
planr map pressure
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## MCP Tools
|
|
387
|
+
|
|
388
|
+
- `planr_project_show`
|
|
389
|
+
- `planr_map_show`
|
|
390
|
+
- `planr_map_status`
|
|
391
|
+
- `planr_map_preview`
|
|
392
|
+
- `planr_map_unlocks`
|
|
393
|
+
- `planr_map_lookahead`
|
|
394
|
+
- `planr_plan_create`
|
|
395
|
+
- `planr_plan_refine`
|
|
396
|
+
- `planr_plan_split`
|
|
397
|
+
- `planr_plan_check`
|
|
398
|
+
- `planr_plan_link`
|
|
399
|
+
- `planr_map_build`
|
|
400
|
+
- `planr_item_create`
|
|
401
|
+
- `planr_item_breakdown`
|
|
402
|
+
- `planr_item_insert`
|
|
403
|
+
- `planr_item_amend`
|
|
404
|
+
- `planr_item_replan`
|
|
405
|
+
- `planr_pick_item`
|
|
406
|
+
- `planr_pick_heartbeat`
|
|
407
|
+
- `planr_pick_progress`
|
|
408
|
+
- `planr_pick_pause`
|
|
409
|
+
- `planr_pick_resume`
|
|
410
|
+
- `planr_pick_stale`
|
|
411
|
+
- `planr_recover_sweep`
|
|
412
|
+
- `planr_approval_request`
|
|
413
|
+
- `planr_approval_approve`
|
|
414
|
+
- `planr_approval_deny`
|
|
415
|
+
- `planr_approval_list`
|
|
416
|
+
- `planr_artifact_add`
|
|
417
|
+
- `planr_artifact_list`
|
|
418
|
+
- `planr_artifact_show`
|
|
419
|
+
- `planr_event_list`
|
|
420
|
+
- `planr_debug_bundle`
|
|
421
|
+
- `planr_log_add`
|
|
422
|
+
- `planr_review_annotate`
|
|
423
|
+
- `planr_review_ingest`
|
|
424
|
+
- `planr_review_artifact`
|
|
425
|
+
- `planr_review_evidence`
|
|
426
|
+
- `planr_review_close`
|
|
427
|
+
- `planr_close_item`
|
|
428
|
+
- `planr_context_create`
|
|
429
|
+
- `planr_search`
|
|
430
|
+
- `planr_log_read`
|
|
431
|
+
|
|
432
|
+
## MCP Resources
|
|
433
|
+
|
|
434
|
+
- `planr://project/context`
|
|
435
|
+
- `planr://project/map`
|
|
436
|
+
- `planr://item/{id}`
|
|
437
|
+
- `planr://plan/{id}`
|
|
438
|
+
- `planr://log/{id}`
|
|
439
|
+
|
|
440
|
+
## MCP Prompts
|
|
441
|
+
|
|
442
|
+
- `planr-plan`
|
|
443
|
+
- `planr-work`
|
|
444
|
+
- `planr-review`
|
|
445
|
+
- `planr-map`
|
|
446
|
+
- `planr-summary`
|
|
447
|
+
|
|
448
|
+
## HTTP API
|
|
449
|
+
|
|
450
|
+
HTTP is optional in V1 and localhost-only by default.
|
|
451
|
+
|
|
452
|
+
```text
|
|
453
|
+
GET /review
|
|
454
|
+
GET /v1/review-workspace
|
|
455
|
+
GET /v1/projects
|
|
456
|
+
POST /v1/projects
|
|
457
|
+
GET /v1/projects/:id/map
|
|
458
|
+
GET /v1/projects/:id/items
|
|
459
|
+
POST /v1/projects/:id/items
|
|
460
|
+
POST /v1/pick
|
|
461
|
+
POST /v1/items/:id/heartbeat
|
|
462
|
+
POST /v1/items/:id/progress
|
|
463
|
+
POST /v1/items/:id/pause
|
|
464
|
+
POST /v1/items/:id/resume
|
|
465
|
+
POST /v1/items/:id/approval/request
|
|
466
|
+
POST /v1/items/:id/approval/approve
|
|
467
|
+
POST /v1/items/:id/approval/deny
|
|
468
|
+
GET /v1/approvals?open=true
|
|
469
|
+
POST /v1/artifacts
|
|
470
|
+
GET /v1/artifacts
|
|
471
|
+
GET /v1/artifacts/:id
|
|
472
|
+
GET /v1/events
|
|
473
|
+
GET /v1/debug/bundle
|
|
474
|
+
POST /v1/items/:id/log
|
|
475
|
+
POST /v1/items/:id/close
|
|
476
|
+
POST /v1/items/:id/reviews
|
|
477
|
+
POST /v1/items/:id/review-annotations
|
|
478
|
+
GET /v1/items/:id/review-evidence
|
|
479
|
+
POST /v1/items/:id/review-evidence
|
|
480
|
+
POST /v1/items/:id/review-feedback
|
|
481
|
+
POST /v1/reviews/:id/close
|
|
482
|
+
POST /v1/reviews/:id/artifact
|
|
483
|
+
GET /v1/reviews/:id/artifact
|
|
484
|
+
POST /v1/contexts
|
|
485
|
+
GET /v1/search?q=...
|
|
486
|
+
GET /v1/events/stream
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Error Model
|
|
490
|
+
|
|
491
|
+
```json
|
|
492
|
+
{
|
|
493
|
+
"error": {
|
|
494
|
+
"code": "not_found",
|
|
495
|
+
"message": "item not found",
|
|
496
|
+
"details": {}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Required codes:
|
|
502
|
+
|
|
503
|
+
- bad_request
|
|
504
|
+
- not_found
|
|
505
|
+
- conflict
|
|
506
|
+
- invalid_transition
|
|
507
|
+
- locked
|
|
508
|
+
- parse_error
|
|
509
|
+
- unauthorized_remote
|
|
510
|
+
- internal_error
|
|
511
|
+
|
|
512
|
+
## Retention
|
|
513
|
+
|
|
514
|
+
- Local database persists until user deletes it.
|
|
515
|
+
- Plan files persist in Git/repo unless archived or deleted.
|
|
516
|
+
- Log persists locally by default.
|
|
517
|
+
- Full transcript retention is off by default.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Backend Implementation Specification
|
|
2
|
+
|
|
3
|
+
## Backend Scope
|
|
4
|
+
|
|
5
|
+
The backend is a local engine embedded in the `planr` binary. It owns map state, plan parsing, search, MCP tools, optional HTTP/SSE, and integration runners.
|
|
6
|
+
|
|
7
|
+
## Language And Runtime
|
|
8
|
+
|
|
9
|
+
Recommended default:
|
|
10
|
+
|
|
11
|
+
- Rust 2021 or newer.
|
|
12
|
+
- `rusqlite` or equivalent SQLite binding.
|
|
13
|
+
- `clap` for CLI.
|
|
14
|
+
- `serde` for JSON.
|
|
15
|
+
- `tokio` and `axum` only if HTTP/SSE ships in V1.
|
|
16
|
+
|
|
17
|
+
## Core Modules
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
src/
|
|
21
|
+
core/
|
|
22
|
+
graph.rs
|
|
23
|
+
state_machine.rs
|
|
24
|
+
readiness.rs
|
|
25
|
+
log.rs
|
|
26
|
+
reviews.rs
|
|
27
|
+
search.rs
|
|
28
|
+
storage/
|
|
29
|
+
schema.rs
|
|
30
|
+
upgrades.rs
|
|
31
|
+
sqlite.rs
|
|
32
|
+
planpack/
|
|
33
|
+
markdown.rs
|
|
34
|
+
frontmatter.rs
|
|
35
|
+
project_pack.rs
|
|
36
|
+
packages.rs
|
|
37
|
+
cli/
|
|
38
|
+
mcp/
|
|
39
|
+
server/
|
|
40
|
+
agents/
|
|
41
|
+
codex.rs
|
|
42
|
+
claude_code.rs
|
|
43
|
+
cursor.rs
|
|
44
|
+
git/
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## State Machine
|
|
48
|
+
|
|
49
|
+
REQ-BE-001: State transitions must be centralized.
|
|
50
|
+
|
|
51
|
+
Required transitions:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
pending -> ready
|
|
55
|
+
ready -> picked
|
|
56
|
+
picked -> running
|
|
57
|
+
running -> picked
|
|
58
|
+
running -> closed
|
|
59
|
+
running -> blocked
|
|
60
|
+
running -> failed
|
|
61
|
+
failed -> ready
|
|
62
|
+
running -> cancelled
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Lenient single-agent convenience may allow `ready -> closed` only when no other active pick exists and the worker id is explicit.
|
|
66
|
+
|
|
67
|
+
## Readiness Engine
|
|
68
|
+
|
|
69
|
+
REQ-BE-010: Readiness must be recomputed transactionally after item creation, link changes, and closure.
|
|
70
|
+
|
|
71
|
+
REQ-BE-011: An item is ready only when all blocking and feeds-into links are closed or closed_partial.
|
|
72
|
+
|
|
73
|
+
REQ-BE-012: Parent item closure must check required children and reviews.
|
|
74
|
+
|
|
75
|
+
## Atomic Picking
|
|
76
|
+
|
|
77
|
+
REQ-BE-020: Picking must use an atomic update equivalent to:
|
|
78
|
+
|
|
79
|
+
```sql
|
|
80
|
+
UPDATE items
|
|
81
|
+
SET status = 'picked',
|
|
82
|
+
worker_id = ?,
|
|
83
|
+
pick_token = ?,
|
|
84
|
+
picked_at = CURRENT_TIMESTAMP,
|
|
85
|
+
last_heartbeat_at = CURRENT_TIMESTAMP
|
|
86
|
+
WHERE id = ? AND status = 'ready';
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The caller succeeds only when exactly one row changes.
|
|
90
|
+
|
|
91
|
+
REQ-BE-021: Heartbeat updates must require the same worker owner when an owner exists, move `picked` to `running`, and refresh `last_heartbeat_at`.
|
|
92
|
+
|
|
93
|
+
REQ-BE-022: Progress, pause, and resume must preserve `worker_id` and `pick_token`.
|
|
94
|
+
|
|
95
|
+
REQ-BE-023: Stale detection must compare `last_heartbeat_at`, `picked_at`, or `updated_at` against an explicit threshold and release only when the caller requests release.
|
|
96
|
+
|
|
97
|
+
## Approval Gates
|
|
98
|
+
|
|
99
|
+
REQ-BE-025: Approval request must store status `requested`, request time, and optional reason.
|
|
100
|
+
|
|
101
|
+
REQ-BE-026: Approval approve and deny must store the decision maker and optional comment.
|
|
102
|
+
|
|
103
|
+
REQ-BE-027: Close must reject items with approval status `requested` or `denied`.
|
|
104
|
+
|
|
105
|
+
## Markdown Plan Parser
|
|
106
|
+
|
|
107
|
+
REQ-BE-030: Parser must support YAML frontmatter and Markdown headings.
|
|
108
|
+
|
|
109
|
+
REQ-BE-031: Parser must preserve files on parse errors and store a parse error record.
|
|
110
|
+
|
|
111
|
+
REQ-BE-032: Parser must map headings to stable section ids using slug + heading depth + ordinal.
|
|
112
|
+
|
|
113
|
+
REQ-BE-033: Parser must not execute instructions contained in plan files.
|
|
114
|
+
|
|
115
|
+
## Search
|
|
116
|
+
|
|
117
|
+
REQ-BE-040: Search must index:
|
|
118
|
+
|
|
119
|
+
- item title/description;
|
|
120
|
+
- context content;
|
|
121
|
+
- plan title/manifest/frontmatter/headings;
|
|
122
|
+
- log summary;
|
|
123
|
+
- review findings summary.
|
|
124
|
+
|
|
125
|
+
REQ-BE-041: Search results must identify source type and path/id.
|
|
126
|
+
|
|
127
|
+
## MCP Server
|
|
128
|
+
|
|
129
|
+
REQ-BE-050: MCP stdio server must start with `planr mcp`.
|
|
130
|
+
|
|
131
|
+
REQ-BE-051: Tool schemas must validate all mutation inputs.
|
|
132
|
+
|
|
133
|
+
REQ-BE-052: Tools must return compact JSON optimized for agent context.
|
|
134
|
+
|
|
135
|
+
REQ-BE-053: Resources must expose read-only project, item, plan, and log data.
|
|
136
|
+
|
|
137
|
+
REQ-BE-054: Prompts must expose Planr workflow prompts.
|
|
138
|
+
|
|
139
|
+
## HTTP/SSE Server
|
|
140
|
+
|
|
141
|
+
Optional V1:
|
|
142
|
+
|
|
143
|
+
- `planr serve --port 7526`.
|
|
144
|
+
- localhost default bind.
|
|
145
|
+
- JSON REST API.
|
|
146
|
+
- SSE stream for events.
|
|
147
|
+
- no remote auth in V1 unless explicitly implemented.
|
|
148
|
+
|
|
149
|
+
## Package Import
|
|
150
|
+
|
|
151
|
+
REQ-BE-060: Import must consume Planr JSON packages created by `planr export`.
|
|
152
|
+
|
|
153
|
+
REQ-BE-061: Import preview must report package metadata, create counts, and conflicting item ids without mutating state.
|
|
154
|
+
|
|
155
|
+
REQ-BE-062: Confirmed import must restore package graph items, links, contexts, optional logs, optional plan file snapshots, and review artifacts.
|
|
156
|
+
|
|
157
|
+
## Agent Runners
|
|
158
|
+
|
|
159
|
+
Runner wrappers are optional but expected after core V1:
|
|
160
|
+
|
|
161
|
+
- Codex: `codex exec`, `codex review`.
|
|
162
|
+
- Claude Code: command runner or MCP-only guidance.
|
|
163
|
+
- Cursor: `cursor-agent` where available or MCP-only guidance.
|
|
164
|
+
|
|
165
|
+
REQ-BE-070: Runners must record run metadata and log.
|
|
166
|
+
|
|
167
|
+
REQ-BE-071: Runners must not hide approval, sandbox, or command failures.
|
|
168
|
+
|
|
169
|
+
## Verification
|
|
170
|
+
|
|
171
|
+
Backend must include:
|
|
172
|
+
|
|
173
|
+
- unit tests for state transitions;
|
|
174
|
+
- integration tests for atomic pick races;
|
|
175
|
+
- integration tests for heartbeat, progress, pause, resume, stale release, and approval-blocked closure;
|
|
176
|
+
- parser tests for valid and invalid plan files;
|
|
177
|
+
- MCP tool schema tests;
|
|
178
|
+
- import fixture tests for existing `.planr` layouts.
|