planning-control-plane 0.1.3__tar.gz

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 (48) hide show
  1. planning_control_plane-0.1.3/LICENSE +21 -0
  2. planning_control_plane-0.1.3/PKG-INFO +499 -0
  3. planning_control_plane-0.1.3/README.md +470 -0
  4. planning_control_plane-0.1.3/pyproject.toml +50 -0
  5. planning_control_plane-0.1.3/setup.cfg +4 -0
  6. planning_control_plane-0.1.3/src/planning_control_plane/__init__.py +40 -0
  7. planning_control_plane-0.1.3/src/planning_control_plane/cli.py +1261 -0
  8. planning_control_plane-0.1.3/src/planning_control_plane/context.py +501 -0
  9. planning_control_plane-0.1.3/src/planning_control_plane/generator.py +840 -0
  10. planning_control_plane-0.1.3/src/planning_control_plane/graph.py +226 -0
  11. planning_control_plane-0.1.3/src/planning_control_plane/i18n.py +540 -0
  12. planning_control_plane-0.1.3/src/planning_control_plane/loader.py +702 -0
  13. planning_control_plane-0.1.3/src/planning_control_plane/model.py +457 -0
  14. planning_control_plane-0.1.3/src/planning_control_plane/templates/base.html +132 -0
  15. planning_control_plane-0.1.3/src/planning_control_plane/templates/ideas.html +88 -0
  16. planning_control_plane-0.1.3/src/planning_control_plane/templates/index.html +221 -0
  17. planning_control_plane-0.1.3/src/planning_control_plane/templates/node.html +301 -0
  18. planning_control_plane-0.1.3/src/planning_control_plane/templates/static/app.js +438 -0
  19. planning_control_plane-0.1.3/src/planning_control_plane/templates/static/style.css +1902 -0
  20. planning_control_plane-0.1.3/src/planning_control_plane/validator.py +410 -0
  21. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/PKG-INFO +499 -0
  22. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/SOURCES.txt +46 -0
  23. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/dependency_links.txt +1 -0
  24. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/entry_points.txt +2 -0
  25. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/requires.txt +5 -0
  26. planning_control_plane-0.1.3/src/planning_control_plane.egg-info/top_level.txt +1 -0
  27. planning_control_plane-0.1.3/tests/test_agents.py +89 -0
  28. planning_control_plane-0.1.3/tests/test_cli.py +256 -0
  29. planning_control_plane-0.1.3/tests/test_context.py +284 -0
  30. planning_control_plane-0.1.3/tests/test_demo_zh.py +132 -0
  31. planning_control_plane-0.1.3/tests/test_dogfood_assets.py +40 -0
  32. planning_control_plane-0.1.3/tests/test_generator.py +164 -0
  33. planning_control_plane-0.1.3/tests/test_graduate.py +488 -0
  34. planning_control_plane-0.1.3/tests/test_graph.py +172 -0
  35. planning_control_plane-0.1.3/tests/test_html_smoke.py +346 -0
  36. planning_control_plane-0.1.3/tests/test_i18n.py +209 -0
  37. planning_control_plane-0.1.3/tests/test_idea_filename.py +92 -0
  38. planning_control_plane-0.1.3/tests/test_ideas.py +828 -0
  39. planning_control_plane-0.1.3/tests/test_ideas_next_id.py +172 -0
  40. planning_control_plane-0.1.3/tests/test_ideas_ui.py +526 -0
  41. planning_control_plane-0.1.3/tests/test_init.py +123 -0
  42. planning_control_plane-0.1.3/tests/test_lang_v012.py +374 -0
  43. planning_control_plane-0.1.3/tests/test_loader.py +246 -0
  44. planning_control_plane-0.1.3/tests/test_review_fixes.py +356 -0
  45. planning_control_plane-0.1.3/tests/test_skill_asset.py +62 -0
  46. planning_control_plane-0.1.3/tests/test_ui_v011.py +380 -0
  47. planning_control_plane-0.1.3/tests/test_validator_rules.py +198 -0
  48. planning_control_plane-0.1.3/tests/test_validator_structure.py +217 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PCP Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,499 @@
1
+ Metadata-Version: 2.4
2
+ Name: planning-control-plane
3
+ Version: 0.1.3
4
+ Summary: Repository-native planning context and progress control tool (pcp)
5
+ Author: PCP Contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/LuneHaven/planning-control-plane
8
+ Project-URL: Repository, https://github.com/LuneHaven/planning-control-plane
9
+ Project-URL: Changelog, https://github.com/LuneHaven/planning-control-plane/blob/main/CHANGELOG.md
10
+ Project-URL: Issues, https://github.com/LuneHaven/planning-control-plane/issues
11
+ Keywords: planning,roadmap,decision-tracking,context-management
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Natural Language :: English
17
+ Classifier: Natural Language :: Chinese (Simplified)
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: PyYAML>=6.0
25
+ Requires-Dist: Jinja2>=3.1
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # Planning Control Plane
31
+
32
+ English | [简体中文](README.zh-CN.md)
33
+
34
+ **Keep long-running planning context in your repository instead of in chat
35
+ transcripts.**
36
+
37
+ PCP is a command-line tool that stores the planning process of an
38
+ AI-assisted project (objectives, decisions, scope, progress) as YAML files
39
+ under `.planning/`, versioned with git; `pcp build` renders them into a
40
+ fully offline static dashboard.
41
+
42
+ ![Dashboard](docs/screenshots/dashboard-en.png)
43
+
44
+ ## Why PCP?
45
+
46
+ Discussing long-running plans in chat sessions usually runs into three
47
+ recurring problems:
48
+
49
+ - **Context loss**: a new session (or a new week) no longer knows the
50
+ parent constraints and the decisions that were already made.
51
+ - **Decision drift**: later discussions silently overturn frozen
52
+ decisions, because nobody re-reads message 40 of a 400-message thread.
53
+ - **Scope drift**: the discussion quietly grows past what this round was
54
+ supposed to decide.
55
+
56
+ A task tracker answers "who is doing what?"; PCP answers "where did the
57
+ discussion's context and boundaries go?" Task assignment stays in your
58
+ tracker; PCP only manages the planning process.
59
+
60
+ ## The Core Idea
61
+
62
+ 1. **Planning data is source; HTML is a projection.** The Planning Graph
63
+ lives in `.planning/` as plain YAML, committed with your repository.
64
+ `pcp build` renders it into a disposable static site you can delete and
65
+ regenerate at any time.
66
+ 2. **Decisions cascade down the tree.** Nodes form a planning tree
67
+ (`PROGRAM → PHASE → STRATEGY → …`). Every child node *inherits and
68
+ displays* the frozen decisions and scope boundaries made at its parent,
69
+ so they stay visible instead of being argued over again.
70
+ 3. **You can always pick up where you left off.** At any moment, exactly
71
+ one node is the current focus. `pcp context` emits a **Context
72
+ Capsule**: a compact, self-contained resume block you paste into a new
73
+ AI session (or send to a teammate) to continue working immediately.
74
+ 4. **Deterministic and offline.** Same planning source + same PCP version =
75
+ byte-identical output. The generated site references no CDN and no
76
+ remote fonts, and makes no network requests at all; it works when opened
77
+ directly via `file://`.
78
+
79
+ ## Features
80
+
81
+ - **Planning Graph**: nodes with parent / dependency / blocking / related
82
+ / supersedes edges, validated as a graph (cycle detection included)
83
+ - **Current Focus**: the single node the next session should work on,
84
+ highlighted in the dashboard and the tree
85
+ - **Frozen / Open / Blocking / Deferred Decisions**: categorized,
86
+ inherited down the tree, never silently lost
87
+ - **Scope Boundary**: explicit *in scope / out of scope* lists per node;
88
+ entries declared by ancestors are inherited and displayed, showing where
89
+ the boundary lies
90
+ - **Three independent tracks**: discussion, writeback and implementation
91
+ status are stored separately and never derived from each other
92
+ - **Context Capsule**: `pcp context <node>` prints a paste-ready resume
93
+ capsule; the node page has a one-click Copy Context button
94
+ - **Static dashboard**: deterministic, offline, dark-mode-capable HTML
95
+ with progressive disclosure
96
+ - **Bilingual UI**: English and 简体中文, switchable at runtime in the
97
+ browser
98
+ - **Authority boundary**: PCP owns planning only; your canonical documents
99
+ stay yours, linked but never replaced
100
+ - **Idea layer**: `.planning/ideas/` captures thinking that is not yet
101
+ committed; `pcp ideas` lists and filters it, and a malformed idea file
102
+ degrades to a single validation issue that never blocks the plan
103
+
104
+ ## Installation
105
+
106
+ PCP is not yet on PyPI; install from source (Python 3.11+). System Python
107
+ installs on many distributions are externally managed (PEP 668), so use a
108
+ virtual environment:
109
+
110
+ ```bash
111
+ git clone https://github.com/LuneHaven/planning-control-plane.git # or download and extract the source
112
+ cd planning-control-plane
113
+ python3 -m venv .venv
114
+ source .venv/bin/activate # Windows PowerShell: .venv\Scripts\activate
115
+ pip install -e .
116
+ pcp --help
117
+ ```
118
+
119
+ Runtime dependencies are just PyYAML and Jinja2.
120
+
121
+ ## Quick Start
122
+
123
+ In your own repository:
124
+
125
+ ```bash
126
+ cd my-project
127
+
128
+ pcp init # creates .planning/{project.yaml, roadmap.yaml, nodes/, .gitignore}
129
+ ```
130
+
131
+ Create your first planning node, `.planning/nodes/N1.yaml`:
132
+
133
+ ```yaml
134
+ id: N1
135
+ title: Choose the deployment approach
136
+ type: DISCUSSION
137
+ status: DISCUSSING
138
+
139
+ objective: >
140
+ Decide how this service gets deployed, given the constraints we froze
141
+ at the program level.
142
+
143
+ scope:
144
+ - Deployment tooling
145
+ - Environment topology
146
+ out_of_scope:
147
+ - Application refactoring
148
+ - Team staffing
149
+
150
+ next_action: >
151
+ Compare the two candidate toolchains against the readiness criteria.
152
+
153
+ discussion_status: IN_PROGRESS
154
+ writeback_status: N/A
155
+ implementation_status: N/A
156
+ last_updated: 2026-08-18
157
+ ```
158
+
159
+ Then:
160
+
161
+ ```bash
162
+ pcp focus N1 # set the current focus (written to project.yaml)
163
+ pcp validate # structural + consistency checks
164
+ pcp build # generate .planning/dist/
165
+ ```
166
+
167
+ Open `.planning/dist/index.html` in a browser (double-clicking works; the
168
+ site is fully offline). Continue in the terminal with:
169
+
170
+ ```bash
171
+ pcp status # overview: focus, blockers, progress counts
172
+ pcp context # the resume capsule for the current focus
173
+ ```
174
+
175
+ To explore a ready-made example instead, see
176
+ [`examples/demo-project`](examples/demo-project): a fictional demo
177
+ repository whose seven-node planning tree is ready to `pcp build`
178
+ immediately. Its counterpart
179
+ [`examples/demo-project-zh`](examples/demo-project-zh) is the same kind of
180
+ scenario written in Chinese; the two are independent planning data sets, not
181
+ translations of each other (see [Localization](#localization)).
182
+
183
+ ## CLI
184
+
185
+ | Command | What it does |
186
+ | --- | --- |
187
+ | `pcp init` | Create the `.planning/` skeleton; never overwrites existing files (`--force` only fills in missing files) |
188
+ | `pcp agents` | Print a paste-ready AGENTS.md section teaching AI harnesses this repository's PCP workflow. Read-only; append it with `pcp agents >> AGENTS.md` |
189
+ | `pcp validate` | Structural + planning-consistency validation, one issue per line (`ERROR`/`WARNING` + node + rule + reason) |
190
+ | `pcp build` | Validate, then deterministically rebuild the HTML output directory |
191
+ | `pcp build --check` | Regenerate in a temp directory and compare, to detect stale output (for CI) |
192
+ | `pcp status` | Terminal overview: project, current focus, decision counts, progress counts |
193
+ | `pcp context [node] [--full]` | Print the session resume capsule (default: the current focus) |
194
+ | `pcp focus [node]` | Show or switch the current focus (line-oriented edit of `project.yaml`; comments preserved) |
195
+ | `pcp ideas [--status S] [--for NODE [--subtree]]` | List the idea layer, grouped by status. `--for` selects ideas related to a node or its ancestors; `--subtree` switches to the node's subtree. Under `--for` without `--status`, only OPEN and PARKED are listed. The last line prints the next free idea id |
196
+ | `pcp graduate IDEA --to NODE [--note TEXT]` | Graduate an idea: write `status: PROMOTED` + `outcome` into the idea file and copy its ref-carrying justification entries into the node's `evidence_sources` (comments preserved; the node must already exist; both files roll back on failure) |
197
+
198
+ Global option `-p/--project-root PATH` sets the target repository root
199
+ (other commands search upward for `.planning/`).
200
+
201
+ Exit codes: `0` success · `1` business failure (validation errors, unknown
202
+ node, stale output) · `2` usage/load error.
203
+
204
+ ## AI Harness Integration
205
+
206
+ Two assets tell an AI coding harness when to use `pcp`:
207
+
208
+ 1. **AGENTS.md section**: `pcp agents >> AGENTS.md`, once per repository. It
209
+ records two kinds of content: the repository's own rules (document
210
+ naming, the registration convention) and the session workflow.
211
+ AGENTS.md is the open standard most harnesses read natively (Codex,
212
+ Cursor, Gemini CLI, ZCode, …). Claude Code is the exception: it reads
213
+ `CLAUDE.md` only, so bridge it with a `CLAUDE.md` whose sole content
214
+ is `@AGENTS.md`.
215
+ 2. **Skill**: [`integrations/skills/pcp/SKILL.md`](integrations/skills/pcp/SKILL.md)
216
+ is the manual for the tool itself. One copy, several install locations:
217
+
218
+ ```bash
219
+ # user level, shared across harnesses (ZCode scans ~/.agents/skills/)
220
+ mkdir -p ~/.agents/skills/pcp
221
+ curl -fsSL https://raw.githubusercontent.com/LuneHaven/planning-control-plane/main/integrations/skills/pcp/SKILL.md \
222
+ -o ~/.agents/skills/pcp/SKILL.md
223
+ ```
224
+
225
+ Claude Code does not scan `~/.agents/`; give it its own copy under
226
+ `~/.claude/skills/pcp/`. To share the skill with a team instead, commit it
227
+ into the repository at `.agents/skills/pcp/SKILL.md`.
228
+
229
+ The skill ships with the repository, not with the Python package: it is a
230
+ harness asset, not part of the PCP runtime; runtime adapters and plugins
231
+ remain out of scope (see Roadmap).
232
+
233
+ This division removes the duplication: repository rules are written only in
234
+ `AGENTS.md` and the command manual only in `SKILL.md`, so there is nothing
235
+ to keep in sync.
236
+
237
+ ## Idea Layer
238
+
239
+ Planning nodes are a *post-decision* control system: a node exists because
240
+ something was already committed to. The idea layer carries what comes
241
+ before that: captured thinking that does not yet qualify for the plan.
242
+
243
+ ```
244
+ .planning/ideas/IDEA-0007.yaml # one file per idea (directly under ideas/, .yaml suffix)
245
+ ```
246
+
247
+ ```yaml
248
+ id: IDEA-0007
249
+ title: Add a trend comparison view to the dashboard
250
+ status: OPEN # OPEN | PARKED | PROMOTED | DISCARDED
251
+ detail: One paragraph. Capture asks for no structure.
252
+ relates_to: [P2] # planning nodes this idea touches
253
+ benchmark_sources: # what mature products actually do
254
+ - ref: docs/benchmarks/grafana-panels.md
255
+ note: Grafana's time-compare panel shows the demand is stable
256
+ - note: Stripe's month-over-month dashboard # outside the repo: note only
257
+ methodology_sources: # why it holds, decoupled from any product
258
+ - ref: docs/method/heuristics.md
259
+ outcome: ~ # set when the idea graduates into a node
260
+ created: 2026-08-27
261
+ last_updated: 2026-08-27
262
+ ```
263
+
264
+ Four properties are deliberate:
265
+
266
+ - **Capture has no gate.** Empty `benchmark_sources` /
267
+ `methodology_sources` are a valid state, and produce no WARNING.
268
+ - **A single entry point.** An idea enters the planning graph only by
269
+ graduating: create the node, then point the idea's `outcome.node` at that
270
+ node, by hand or with `pcp graduate IDEA-0007 --to P2-A5`, which also
271
+ copies the idea's ref-carrying justification entries into the node's
272
+ `evidence_sources`. Nodes never reference ideas back, so reading the
273
+ plan never involves unfinished thinking.
274
+ - **Ideas cannot break the plan.** A malformed idea file becomes a
275
+ validation issue and is skipped; `pcp status`, `pcp context` and
276
+ `pcp build` keep working, and idea-layer errors never block a build.
277
+ - **Ideas are never in a capsule.** `pcp context` carries planning data
278
+ only; `pcp ideas --for <node>` is the separate, deliberate second lookup.
279
+
280
+ The generated site gets an `ideas.html` page and a sidebar entry, but only
281
+ when the project actually has ideas.
282
+
283
+ One rule runs through the idea layer: the `id` is the identity, the file
284
+ name is only an index. Two consequences follow. When a file name does not
285
+ match its `id`, `pcp validate` reports the `idea-filename-mismatch`
286
+ WARNING (advisory, never blocking); rename the file to fix it. And the last
287
+ line of `pcp ideas` prints the next free `IDEA-<NNNN>`, computed from both
288
+ loaded ids and the file names on disk, so it never points at a file that
289
+ already exists.
290
+
291
+ ## Planning Model
292
+
293
+ - **Node types** (controlled enum): `PROGRAM`, `PHASE`, `STRATEGY`,
294
+ `DISCUSSION`, `DECISION`, `INVESTIGATION`, `IMPLEMENTATION`, `CLOSURE`.
295
+ - **Node status** (planning lifecycle, not a kanban): `NOT_STARTED`,
296
+ `DISCUSSING`, `INVESTIGATING`, `DECIDED`, `WRITEBACK_PENDING`,
297
+ `WRITEBACK_DONE`, `READY`, `IMPLEMENTING`, `BLOCKED`, `DONE`, `DEFERRED`.
298
+ - **Three independent tracks** per node: `discussion_status`,
299
+ `writeback_status`, `implementation_status` ∈ `NOT_STARTED`,
300
+ `IN_PROGRESS`, `DONE`, `N/A`. A pure discussion node can be
301
+ Discussion `DONE` + Writeback `DONE` + Implementation `N/A`.
302
+ - **Decisions** come in four lists per node:
303
+ - *Frozen*: settled; children inherit them and must not silently overturn them
304
+ - *Open*: identified, not yet settled
305
+ - *Blocking*: unresolved and preventing closure (`DONE` + blocking → validation ERROR)
306
+ - *Deferred*: deliberately postponed
307
+ - **Scope Boundary**: `scope` / `out_of_scope` lists per node; entries
308
+ declared by ancestors are inherited and displayed, showing where the
309
+ boundary lies.
310
+
311
+ ## `.planning/` Structure
312
+
313
+ ```
314
+ .planning/
315
+ ├── project.yaml # project id/name, current_focus, authority roots, ui.locale
316
+ ├── roadmap.yaml # optional inline nodes list
317
+ ├── nodes/ # one YAML file per planning node
318
+ └── dist/ # generated site (gitignored, disposable)
319
+ ```
320
+
321
+ ## Example Node
322
+
323
+ From `examples/demo-project/.planning/nodes/P2-A4.yaml`:
324
+
325
+ ```yaml
326
+ id: P2-A4
327
+ title: Rollout Readiness Preflight
328
+ type: DISCUSSION
329
+ parent: P2-A
330
+ status: NOT_STARTED
331
+ objective: >
332
+ Run the readiness preflight for the first wave ...
333
+ scope:
334
+ - First-wave readiness verification
335
+ - Blocking-issue escalation
336
+ out_of_scope:
337
+ - Changing the readiness criteria (frozen at P2-A2)
338
+ open_decisions:
339
+ - id: OD-401
340
+ summary: How much readiness evidence is enough to declare the first wave ready?
341
+ blocking_decisions:
342
+ - id: BD-401
343
+ summary: Must a blocking gate owner sign off before rollout execution starts?
344
+ depends_on: [P2-A3]
345
+ canonical_sources:
346
+ - docs/rollout/readiness-criteria.md
347
+ evidence_sources:
348
+ - docs/notes/2026-08-15-sequencing-review.md
349
+ next_action: >
350
+ Resolve BD-401 with the gate owners, then walk the criteria checklist.
351
+ discussion_status: NOT_STARTED
352
+ writeback_status: N/A
353
+ implementation_status: N/A
354
+ last_updated: 2026-08-17
355
+ ```
356
+
357
+ ## Dashboard & Progressive Disclosure
358
+
359
+ ![Node detail](docs/screenshots/node-en.png)
360
+
361
+ - The **sidebar** carries the full planning tree, including status, focus
362
+ marker and expand/collapse.
363
+ - The **dashboard** answers four questions only: where are we (Current
364
+ Focus), is anything blocked (Needs Attention), what is around the focus
365
+ (Focus Branch), and what can start next (Ready Queue).
366
+ - The **node page** is ordered by control-plane priority: sticky header
367
+ (id, status, three tracks, Copy Context) → Next Action → Objective →
368
+ Scope Boundary → decisions (Blocking → Open → Frozen, inherited groups
369
+ collapsed per ancestor) → relations → sources → Resume This Work.
370
+ - Details that would obscure the essentials start collapsed (inherited
371
+ frozen decisions, deferred decisions, the full capsule) with counts
372
+ always visible.
373
+
374
+ ## Context Recovery
375
+
376
+ The **Context Capsule** hands the current state of the planning graph to
377
+ your next working session:
378
+
379
+ ```bash
380
+ pcp context # compact capsule for the current focus
381
+ pcp context P2-A4 # any node
382
+ pcp context --full # adds ancestor summaries, relations, deferred decisions
383
+ ```
384
+
385
+ Paste the capsule into a new AI session as the opening context. It carries
386
+ only what a new session needs: the node's objective, inherited frozen
387
+ decisions, scope boundaries, open and blocking decisions, sources and
388
+ track status, and nothing else. The node page's **Resume This Work**
389
+ panel shows the same capsule with a copy button.
390
+
391
+ ## Recommended AI Agent Workflow
392
+
393
+ ```
394
+ 1. pcp build → open the dashboard, read Current Focus
395
+ 2. pcp context → paste the capsule into a new agent session
396
+ 3. Discuss only that branch; record outcomes as decisions in the node YAML
397
+ 4. Write conclusions that belong in specs back into the canonical docs;
398
+ keep only links in the node
399
+ 5. Update status / tracks / next_action / last_updated
400
+ 6. pcp validate → fix ERRORs
401
+ 7. pcp build (CI: pcp build --check)
402
+ 8. pcp focus <next-node> → repeat
403
+ ```
404
+
405
+ Every artifact of the loop is on disk, so it can be interrupted anywhere
406
+ and resumed later.
407
+
408
+ ## Localization
409
+
410
+ The UI ships in English and 简体中文.
411
+
412
+ - **Project default**: `ui.locale` in `.planning/project.yaml`:
413
+
414
+ ```yaml
415
+ ui:
416
+ locale: zh-CN # or en (default)
417
+ ```
418
+
419
+ - **Runtime switch**: the top bar has a `English / 中文` toggle. Switching
420
+ happens instantly in the browser: no rebuild, no refresh, no network. The
421
+ preference is stored in `localStorage` and survives navigation and
422
+ reloads; clearing it falls back to the project default. `project.yaml`
423
+ is never modified.
424
+ - **Language never touches data**: node ids, decision ids, stored enum
425
+ values, user-written titles/summaries and the `pcp context` capsule stay
426
+ exactly as written in any locale. Detailed status views show
427
+ `localized label + RAW_ENUM` (e.g. `未开始 NOT_STARTED`), so machine-facing
428
+ values remain searchable.
429
+
430
+ > The language switch localizes PCP's interface.
431
+ > It does not translate your project planning content.
432
+ > Planning data remains exactly as authored.
433
+
434
+ That boundary is why this repository ships two demo projects rather than one:
435
+ [`examples/demo-project`](examples/demo-project) holds English planning data
436
+ and [`examples/demo-project-zh`](examples/demo-project-zh) holds Chinese
437
+ planning data. The Chinese screenshots in
438
+ [README.zh-CN.md](README.zh-CN.md) come from the Chinese demo, not from the
439
+ English demo viewed through a Chinese UI.
440
+
441
+ ## Architecture
442
+
443
+ | Layer | Location | Owner |
444
+ | --- | --- | --- |
445
+ | PCP engine | `src/planning_control_plane/` (this repository) | standalone pip-installed tool |
446
+ | Planning data | `<your-repo>/.planning/{project.yaml, roadmap.yaml, nodes/}` | your repository |
447
+ | Generated HTML | `<your-repo>/.planning/dist/` | your repository (disposable) |
448
+
449
+ Modules: `model.py` (enums + data model) · `loader.py` (tolerant YAML
450
+ loading) · `graph.py` (tree/graph operations) · `validator.py` (rules) ·
451
+ `context.py` (capsule) · `i18n.py` (UI translations, the single source
452
+ embedded into each page) · `generator.py` + `templates/` (deterministic
453
+ HTML) · `cli.py`.
454
+
455
+ ## Authority Boundary
456
+
457
+ PCP is authoritative **only** for planning structure and planning progress.
458
+ Normative product, governance, architecture and implementation semantics
459
+ remain owned by your project's own documents; PCP links to them
460
+ (`canonical_sources` / `evidence_sources`) and never copies or judges them.
461
+ Every generated page states this in its footer.
462
+
463
+ ## Current Status
464
+
465
+ **Current release: V0.1.3** is a usable MVP validated through real-project
466
+ self-use: the engine, CLI, validator, capsule and bilingual UI all work, and
467
+ the automated test suite has 409 tests. PCP is **not yet published on PyPI**;
468
+ install from source as shown above.
469
+
470
+ ## Roadmap
471
+
472
+ Deliberately **not** in scope: multi-user collaboration, server/cloud sync,
473
+ database, GitHub/PR integration, AI plugins, automatic summarization or
474
+ decision-making, semantic search, Jira/Notion replacement.
475
+
476
+ Named extension points reserved for later versions (no interfaces yet):
477
+ `pcp prompt`, `pcp close`, `pcp reopen`, Git/GitHub adapters, Claude Code /
478
+ Codex / ChatGPT adapters, multi-project workspace.
479
+
480
+ V0.2 candidates (none of them is implemented, and none is a promise):
481
+
482
+ - close / reopen workflow
483
+ - prompt generation
484
+ - integration status
485
+ - search / filter
486
+ - multi-project workspace
487
+
488
+ ## Contributing
489
+
490
+ Issues and pull requests are welcome. For development:
491
+
492
+ ```bash
493
+ pip install -e ".[dev]"
494
+ python -m pytest
495
+ ```
496
+
497
+ ## License
498
+
499
+ [MIT](LICENSE)