project-guide 2.2.3__tar.gz → 2.3.5__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 (151) hide show
  1. {project_guide-2.2.3 → project_guide-2.3.5}/.project-guide.yml +2 -2
  2. {project_guide-2.2.3 → project_guide-2.3.5}/CHANGELOG.md +159 -0
  3. {project_guide-2.2.3 → project_guide-2.3.5}/PKG-INFO +5 -5
  4. {project_guide-2.2.3 → project_guide-2.3.5}/README.md +4 -4
  5. {project_guide-2.2.3/project_guide/templates → project_guide-2.3.5/docs}/project-guide/.metadata.yml +7 -0
  6. project_guide-2.3.5/docs/project-guide/go.md +184 -0
  7. project_guide-2.3.5/docs/project-guide/templates/artifacts/project-essentials.md +43 -0
  8. {project_guide-2.2.3/project_guide/templates → project_guide-2.3.5/docs}/project-guide/templates/modes/_header-common.md +6 -0
  9. project_guide-2.3.5/docs/project-guide/templates/modes/plan-phase-mode.md +75 -0
  10. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/plan-tech-spec-mode.md +18 -0
  11. project_guide-2.3.5/docs/project-guide/templates/modes/refactor-plan-mode.md +123 -0
  12. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/modes.md +9 -2
  13. project_guide-2.3.5/docs/specs/project-essentials.md +40 -0
  14. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/stories.md +102 -90
  15. project_guide-2.3.5/project_guide/render.py +194 -0
  16. {project_guide-2.2.3/docs → project_guide-2.3.5/project_guide/templates}/project-guide/.metadata.yml +7 -0
  17. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/artifacts/concept.md +1 -1
  18. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/artifacts/features.md +1 -1
  19. project_guide-2.3.5/project_guide/templates/project-guide/templates/artifacts/project-essentials.md +43 -0
  20. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/artifacts/stories.md +1 -1
  21. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/artifacts/tech-spec.md +1 -1
  22. {project_guide-2.2.3/docs → project_guide-2.3.5/project_guide/templates}/project-guide/templates/modes/_header-common.md +6 -0
  23. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/default-mode.md +8 -2
  24. project_guide-2.3.5/project_guide/templates/project-guide/templates/modes/plan-phase-mode.md +75 -0
  25. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/plan-tech-spec-mode.md +18 -0
  26. project_guide-2.3.5/project_guide/templates/project-guide/templates/modes/refactor-plan-mode.md +123 -0
  27. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/version.py +1 -1
  28. {project_guide-2.2.3 → project_guide-2.3.5}/pyproject.toml +1 -1
  29. project_guide-2.3.5/tests/test_render.py +790 -0
  30. project_guide-2.2.3/docs/project-guide/go.md +0 -99
  31. project_guide-2.2.3/docs/project-guide/templates/modes/plan-phase-mode.md +0 -55
  32. project_guide-2.2.3/docs/project-guide/templates/modes/refactor-plan-mode.md +0 -81
  33. project_guide-2.2.3/project_guide/render.py +0 -99
  34. project_guide-2.2.3/project_guide/templates/project-guide/templates/modes/plan-phase-mode.md +0 -55
  35. project_guide-2.2.3/project_guide/templates/project-guide/templates/modes/refactor-plan-mode.md +0 -81
  36. project_guide-2.2.3/tests/test_render.py +0 -217
  37. {project_guide-2.2.3 → project_guide-2.3.5}/.github/FUNDING.yml +0 -0
  38. {project_guide-2.2.3 → project_guide-2.3.5}/.github/dependabot.yml +0 -0
  39. {project_guide-2.2.3 → project_guide-2.3.5}/.github/workflows/ci.yml +0 -0
  40. {project_guide-2.2.3 → project_guide-2.3.5}/.github/workflows/deploy-docs.yml +0 -0
  41. {project_guide-2.2.3 → project_guide-2.3.5}/.github/workflows/publish.yml +0 -0
  42. {project_guide-2.2.3 → project_guide-2.3.5}/.github/workflows/test.yml +0 -0
  43. {project_guide-2.2.3 → project_guide-2.3.5}/.gitignore +0 -0
  44. {project_guide-2.2.3 → project_guide-2.3.5}/.pyve/config +0 -0
  45. {project_guide-2.2.3 → project_guide-2.3.5}/.tool-versions +0 -0
  46. {project_guide-2.2.3 → project_guide-2.3.5}/LICENSE +0 -0
  47. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/README.md +0 -0
  48. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/best-practices-guide.md +0 -0
  49. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/brand-descriptions-guide.md +0 -0
  50. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/codecov-setup-guide.md +0 -0
  51. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/debug-guide.md +0 -0
  52. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/landing-page-guide.md +0 -0
  53. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/production-github-guide.md +0 -0
  54. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/developer/project-guide.md +0 -0
  55. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/artifacts/brand-descriptions.md +0 -0
  56. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/artifacts/concept.md +0 -0
  57. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/artifacts/features.md +0 -0
  58. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/artifacts/stories.md +0 -0
  59. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/artifacts/tech-spec.md +0 -0
  60. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/llm_entry_point.md +0 -0
  61. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/_header-cycle.md +0 -0
  62. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/_header-sequence.md +0 -0
  63. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/_phase-letters.md +0 -0
  64. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/archive-stories-mode.md +0 -0
  65. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/code-test-first-mode.md +0 -0
  66. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/code-velocity-mode.md +0 -0
  67. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/debug-mode.md +0 -0
  68. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/default-mode.md +0 -0
  69. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/document-brand-mode.md +0 -0
  70. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/document-landing-mode.md +0 -0
  71. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/plan-concept-mode.md +0 -0
  72. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/plan-features-mode.md +0 -0
  73. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/plan-stories-mode.md +0 -0
  74. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/production-mode.md +0 -0
  75. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/project-scaffold-mode.md +0 -0
  76. {project_guide-2.2.3 → project_guide-2.3.5}/docs/project-guide/templates/modes/refactor-document-mode.md +0 -0
  77. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/.gitignore +0 -0
  78. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/about/changelog.md +0 -0
  79. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/about/license.md +0 -0
  80. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/developer-guide/contributing.md +0 -0
  81. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/developer-guide/development.md +0 -0
  82. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/developer-guide/testing.md +0 -0
  83. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/getting-started.md +0 -0
  84. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/images/project-guide-banner-landing.png +0 -0
  85. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/images/project-guide-header-readme.png +0 -0
  86. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/index.html +0 -0
  87. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/commands.md +0 -0
  88. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/configuration.md +0 -0
  89. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/install-options.md +0 -0
  90. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/overrides.md +0 -0
  91. {project_guide-2.2.3 → project_guide-2.3.5}/docs/site/user-guide/workflow.md +0 -0
  92. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/.archive/phase-j-modes-plan.md +0 -0
  93. {project_guide-2.2.3/docs/specs → project_guide-2.3.5/docs/specs/.archive}/phase-k-release-lifecycle-plan.md +0 -0
  94. {project_guide-2.2.3/docs/specs → project_guide-2.3.5/docs/specs/.archive}/phase-l-no-input-init-plan.md +0 -0
  95. {project_guide-2.2.3/docs/specs → project_guide-2.3.5/docs/specs/.archive}/project-guide-no-input-spec.md +0 -0
  96. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/.archive/stories-v1.3.1.md +0 -0
  97. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/.archive/stories-v2.0.20.md +0 -0
  98. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/.archive/ux-problems-v2.0.10.md +0 -0
  99. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/concept.md +0 -0
  100. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/descriptions.md +0 -0
  101. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/features.md +0 -0
  102. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/phase-m-project-essentials-plan.md +0 -0
  103. {project_guide-2.2.3 → project_guide-2.3.5}/docs/specs/tech-spec.md +0 -0
  104. {project_guide-2.2.3 → project_guide-2.3.5}/mkdocs.yml +0 -0
  105. {project_guide-2.2.3 → project_guide-2.3.5}/project-guide-old-template.md +0 -0
  106. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/__init__.py +0 -0
  107. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/__main__.py +0 -0
  108. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/actions.py +0 -0
  109. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/cli.py +0 -0
  110. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/config.py +0 -0
  111. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/exceptions.py +0 -0
  112. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/metadata.py +0 -0
  113. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/runtime.py +0 -0
  114. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/sync.py +0 -0
  115. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/.project-guide.yml.template +0 -0
  116. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/README.md +0 -0
  117. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/best-practices-guide.md +0 -0
  118. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/brand-descriptions-guide.md +0 -0
  119. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/codecov-setup-guide.md +0 -0
  120. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/debug-guide.md +0 -0
  121. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/landing-page-guide.md +0 -0
  122. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/production-github-guide.md +0 -0
  123. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/developer/project-guide.md +0 -0
  124. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/artifacts/brand-descriptions.md +0 -0
  125. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/llm_entry_point.md +0 -0
  126. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/_header-cycle.md +0 -0
  127. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/_header-sequence.md +0 -0
  128. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/_phase-letters.md +0 -0
  129. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/archive-stories-mode.md +0 -0
  130. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/code-test-first-mode.md +0 -0
  131. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/code-velocity-mode.md +0 -0
  132. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/debug-mode.md +0 -0
  133. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/document-brand-mode.md +0 -0
  134. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/document-landing-mode.md +0 -0
  135. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/plan-concept-mode.md +0 -0
  136. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/plan-features-mode.md +0 -0
  137. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/plan-stories-mode.md +0 -0
  138. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/production-mode.md +0 -0
  139. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/project-scaffold-mode.md +0 -0
  140. {project_guide-2.2.3 → project_guide-2.3.5}/project_guide/templates/project-guide/templates/modes/refactor-document-mode.md +0 -0
  141. {project_guide-2.2.3 → project_guide-2.3.5}/requirements-dev.txt +0 -0
  142. {project_guide-2.2.3 → project_guide-2.3.5}/tests/__init__.py +0 -0
  143. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_actions.py +0 -0
  144. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_archive_stories_mode.py +0 -0
  145. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_cli.py +0 -0
  146. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_config.py +0 -0
  147. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_integration.py +0 -0
  148. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_metadata.py +0 -0
  149. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_purge.py +0 -0
  150. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_runtime.py +0 -0
  151. {project_guide-2.2.3 → project_guide-2.3.5}/tests/test_sync.py +0 -0
@@ -1,5 +1,5 @@
1
1
  version: '2.0'
2
- installed_version: 2.1.6
2
+ installed_version: 2.3.3
3
3
  target_dir: docs/project-guide
4
4
  metadata_file: .metadata.yml
5
- current_mode: code_velocity
5
+ current_mode: default
@@ -7,6 +7,165 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.5] - 2026-04-11
11
+
12
+ ### Added
13
+ - **Phase M documentation pass** (Story M.f) — the `project-essentials.md` artifact that landed in v2.3.0 and the three planning-mode wirings that landed in v2.3.2 / v2.3.3 / v2.3.4 are now reflected across all user-facing documentation and cross-referenced from the other artifact templates:
14
+ - **`project_guide/templates/project-guide/templates/artifacts/concept.md`** — the existing "see also" sentence in the header gains a fourth cross-reference to `project-essentials.md` with a one-line description of what belongs there ("workflow rules, hidden coupling, tool-wrapper conventions that the LLM would otherwise random-walk on").
15
+ - **`project_guide/templates/project-guide/templates/artifacts/features.md`** — same cross-reference added to the "see also" sentence.
16
+ - **`project_guide/templates/project-guide/templates/artifacts/tech-spec.md`** — same cross-reference, with an additional one-line note that `plan_tech_spec` populates it after the tech-spec is approved (so the developer knows the capture flow is automatic, not manual).
17
+ - **`project_guide/templates/project-guide/templates/artifacts/stories.md`** — same cross-reference, with a one-line note that `plan_phase` appends to it per phase.
18
+ - **`project_guide/templates/project-guide/templates/modes/default-mode.md`** — the "Planning (sequence)" table's `plan_tech_spec` and `plan_phase` rows now mention the `project-essentials.md` side-effect. A new **"Refactoring (cycle)"** section was added to the "All Available Modes" table (previously missing entirely — Refactoring modes were listed in the README but not in the bundled default-mode template). The new `refactor_plan` row explicitly mentions the terminal-step project-essentials refresh.
19
+ - **`README.md` — `### Planning Modes` table** — same `plan_tech_spec` and `plan_phase` updates as above.
20
+ - **`README.md` — `### Refactoring Modes` table** — `refactor_plan` row rewritten from the vague "Plan a refactor" to the specific "Update `concept`/`features`/`tech-spec` for new capabilities or legacy migration; terminal step refreshes `project-essentials.md` (creates it for legacy projects)".
21
+ - **`docs/site/user-guide/modes.md`** — full reference entries rewritten for `plan_tech_spec`, `plan_phase`, and `refactor_plan`:
22
+ - `plan_tech_spec` now lists two **Artifacts** (was one) and explains the post-approval capture flow with the "skip if none" escape hatch called out.
23
+ - `plan_phase` now lists three **Artifacts** (was two) and explains the terminal append step with the append-only-semantics rationale (`refactor_plan`'s Final Step is where you refactor essentials, not here).
24
+ - `refactor_plan` now lists a **Artifact** field (was none) and explains the terminal "Revisit Project Essentials" step with all five refactor-specific framing categories visible in the prose. Legacy projects are explicitly flagged as the highest-value capture moment.
25
+
26
+ ### Notes
27
+ - **Phase M is now complete** (`v2.3.0`–`v2.3.5`). Six stories shipped: M.a render hook + artifact template + dogfooding, M.b post-render placeholder validator, M.c `plan_tech_spec` create-wiring, M.d `refactor_plan` modify-wiring (terminal step), M.e `plan_phase` modify-wiring (append-only), and M.f (this documentation pass). The M.a render hook reads `<spec_artifacts_path>/project-essentials.md` at render time and injects its content under a `## Project Essentials` section in every rendered `go.md` via the `{% if project_essentials %}` guard in `_header-common.md`. The three planning modes populate, refresh, and append to the file at their respective lifecycle touchpoints. The M.b validator catches any future template edit that breaks the render pipeline (including removing the guard, typo-ing a context variable, or forgetting to update `render.py` when adding a new template variable).
28
+ - **Documentation-only release.** No code or test changes. All 248 tests continue to pass unchanged (`pyve test`). Ruff clean across `project_guide/` and `tests/`. mypy clean on all unchanged production modules.
29
+ - **Cross-reference scope**: only the four artifact templates that form the standard planning-doc chain (`concept.md`, `features.md`, `tech-spec.md`, `stories.md`) get the new cross-reference to `project-essentials.md`. `brand-descriptions.md` is a documentation artifact, not a planning doc, and was deliberately not touched — keeping that artifact's header focused on brand-specific cross-references.
30
+ - **Implicit verification via the M.c / M.d / M.e end-to-end tests**: the story's "verify by running each of the three updated planning modes against a fresh fixture" checklist item is covered by the existing `test_plan_tech_spec_mode_prompts_for_project_essentials`, `test_refactor_plan_mode_prompts_for_project_essentials_revisit`, and `test_plan_phase_mode_prompts_for_project_essentials_append` tests in `tests/test_render.py`. Each runs `init` + `mode <name>` against a fresh `CliRunner.isolated_filesystem()` and asserts the prompt content. Re-running these three tests as part of the full suite (248 passed) is the verification — no separate fixture test added.
31
+ - **What this phase leaves on the table for a future phase**: none. Phases K / L / M are all complete and ready for the next `archive_stories` run. When that happens, `stories.md` will be archived to `.archive/stories-v2.3.5.md` and a fresh empty `stories.md` will be re-rendered for the next phase.
32
+
33
+ ## [2.3.4] - 2026-04-11
34
+
35
+ ### Added
36
+ - **`plan_phase` mode appends to `project-essentials.md`** (Story M.e) — wires the third and final planning mode to the M.a render hook, completing the M.c/M.d/M.e lifecycle coverage. Where M.c populates on initial tech-spec creation and M.d revisits on refactor, M.e runs once per new phase plan and **appends** (rather than revisits or rewrites) new must-know facts to the file. The append-only semantics are a deliberate design constraint — `plan_phase` runs frequently over a project's lifetime and should not be the place to refactor or reorder existing project-essentials content; that's `refactor_plan`'s Final Step job.
37
+ - **New step 7 in `plan-phase-mode.md`** appended after Step 6 (stories approval), runs **once** at the end of phase planning (not per-story). Structure:
38
+ - **Create-if-absent branch**: if `docs/specs/project-essentials.md` doesn't exist (legacy project), the mode creates it from the artifact template first, following the same create path as `refactor_plan`'s Final Step. Legacy projects are explicitly flagged as the highest-value case.
39
+ - **Modify branch**: if the file exists, the mode reads it, keeps the current content in mind for the phase-specific prompt, and appends new `###` subsections under appropriate categories.
40
+ - **Phase-specific worked examples** with framing appropriate to "adding capability to an existing codebase": new architecture boundary (example cites Phase K's action-type registration pattern); new workflow rule or CLI contract (example cites Phase L's `--no-input` error-message contract that downstream tools pin); new hidden coupling between files (example cites Phase M's own `_header-common.md` guard + M.b validator); new deferred-but-documented item.
41
+ - **Principle anchor**: "if the phase introduced a new *invariant* or *convention* that someone working in this codebase a year from now would waste an hour rediscovering, it belongs in project-essentials." Straightforward feature additions with no new invariants should skip this step.
42
+ - **Skip-if-none escape hatch** is explicit — not every phase introduces new must-know facts.
43
+ - **Append-only semantics** are explicit: "append (do not rewrite or reorder)". Add new `###` subsections under the appropriate category (or create a new category if none fits). Do not edit existing content.
44
+ - **Heading convention reminder** (no top-level `#`; `###` for subsections) is present so the append nests correctly under the wrapper's `## Project Essentials`.
45
+ - **`plan_phase` metadata entry** now declares three `artifacts` (was two): `new-phase-{{phase_name}}.md` (no action — document artifact), `stories.md` (`action: modify`), and the new `project-essentials.md` (`action: modify`). The new wiring does not disturb the existing two declarations — the M.e story's test explicitly guards against that regression.
46
+
47
+ ### Changed
48
+ - **`{% raw %}...{% endraw %}` escape on the "hidden coupling" worked example** in `plan-phase-mode.md`. The example references `_header-common.md`'s `{% if project_essentials %}` guard literally inside a backtick code span — without the `{% raw %}` escape, Jinja2 parses the literal as an actual tag and the render fails with `Unexpected end of template`. This is the first time any bundled template has needed `{% raw %}` escaping, and it's a useful datapoint for the M.b validator's known-limitation note (templates that want to emit literal `{{ var }}` or `{% ... %}` strings need `{% raw %}`). Discovered during the first M.e test run; documented inline in the template.
49
+
50
+ ### Tests
51
+ - **2 new tests in `tests/test_render.py`** under the "Story M.e" heading:
52
+ - `test_plan_phase_mode_prompts_for_project_essentials_append` — end-to-end render. Asserts: append step present and runs once; append-only semantics explicit ("do not rewrite or reorder"); create-if-absent branch present with legacy-project framing; at least two phase-specific worked example categories (architecture boundary, workflow rule / CLI contract); skip-if-none escape hatch; artifact template reference; heading convention reminder.
53
+ - `test_plan_phase_metadata_declares_project_essentials_modify_artifact` — loads bundled metadata, asserts exactly one `project-essentials.md` artifact with `ActionType.MODIFY`. Also sanity-checks that the existing `new-phase-*.md` and `stories.md` declarations are still present, guarding against a clobber regression.
54
+ - **`test_every_mode_renders_successfully` parametrized test continues to pass unchanged** — and was specifically what caught the missing `{% raw %}` escape on the first run, since the `plan_phase` mode render failed until the escape was added.
55
+
56
+ ### Notes
57
+ - **Phase M wiring is now complete** (M.c/M.d/M.e). All three planning modes populate, refresh, or append to `project-essentials.md` at their respective lifecycle touchpoints:
58
+ - `plan_tech_spec` → `action: create` (initial population after tech-spec approval)
59
+ - `refactor_plan` → `action: modify` (terminal revisit, create-if-legacy, refresh-if-exists)
60
+ - `plan_phase` → `action: modify` (append-only, create-if-legacy)
61
+ - All three use concrete worked examples with lifecycle-specific framing (initial / refactor-driven / phase-driven). All three have end-to-end render tests and metadata wiring tests. All three follow the heading convention that lets the content nest under `_header-common.md`'s `## Project Essentials` wrapper.
62
+ - **What M.f (next and final Phase M story) adds**: a documentation pass — README / modes catalogue / CHANGELOG consolidation. No code changes; just closes out Phase M.
63
+ - Full test suite: **248 passed** (+2 new M.e tests). Ruff clean across `project_guide/` and `tests/`. mypy clean on the unchanged production modules (no code changes in this story).
64
+ - Verified end-to-end by running `pyve run project-guide update && pyve run project-guide mode plan_phase` in this repo. The rendered `go.md` contains the new step 7 at the expected position (after the stories-approval step 6) AND the M.a-injected `## Project Essentials` section at the top. The `{% if project_essentials %}` literal inside the worked example renders correctly (line 162 of the rendered output), confirming the `{% raw %}` escape works.
65
+
66
+ ## [2.3.3] - 2026-04-11
67
+
68
+ ### Added
69
+ - **`refactor_plan` mode refreshes `project-essentials.md`** (Story M.d) — wires the second of the three planning modes to the M.a render hook. When a refactor updates concept/features/tech-spec, the mode now runs a terminal "Revisit Project Essentials" sequence to capture any new must-know facts the refactor introduced. Distinct from M.c's `plan_tech_spec` (initial-lifecycle path) and M.e's upcoming `plan_phase` (per-phase append) in two ways: (1) it runs **once** per refactor session, not per-document, and (2) it handles both the **create** case (legacy project being migrated to v2.x, no file exists yet) and the **modify** case (project already has the file).
70
+ - **New "Final Step: Revisit Project Essentials" section** in `refactor-plan-mode.md`, appended after Step 8 (Cleanup). Structured as a 4-step sub-sequence to keep the decision path explicit:
71
+ - **Step F.1: Check for Existing File** — branches on whether `docs/specs/project-essentials.md` exists. The legacy-project branch is explicitly flagged as the highest-value case, because these projects typically have *never had their conventions written down* — their developers have internalized the rules and forgotten they're non-obvious.
72
+ - **Step F.2: Ask the Refactor-Revisit Prompt** — five concrete worked examples with *refactor-specific* framing (not M.c's initial-lifecycle framing): switched or added an environment manager (`pyve`/`uv`/`poetry`/`hatch`); split runtime from dev environment with the `pip install -e '.[dev]'` anti-pattern explicitly called out; renamed module or moved source-of-truth; changed domain conventions (money float → cents); new auto-generated or hidden-coupling files. Anchored by the **fork-in-the-road principle**: if the refactor introduced a decision where the *wrong* choice still "works" (runs, compiles, passes some tests), that is a project-essential. Each worked example includes a fully-rendered "*Example:*" sentence so the LLM can put concrete language in front of the developer, not abstract category names.
73
+ - **Step F.3: Generate or Update the File** — explicit create vs modify branching. Legacy projects get a fresh file from the artifact template; existing projects get an in-place update that preserves-updates-adds. Both paths re-iterate the heading convention (no top-level `#`; `###` for subsections).
74
+ - **Step F.4: Approval** — show the developer what was added, modified, and preserved, so the diff is legible.
75
+ - **"Skip if there are none" escape hatch** is part of Step F.2, explicitly framed for the pure-doc-restructure case where no tool/architecture/convention change occurred. A pure reformat is a legitimate refactor and should not be forced to produce project-essentials content.
76
+ - **`refactor_plan` metadata entry** now declares a single `artifacts` list (was previously empty) containing `project-essentials.md` with `action: modify`. The `modify` action type is the *conversational escape hatch* for the create-if-absent case: the deterministic action doesn't fire if the file doesn't exist, so the LLM's Step F.1 branching is what handles the create path in prose. The `action: modify` declaration is still correct at the metadata level because the *intent* is to end up with a modified (or newly-created) file.
77
+
78
+ ### Tests
79
+ - **2 new tests in `tests/test_render.py`** under the "Story M.d" heading:
80
+ - `test_refactor_plan_mode_prompts_for_project_essentials_revisit` — end-to-end render test. Fresh `init` → `mode refactor_plan` → read `go.md`. Asserts the terminal section is present and runs once (not per-document); the create/modify branches are both visible; the legacy-project framing is explicit; at least one concrete worked example with environment-manager naming is present; the artifact template path is referenced; the heading convention reminder is emitted; the "skip if none" escape hatch is present; and the fork-in-the-road / "wrong choice still works" principle is visible (refactor-framing anchor).
81
+ - `test_refactor_plan_metadata_declares_project_essentials_modify_artifact` — loads the bundled metadata, gets the `refactor_plan` mode, and asserts exactly one `project-essentials.md` artifact with `ActionType.MODIFY`. The "exactly one" check is deliberate — a duplicate declaration from a copy-paste mistake would be silently accepted by the schema but would break the conversational handoff.
82
+ - **`test_every_mode_renders_successfully` parametrized test continues to pass unchanged** — the new terminal section introduces no undefined-variable placeholders (validated by the M.b post-render validator) and the new metadata wiring does not break rendering for any of the 14 modes.
83
+
84
+ ### Notes
85
+ - **Design choice — terminal step vs cycle step**: the M.d story offered two options ("add a cycle step OR extend Step 1"). I chose a terminal step (new "Final Step: Revisit Project Essentials" section appended after Step 8). Rationale: `refactor_plan`'s main cycle processes three documents (concept, features, tech-spec) one at a time — asking about project-essentials once per document would be annoying and redundant, because most of the meaningful facts a refactor introduces are cross-document (a new tool wrapper affects how you run everything, not just how you build one artifact). Running the prompt once at the end gives the developer the full refactor context and produces a cleaner essentials file.
86
+ - **Terminology for metadata `action: modify`**: refactor_plan runs `action: modify` even though the file may not exist (legacy projects). This is the design pattern already established by `plan_phase`'s `stories.md` artifact in the bundled metadata — `modify` declares the intent ("end up with a modified file") and the mode template handles the create-if-absent case conversationally. The deterministic action handler in `actions.py` does NOT fire for `modify` actions — those go through the LLM. Only `archive` actions fire deterministically (via the `archive-stories` CLI command). So `modify` on a nonexistent file is not a runtime error; it's an instruction to the LLM.
87
+ - Full test suite: **246 passed** (+2 new M.d tests). Ruff clean across `project_guide/` and `tests/`. mypy clean on `project_guide/render.py`.
88
+ - Verified end-to-end by running `pyve run project-guide update && pyve run project-guide mode refactor_plan` in this repo. The rendered `go.md` contains all four sub-steps (F.1 through F.4) in the expected terminal position AND the M.a-injected `## Project Essentials` section at the top — proving the two layers compose correctly for this cycle-type mode as well.
89
+ - **M.e (next story)** will take the same pattern into `plan_phase` with an *append-only* variant: rather than revisit or refresh, the prompt asks what *new* facts the phase introduces and appends them. Also uses `action: modify`. After M.e ships, all three planning modes (M.c/M.d/M.e) will populate `project-essentials.md` at their respective lifecycle touchpoints.
90
+
91
+ ## [2.3.2] - 2026-04-11
92
+
93
+ ### Added
94
+ - **`plan_tech_spec` mode populates `project-essentials.md`** (Story M.c) — wires the first of the three planning modes to the M.a render hook. After the developer approves the tech-spec, the mode now asks whether any must-know facts should be captured for future LLMs working on the project, with concrete worked examples in the prompt (not just abstract category names). If the developer provides facts, the mode generates `docs/specs/project-essentials.md` from the artifact template; if not, the file is not created (an empty file is deliberately avoided on fresh projects — the "skip if none" escape hatch is explicit).
95
+ - **New step 5 in `plan_tech_spec` mode template** at `project_guide/templates/project-guide/templates/modes/plan-tech-spec-mode.md`: "After tech-spec approval, capture project essentials." The prompt lists five categories (workflow rules, architecture quirks, domain conventions, hidden coupling, dogfooding/meta notes) and provides concrete worked examples for each — in particular, the *tool wrapper random walk* anti-pattern (Python invocation, dev tool installation, test invocation) that the story's implementation strategy explicitly calls out as the highest-value category to capture.
96
+ - **New step 6 in the same mode**: generate `project-essentials.md` from the artifact template when the developer provides facts. The step explicitly reminds the LLM to follow the template's heading convention (no top-level `#`; `###` for subsections) so the content nests correctly under the `## Project Essentials` wrapper injected by `_header-common.md`.
97
+ - **`plan_tech_spec` metadata entry** now declares two `artifacts` (was one): `tech-spec.md` + `project-essentials.md`, both with `action: create`. The `create` action type is correct here because `plan_tech_spec` is the initial-lifecycle population path; `refactor_plan` (M.d) and `plan_phase` (M.e) will use `modify`/`modify` since those run against existing projects where the file may already exist.
98
+
99
+ ### Tests
100
+ - **2 new tests in `tests/test_render.py`** under the "Story M.c" heading:
101
+ - `test_plan_tech_spec_mode_prompts_for_project_essentials` — end-to-end render test. Fresh `init` → `mode plan_tech_spec` → read `go.md`. Asserts the capture step is present and ordered after tech-spec approval, at least one concrete worked example (`pyve run python` or `poetry run python`) is visible, two category names (`Workflow rules`, `Architecture quirks`) appear, the "skip if none" escape hatch is present, the artifact template path is referenced, and the heading convention reminder ("do NOT include a top-level", `###`) is emitted.
102
+ - `test_plan_tech_spec_metadata_declares_project_essentials_artifact` — loads the bundled `.metadata.yml`, gets the `plan_tech_spec` mode, and asserts both `tech-spec.md` and `project-essentials.md` are declared as artifacts with the `project-essentials.md` artifact using `ActionType.CREATE`. This is the wiring checkpoint that M.d/M.e will deliberately diverge from.
103
+ - **`test_every_mode_renders_successfully` parametrized test continues to pass unchanged** — the new prompt content and the new metadata entry do not introduce any undefined-variable placeholders (validated by the M.b post-render validator) and do not break rendering for any of the 14 modes.
104
+
105
+ ### Notes
106
+ - The `create` action type on the new artifact is an **intent declaration**, not an unconditional file-creation. The mode template's step 5 "skip to step 7 if there are no facts to capture" clause is the LLM-runtime escape hatch — a fresh project where the developer has nothing to put in `project-essentials.md` does NOT get an empty file. This is a deliberate design choice: empty files would trigger the render hook's "whitespace-only = omit section" branch (which is correct) but would leave a dormant empty file in `docs/specs/` that looks like an oversight. Better to not create it at all.
107
+ - Full test suite: **244 passed** (+2 new M.c tests). Ruff clean across `project_guide/` and `tests/`. mypy clean on `project_guide/render.py`.
108
+ - Verified end-to-end by running `pyve run project-guide update && pyve run project-guide mode plan_tech_spec` in this repo. The rendered `go.md` contains both the M.a-injected Project Essentials section at the top (fed by this project's own `docs/specs/project-essentials.md`) and the new M.c capture step at step 5 — proving the two layers compose correctly on a project that already has the file populated.
109
+ - **What M.d and M.e add next**: M.d (`refactor_plan`) adds the same prompt with a "refactor-driven changes" framing and handles the legacy-project case where `project-essentials.md` does not yet exist; declares `action: modify` so the mode can either create-if-absent or modify-if-present. M.e (`plan_phase`) adds an append-only variant that runs once per new phase plan; also declares `action: modify`. M.c/M.d/M.e are mutually independent (per the phase plan in `docs/specs/stories.md`) but the listed order matches the project lifecycle.
110
+
111
+ ## [2.3.1] - 2026-04-11
112
+
113
+ ### Added
114
+ - **Post-render placeholder validator** (Story M.b) — generalizes the M.a `{{ project_essentials }}` regression guard into a project-wide safeguard. After every `render_go_project_guide` call, the rendered output is scanned for any bare `{{ identifier }}` Jinja-style placeholder; if any are found, `RenderError` is raised with the offending names and a fix hint, and the output file is **not** written. This catches three distinct failure modes at the same place:
115
+ 1. **Missed intents** — a context variable that should have been set in `render.py` but wasn't.
116
+ 2. **Typos** — a template referencing `{{ project_essentialss }}` or any other misspelled variable name.
117
+ 3. **Removed guards** — a future edit that drops a `{% if %}` wrapper and lets an unset variable leak through.
118
+ - **`_UNRENDERED_PLACEHOLDER_RE` module-level regex** (`render.py`): `\{\{\s*([a-zA-Z_]\w*)\s*\}\}`. Matches exactly the shape that `_LenientUndefined.__str__` emits — `{{var}}`, `{{ var }}`, `{{ var }}`. Deliberately does **not** match attribute access (`{{ obj.attr }}`), filters (`{{ name|upper }}`), expressions (`{{ a + 1 }}`), or statement blocks (`{% ... %}`). Those shapes raise at Jinja render time and never reach the validator.
119
+ - **`_validate_no_unrendered_placeholders(rendered)` helper** (`render.py`): scans the rendered output, deduplicates offenders while preserving first-occurrence order, and raises `RenderError` with a message of the form `Unrendered placeholder(s) in rendered output: <names>. Hint: check (1) render.py context variables and (2) template variable spellings.`. The validator is called inside `render_go_project_guide` **after** `template.render()` and **before** `output_path.write_text()`, so a failing render leaves the filesystem untouched.
120
+
121
+ ### Changed
122
+ - **`_LenientUndefined` contract documented inversion**: the class itself is unchanged (still emits `{{ name }}` for undefined variables), but its *purpose* has inverted. Before M.b, the placeholder shape was the final output — a permissive pass-through so unset variables wouldn't crash renders. After M.b, the placeholder shape is the *detection signal* — lenient undefined produces the shape that the post-render validator catches and promotes to an error. The class stays lenient so the validator can see and report every offender in one pass, rather than Jinja crashing on the first undefined variable it encounters.
123
+ - **`test_render_undefined_vars_are_preserved` renamed to `test_render_undefined_vars_raise_render_error`** and inverted to assert the new behavior: undefined variables now raise `RenderError` with the offending name, and no output file is written.
124
+
125
+ ### Removed
126
+ - **Temporary M.a regression guard `test_project_essentials_never_renders_literal_placeholder`** — the general validator subsumes it. If the `{% if %}` guard on `_header-common.md` is ever removed, the M.b validator raises `RenderError` on every mode render that has no populated `project-essentials.md`, which is far louder than a single dedicated test. A comment in the test file marks the removal for future readers.
127
+
128
+ ### Tests
129
+ - **7 new tests in `tests/test_render.py`** under the "Story M.b" heading:
130
+ - `test_validator_raises_on_single_undefined_variable` — baseline: one typo'd variable → `RenderError` citing the name.
131
+ - `test_validator_error_message_lists_all_offenders` — three distinct offenders → error message names all three (no first-match short-circuit).
132
+ - `test_validator_deduplicates_repeated_offenders` — a name repeated 3× → appears exactly once in the message, in first-occurrence order.
133
+ - `test_validator_error_message_includes_fix_hint` — message contains both "render.py context variables" and "template variable spellings".
134
+ - `test_validator_does_not_write_output_on_failure` — the output file must not exist after a raise (pre/post `exists()` assertions).
135
+ - `test_validator_passes_when_all_vars_defined` — happy path: the standard `template_dir` fixture renders cleanly and the rendered file contains zero matching placeholders.
136
+ - `test_validator_passes_on_template_with_no_jinja_variables` — empty-match edge case: a minimal plain-text template renders without raising.
137
+ - **Existing `test_every_mode_renders_successfully` parametrized test continues to pass unchanged.** This is the critical cross-template audit: every bundled mode is rendered through a fresh `CliRunner.isolated_filesystem()` install and must now pass the validator. All 14 modes pass, confirming that no bundled template references an undefined variable. This replaces the manual "audit existing templates" step in the M.b story checklist with an empirical proof.
138
+
139
+ ### Notes
140
+ - **Audit result**: every bundled mode template's bare `{{ var }}` is backed by either a `render.py` context variable (`mode_name`, `mode_info`, `mode_description`, `sequence_or_cycle`, `next_mode`, `target_dir`, `project_essentials`) or a `metadata.common` entry (`test_invocation`, `spec_artifacts_path`, `web_root`). No mode template `{% include %}`s an artifact template, so artifact-template placeholders like `{{problem_statement}}` never enter the mode render path — they go through a separate `perform_archive` path in `actions.py` with its own `_LenientUndefined`, which is unchanged by this story.
141
+ - **Known limitation** (documented inline in `_UNRENDERED_PLACEHOLDER_RE`'s docstring): templates that legitimately want to emit a literal `{{ var }}` string (e.g., documentation of Jinja syntax inside a code fence) will trigger false positives. Not currently a problem in any bundled template; bridge if/when needed, likely via a `{% raw %}` escape.
142
+ - Full test suite: **242 passed** (+7 new M.b tests, −1 removed M.a guard, 1 renamed). Ruff clean across `project_guide/` and `tests/`. mypy clean on `project_guide/render.py`.
143
+ - Verified end-to-end by re-rendering `docs/project-guide/go.md` under `default` and `plan_concept` modes per the story checklist. Both produce zero unrendered placeholders (confirmed via grep of the output).
144
+
145
+ ## [2.3.0] - 2026-04-11
146
+
147
+ ### Added
148
+ - **`project-essentials.md` artifact and render hook** (Story M.a) — a new per-project artifact that captures must-know facts future LLMs need to avoid blunders (workflow rules, architecture quirks, domain conventions, hidden coupling, dogfooding notes). When present and non-empty, its content is injected verbatim under a `## Project Essentials` section in **every** rendered mode via `_header-common.md`, making the facts visible no matter which mode the developer is in. This story lays the rails; the `plan_tech_spec` / `refactor_plan` / `plan_phase` modes will be wired to populate it in stories M.c–M.e.
149
+ - **`project_guide/templates/project-guide/templates/artifacts/project-essentials.md`** — the new artifact template. Ships as a comment-block-only file documenting what belongs there (workflow rules with concrete examples, architecture quirks, domain conventions, hidden coupling, dogfooding notes) and explicitly noting that an empty file is acceptable. The template deliberately omits a top-level `#` heading — the wrapper in `_header-common.md` provides the `## Project Essentials` heading, and content uses `###` for subsections to nest cleanly.
150
+ - **`_read_project_essentials()` helper in `project_guide/render.py`** — reads `<spec_artifacts_path>/project-essentials.md` (resolved from `metadata.common["spec_artifacts_path"]`, typically `docs/specs`). Returns an empty string when the path is missing, the file does not exist, or the file is whitespace-only. `render_go_project_guide` now calls this helper and passes the result as the `project_essentials` Jinja2 context variable.
151
+ - **`{% if project_essentials %}` guard in `_header-common.md`** — renders the `## Project Essentials` section (with the file's content and a `---` separator) only when the variable is non-empty. Empty/missing files omit the section entirely, so projects that don't want to maintain this file render cleanly.
152
+ - **`docs/specs/project-essentials.md` for this project** (dogfooding) — populated with the current must-know facts: pyve two-environment workflow rules (`pyve run` / `pyve test` / `pyve testenv run`), the dogfooding rule (edit templates in `project_guide/templates/project-guide/`, never `docs/project-guide/`), v2 mode-driven architecture, the Phase K release-lifecycle pattern, the Phase L `--no-input` contract, and the commit/version style conventions.
153
+
154
+ ### Tests
155
+ - **6 new tests in `tests/test_render.py`** under the "Story M.a" heading, all using a new `essentials_template_dir` fixture that faithfully reproduces the `{% if %}` guard shape and a new `essentials_metadata` fixture with `spec_artifacts_path`:
156
+ - `test_project_essentials_rendered_when_file_non_empty` — populated file → section appears between the header and the mode body.
157
+ - `test_project_essentials_omitted_when_file_empty` — zero-length file → section omitted.
158
+ - `test_project_essentials_omitted_when_file_whitespace_only` — whitespace-only file → section omitted (treated as empty).
159
+ - `test_project_essentials_omitted_when_file_missing` — no file at all → section omitted, no error.
160
+ - `test_project_essentials_omitted_when_spec_artifacts_path_not_in_metadata` — minimal metadata without `spec_artifacts_path` → lookup is skipped, section omitted.
161
+ - `test_project_essentials_never_renders_literal_placeholder` — **temporary regression guard** (scheduled for removal by M.b once the general post-render placeholder validator lands). Exercises all four file shapes and asserts the literal string `{{ project_essentials }}` never appears in the output. Catches a future template edit that removes the `{% if %}` guard, since `_LenientUndefined.__str__` would otherwise render the placeholder verbatim. See `render.py:83-99` for the lenient-undefined contract.
162
+
163
+ ### Notes
164
+ - The M.a story deliberately does **not** add `project-essentials.md` to any mode's `.metadata.yml` `artifacts` list — that wiring is M.c–M.e's responsibility (population via `plan_tech_spec`, refresh via `refactor_plan`, append via `plan_phase`). M.a only establishes the render-time lookup, the guarded section, and the dogfooded content for this project.
165
+ - The existing `test_every_mode_renders_successfully` parametrized test continues to pass unchanged. It runs every bundled mode through an isolated filesystem where no `docs/specs/project-essentials.md` exists, so the section is omitted and the render produces valid output — this is the implicit cross-mode regression guard.
166
+ - Full test suite: **236 passed** (`pyve test`). Ruff clean across `project_guide/` and `tests/`. mypy clean on `project_guide/render.py`.
167
+ - Verified end-to-end by re-rendering `docs/project-guide/go.md` under both `default` and `code_velocity` modes; the `## Project Essentials` section appears between the `**Rules**` block and the mode heading, with the `###` subsection nesting rendering correctly.
168
+
10
169
  ## [2.2.3] - 2026-04-11
11
170
 
12
171
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: project-guide
3
- Version: 2.2.3
3
+ Version: 2.3.5
4
4
  Summary: Stay organized and in control with adaptive LLM workflow prompts.
5
5
  Project-URL: Homepage, https://github.com/pointmatic/project-guide
6
6
  Project-URL: Documentation, https://pointmatic.github.io/project-guide/
@@ -444,9 +444,9 @@ overrides:
444
444
  |------|---------|--------|
445
445
  | **Concept** | `project-guide mode plan_concept` | `docs/specs/concept.md` |
446
446
  | **Features** | `project-guide mode plan_features` | `docs/specs/features.md` |
447
- | **Tech Spec** | `project-guide mode plan_tech_spec` | `docs/specs/tech-spec.md` |
447
+ | **Tech Spec** | `project-guide mode plan_tech_spec` | `docs/specs/tech-spec.md` + `docs/specs/project-essentials.md` (initial population) |
448
448
  | **Stories** | `project-guide mode plan_stories` | `docs/specs/stories.md` |
449
- | **Phase** | `project-guide mode plan_phase` | New phase added to stories |
449
+ | **Phase** | `project-guide mode plan_phase` | New phase added to `stories.md` + append to `project-essentials.md` |
450
450
 
451
451
  ### Coding Modes
452
452
 
@@ -473,8 +473,8 @@ overrides:
473
473
 
474
474
  | Mode | Command | Workflow |
475
475
  |------|---------|----------|
476
- | **Plan** | `project-guide mode refactor_plan` | Plan a refactor |
477
- | **Document** | `project-guide mode refactor_document` | Document a refactor |
476
+ | **Plan** | `project-guide mode refactor_plan` | Update `concept`/`features`/`tech-spec` for new capabilities or legacy migration; terminal step refreshes `project-essentials.md` (creates it for legacy projects) |
477
+ | **Document** | `project-guide mode refactor_document` | Update README, brand descriptions, landing page, and MkDocs config |
478
478
 
479
479
  ## Troubleshooting
480
480
 
@@ -408,9 +408,9 @@ overrides:
408
408
  |------|---------|--------|
409
409
  | **Concept** | `project-guide mode plan_concept` | `docs/specs/concept.md` |
410
410
  | **Features** | `project-guide mode plan_features` | `docs/specs/features.md` |
411
- | **Tech Spec** | `project-guide mode plan_tech_spec` | `docs/specs/tech-spec.md` |
411
+ | **Tech Spec** | `project-guide mode plan_tech_spec` | `docs/specs/tech-spec.md` + `docs/specs/project-essentials.md` (initial population) |
412
412
  | **Stories** | `project-guide mode plan_stories` | `docs/specs/stories.md` |
413
- | **Phase** | `project-guide mode plan_phase` | New phase added to stories |
413
+ | **Phase** | `project-guide mode plan_phase` | New phase added to `stories.md` + append to `project-essentials.md` |
414
414
 
415
415
  ### Coding Modes
416
416
 
@@ -437,8 +437,8 @@ overrides:
437
437
 
438
438
  | Mode | Command | Workflow |
439
439
  |------|---------|----------|
440
- | **Plan** | `project-guide mode refactor_plan` | Plan a refactor |
441
- | **Document** | `project-guide mode refactor_document` | Document a refactor |
440
+ | **Plan** | `project-guide mode refactor_plan` | Update `concept`/`features`/`tech-spec` for new capabilities or legacy migration; terminal step refreshes `project-essentials.md` (creates it for legacy projects) |
441
+ | **Document** | `project-guide mode refactor_document` | Update README, brand descriptions, landing page, and MkDocs config |
442
442
 
443
443
  ## Troubleshooting
444
444
 
@@ -53,6 +53,8 @@ modes:
53
53
  artifacts:
54
54
  - file: "{{spec_artifacts_path}}/tech-spec.md"
55
55
  action: create
56
+ - file: "{{spec_artifacts_path}}/project-essentials.md"
57
+ action: create
56
58
  files_exist:
57
59
  - "{{spec_artifacts_path}}/concept.md"
58
60
  - "{{spec_artifacts_path}}/features.md"
@@ -95,6 +97,8 @@ modes:
95
97
  - file: "{{spec_artifacts_path}}/new-phase-{{phase_name}}.md"
96
98
  - file: "{{spec_artifacts_path}}/stories.md"
97
99
  action: modify
100
+ - file: "{{spec_artifacts_path}}/project-essentials.md"
101
+ action: modify
98
102
  files_exist:
99
103
  - "{{spec_artifacts_path}}/concept.md"
100
104
  - "{{spec_artifacts_path}}/features.md"
@@ -180,6 +184,9 @@ modes:
180
184
  sequence_or_cycle: cycle
181
185
  generation_type: document
182
186
  mode_template: "{{mode_templates_path}}/refactor-plan-mode.md"
187
+ artifacts:
188
+ - file: "{{spec_artifacts_path}}/project-essentials.md"
189
+ action: modify
183
190
  - name: refactor_document
184
191
  info: Update documentation artifacts (README, brand descriptions, landing page, MkDocs)
185
192
  description: Update existing documentation files because of new features or improvements, including README, brand descriptions, landing page, and MkDocs configuration. You can also migrate legacy project-guide documentation--it will preserve information while restructuring into standardized sections.
@@ -0,0 +1,184 @@
1
+ # Project-Guide — Calm the chaos of LLM-assisted coding
2
+
3
+ This document provides step-by-step instructions for an LLM to assist a human developer in a project.
4
+
5
+ ## How to Use Project-Guide
6
+
7
+ ### For Developers
8
+ After installing project-guide (`pip install project-guide`) and running `project-guide init`, instruct your LLM as follows in the chat interface:
9
+
10
+ ```
11
+ Read `docs/project-guide/go.md`
12
+ ```
13
+
14
+ After reading, the LLM will respond:
15
+ 1. (optional) "I need more information..." followed by a list of questions or details needed.
16
+ - LLM will continue asking until all needed information is clear.
17
+ 2. "The next step is ___."
18
+ 3. "Say 'go' when you're ready."
19
+
20
+ For efficiency, when you change modes, start a new LLM conversation.
21
+
22
+ ### For LLMs
23
+
24
+ **Modes**
25
+ This Project-Guide offers a human-in-the-loop workflow for you to follow that can be dynamically reconfigured based on the project `mode`. Each `mode` defines a focused sequence of steps to guide you (the LLM) to help generate artifacts for some facet in the project lifecycle. This document is customized for default.
26
+
27
+ **Approval Gate**
28
+ When you have completed the steps, pause for the developer to review, correct, redirect, or ask questions about your work.
29
+
30
+ **Rules**
31
+ - Work through each step methodically, presenting your work for approval before continuing a cycle.
32
+ - When the developer says "go" (or equivalent like "continue", "next", "proceed"), continue with the next action.
33
+ - If the next action is unclear, tell the developer you don't have a clear direction on what to do next, then suggest something.
34
+ - Never auto-advance past an approval gate—always wait for explicit confirmation.
35
+ - After compacting memory, re-read this guide to refresh your context.
36
+
37
+ ---
38
+
39
+ ## Project Essentials
40
+
41
+ Must-know facts for future LLMs working on the project-guide project. These are things a smart newcomer could easily miss and waste time on. This content gets injected verbatim under a `## Project Essentials` section in every rendered mode, so entries below use `###` for subsections.
42
+
43
+ ### Workflow rules — pyve environment conventions
44
+
45
+ This project uses `pyve` with **two separate environments**. Picking the wrong invocation form often "works" but leads to subtle drift. Use the canonical forms below:
46
+
47
+ - **Runtime code (the `project_guide` package itself):** `pyve run python ...` or `pyve run project-guide ...`.
48
+ - **Tests:** `pyve test [pytest args]` — **not** `pyve run pytest`. Pytest is not installed in the main `.venv/`; it lives in the dev testenv.
49
+ - **Dev tools (ruff, mypy, pytest):** `pyve testenv run ruff check ...`, `pyve testenv run mypy ...`. These use `.pyve/testenv/venv/`.
50
+ - **Install dev tools:** `pyve testenv --install -r requirements-dev.txt`. **Do not** run `pip install -e ".[dev]"` into the main venv — that pollutes the runtime environment with test-only dependencies and breaks the two-env isolation.
51
+
52
+ If `pytest` fails with "not found" that is the signal to use `pyve test`, not to `pip install pytest` into the wrong venv.
53
+
54
+ ### Dogfooding rule — template source of truth
55
+
56
+ This project uses itself (dogfooding). Template files live in **two places** that must not be confused:
57
+
58
+ - **Source of truth:** `project_guide/templates/project-guide/` — the bundled templates that ship inside the Python package. **Edit these.**
59
+ - **Installed copy:** `docs/project-guide/` — the rendered output from running `project-guide init` on this project. **Never hand-edit these.** They are regenerated by `project-guide mode` and `project-guide update`, and any hand-edits will be lost on the next sync.
60
+
61
+ In particular, `docs/project-guide/go.md` is dynamically re-rendered by the `project-guide mode` command every time the mode changes. Never hand-edit `go.md`. After editing a source template, run `project-guide update` (while working in an editable install, e.g. `pyve run pip install -e .`) to propagate changes into the installed copy before re-rendering.
62
+
63
+ ### Architecture quirks
64
+
65
+ - **v2 architecture is mode-driven Jinja2 templating,** not static file sync. The v1 "copy files to `docs/guides/`" pattern is deprecated; all new work targets `docs/project-guide/` via rendered templates.
66
+ - **Phase K release lifecycle:** `archive_stories` mode + the `archive-stories` CLI command form a two-part pattern — the mode template walks the developer through the decision conversationally; the CLI performs the deterministic file move + re-render. Keep this split when adding similar lifecycle commands.
67
+ - **Phase letters continue across archive boundaries.** When planning a new phase with `plan_phase` and `stories.md` is empty (post-archive), the `.archive/stories-vX.Y.Z.md` files must be read to determine the next letter. The rules are centralized in `project_guide/templates/project-guide/templates/modes/_phase-letters.md`.
68
+
69
+ ### `--no-input` contract (added v2.2.1)
70
+
71
+ Any future interactive prompt added to a CLI command **must** use the `should_skip_input()` helper from `project_guide/runtime.py` to decide whether to read from stdin, and must use `_require_setting()` to fail loudly when a required setting has no default under `--no-input`. The contract and the exact error message format are pinned by `tests/test_cli.py::test_require_setting_contract_exit_code_and_message` — do not change that message lightly, as downstream tooling (e.g., pyve) may cite it.
72
+
73
+ `init` currently has no prompts, but the plumbing (`skip_input = should_skip_input(no_input)` in `cli.py:init`) is already in place. The unused local is intentional — see the `# noqa: F841` comment.
74
+
75
+ ### Commit and version style
76
+
77
+ - **One version bump per story** (code stories only — doc-only stories share the version with the preceding code story or bump to a `.N` doc release).
78
+ - **Commit messages reference the story ID**: `"Story M.a: v2.3.0 project-essentials render hook"`.
79
+ - **Direct commits to main** in `code_velocity` mode — no branches, no PRs.
80
+ - **Bump version in three places** per story: `project_guide/version.py`, `pyproject.toml`, and `CHANGELOG.md` (new `## [X.Y.Z]` entry dated).
81
+
82
+
83
+ ---
84
+
85
+ # default mode (sequence)
86
+
87
+ > Getting started -- full project lifecycle overview
88
+
89
+
90
+ This is the default mode for new projects. It provides an overview of the full project lifecycle. For focused work, switch to a specific mode with `project-guide mode <name>`.
91
+
92
+ ---
93
+
94
+ ## Project Lifecycle
95
+
96
+ | Step | Mode | What it does |
97
+ |------|------|-------------|
98
+ | 1 | `plan_concept` | Define the problem and solution space |
99
+ | 2 | `plan_features` | Define requirements, inputs, outputs, behavior |
100
+ | 3 | `plan_tech_spec` | Define architecture, modules, dependencies |
101
+ | 4 | `plan_stories` | Break into phases and stories with checklists |
102
+ | 5 | `project_scaffold` | Scaffold LICENSE, headers, manifest, README, CHANGELOG, .gitignore |
103
+ | 6 | `code_velocity` | Implement stories with fast iteration |
104
+
105
+ ## Get Started
106
+
107
+ To begin a new project, run:
108
+
109
+ ```bash
110
+ project-guide mode plan_concept
111
+ ```
112
+
113
+ ## Suggesting the Next Step
114
+
115
+ When this mode is set, read `docs/specs/stories.md` (if it exists) and check the status of every `### Story X.y: ... [<status>]` heading.
116
+
117
+ ### If all stories are `[Done]`
118
+
119
+ The current phase is complete. There is no in-progress work to resume. Suggest **both** of the following next steps to the developer and explain the trade-off:
120
+
121
+ > All stories in `stories.md` are marked `[Done]`. The current phase is finished. Two reasonable next steps:
122
+ >
123
+ > **Option A — `archive_stories` first, then `plan_phase`** (clean slate)
124
+ > ```bash
125
+ > project-guide mode archive_stories
126
+ > ```
127
+ > This moves the current `stories.md` to `docs/specs/.archive/stories-vX.Y.Z.md` and re-renders an empty `stories.md` (preserving the `## Future` section). Then `plan_phase` plans against an empty file. Phase letters continue across the archive boundary (`.archive/` is consulted to determine the next letter).
128
+ >
129
+ > *Use this when:* the completed phase is large enough that scrolling past it during planning is friction, or you want each phase as a self-contained file in `.archive/` for git history clarity.
130
+ >
131
+ > **Option B — `plan_phase` directly** (plan against history)
132
+ > ```bash
133
+ > project-guide mode plan_phase
134
+ > ```
135
+ > This appends the new phase to the existing `stories.md` alongside the completed phases.
136
+ >
137
+ > *Use this when:* the completed phases provide useful context that should remain visible during planning, or the project is still small enough that a single `stories.md` is comfortable to scroll.
138
+ >
139
+ > Which would you like?
140
+
141
+ Wait for the developer to choose before changing modes.
142
+
143
+ ### If at least one story is non-`[Done]`
144
+
145
+ The current phase still has in-progress, planned, or otherwise incomplete work. Use the existing project lifecycle suggestions above — direct the developer to the relevant coding mode (`code_velocity`, `code_test_first`) or, if planning artifacts are missing, to the appropriate planning mode.
146
+
147
+ ### If `stories.md` does not exist
148
+
149
+ This is a fresh project. Direct the developer to `project-guide mode plan_concept` to begin the lifecycle.
150
+
151
+ ## All Available Modes
152
+
153
+ ### Planning (sequence)
154
+ | Mode | Command | Output |
155
+ |------|---------|--------|
156
+ | **Concept** | `project-guide mode plan_concept` | `docs/specs/concept.md` |
157
+ | **Features** | `project-guide mode plan_features` | `docs/specs/features.md` |
158
+ | **Tech Spec** | `project-guide mode plan_tech_spec` | `docs/specs/tech-spec.md` |
159
+ | **Stories** | `project-guide mode plan_stories` | `docs/specs/stories.md` |
160
+ | **Phase** | `project-guide mode plan_phase` | Add a new phase to an existing project |
161
+
162
+ ### Scaffold (sequence)
163
+ | Mode | Command | Purpose |
164
+ |------|---------|---------|
165
+ | **Project Scaffold** | `project-guide mode project_scaffold` | One-time project scaffolding |
166
+
167
+ ### Coding (cycle)
168
+ | Mode | Command | Workflow |
169
+ |------|---------|----------|
170
+ | **Velocity** | `project-guide mode code_velocity` | Direct commits, fast iteration |
171
+ | **Test-First** | `project-guide mode code_test_first` | TDD red-green-refactor cycle |
172
+ | **Debug** | `project-guide mode debug` | Test-driven debugging |
173
+
174
+ ### Documentation (sequence)
175
+ | Mode | Command | Output |
176
+ |------|---------|--------|
177
+ | **Branding** | `project-guide mode document_brand` | `docs/specs/brand-descriptions.md` |
178
+ | **Landing Page** | `project-guide mode document_landing` | GitHub Pages + MkDocs docs |
179
+
180
+ ### Post-Release (sequence)
181
+ | Mode | Command | Purpose |
182
+ |------|---------|---------|
183
+ | **Archive Stories** | `project-guide mode archive_stories` | Move completed `stories.md` to `.archive/` and re-render an empty one for the next phase |
184
+
@@ -0,0 +1,43 @@
1
+ <!--
2
+ This file captures must-know facts future LLMs need to avoid blunders when
3
+ working on this project. Anything a smart newcomer could miss on day one and
4
+ waste time on goes here.
5
+
6
+ This content gets injected verbatim under a `## Project Essentials` section
7
+ in every rendered `go.md`, so entries below should use `###` for subsections
8
+ (not `##`, which would collide with the wrapper heading). Do NOT include a
9
+ top-level `#` title — the wrapper provides it.
10
+
11
+ What belongs here:
12
+
13
+ - **Workflow rules — tool wrappers and environment conventions.** A common
14
+ source of "random walks" by LLMs: multiple invocation forms all *work*,
15
+ but only one is canonical. Capture which form to use so future LLMs don't
16
+ pick whatever happens to succeed first. Examples:
17
+ - Python invocation (`pyve run python ...` vs `python -m ...` vs
18
+ `.venv/bin/python ...`)
19
+ - Dev-tool installation (dedicated testenv vs `pip install -e ".[dev]"`
20
+ into the main venv — different isolation guarantees)
21
+ - Test invocation (`pyve test`, `poetry run pytest`, `make test` vs
22
+ bare `pytest`)
23
+
24
+ - **Architecture quirks.** Source-of-truth vs generated/installed file
25
+ locations (edit the source, not the copy); build outputs that get
26
+ regenerated; files that look hand-edited but aren't.
27
+
28
+ - **Domain conventions.** Money stored in cents, all timestamps UTC, IDs
29
+ are strings not ints, and similar non-obvious rules.
30
+
31
+ - **Hidden coupling.** Files that mirror each other; auto-generated code;
32
+ regenerated outputs that look hand-edited.
33
+
34
+ - **Dogfooding / meta notes.** If the project uses itself, capture the
35
+ rules that keep the dogfood loop safe.
36
+
37
+ An empty file is acceptable — omit this file entirely, or leave the comment
38
+ block above with no content below it. When empty, the rendered `go.md` for
39
+ every mode will simply omit the "Project Essentials" section.
40
+
41
+ The `plan_tech_spec`, `refactor_plan`, and `plan_phase` modes prompt for new
42
+ entries at natural points in the project lifecycle.
43
+ -->
@@ -33,7 +33,13 @@ When you have completed the steps, pause for the developer to review, correct, r
33
33
  - After compacting memory, re-read this guide to refresh your context.
34
34
 
35
35
  ---
36
+ {% if project_essentials %}
37
+ ## Project Essentials
36
38
 
39
+ {{ project_essentials }}
40
+
41
+ ---
42
+ {% endif %}
37
43
  # {{ mode_name }} mode ({{ sequence_or_cycle }})
38
44
 
39
45
  > {{ mode_info }}
@@ -0,0 +1,75 @@
1
+ Generate a combined concept/features/tech-spec document for a new phase in an existing project, then add the phase and stories to `docs/specs/stories.md`.
2
+
3
+ Use this mode when the developer wants to add a significant new capability to a project that already has an established codebase and spec documents.
4
+
5
+ {% include "modes/_header-sequence.md" %}
6
+
7
+ ## Prerequisites
8
+
9
+ Before planning a new phase, the following should exist:
10
+ - `docs/specs/concept.md`
11
+ - `docs/specs/features.md`
12
+ - `docs/specs/tech-spec.md`
13
+ - `docs/specs/stories.md`
14
+
15
+ ## Steps
16
+
17
+ 1. Read the existing spec documents to understand the current project state.
18
+
19
+ `docs/specs/stories.md` may be in one of two shapes:
20
+
21
+ a. **Populated** — contains one or more `## Phase <Letter>:` sections from prior phases. Use the highest existing phase letter as the basis for the next one (see step 5).
22
+
23
+ b. **Empty (post-archive)** — `archive_stories` was just run and `stories.md` contains only the header and a `## Future` section, no phases. In this case, look in `docs/specs/.archive/` for files named `stories-vX.Y.Z.md`. Read the one with the highest version and find its highest `## Phase <Letter>:` heading — that is the basis for the next phase letter. Phase letters **continue across the archive boundary**; they do not reset.
24
+
25
+ If neither `stories.md` nor `.archive/` contains any phases, this is a fresh project — start at `A`.
26
+
27
+ 2. Gather information from the developer about the new phase:
28
+ - phase_name: A short name for the phase (e.g., "Mode System", "API Integration")
29
+ - problem_gap: What capability is missing or what problem this phase solves
30
+ - new_features: What the phase will add (functional requirements)
31
+ - technical_approach: How it will be built (architecture changes, new modules, new dependencies)
32
+ - constraints: Any limitations or compatibility requirements with existing code
33
+ - scope: What this phase will and won't do
34
+
35
+ 3. Generate a phase plan document at `docs/specs/phase-<letter>-<name>-plan.md` that combines:
36
+ - **Gap analysis**: What exists vs. what's needed
37
+ - **Feature requirements**: What the phase adds (mini features.md)
38
+ - **Technical changes**: New/modified modules, dependencies, config changes (mini tech-spec.md)
39
+ - **Out of scope**: What's deferred to future phases
40
+
41
+ 4. Present the phase plan to the developer for approval.
42
+
43
+ 5. After approval, add a new phase section and stories to `docs/specs/stories.md`:
44
+ - **Determine the next phase letter** by applying the algorithm from step 1:
45
+ - If `stories.md` had existing phases, the next letter is the successor of the highest one (e.g., `K` → `L`).
46
+ - If `stories.md` was empty but `.archive/` had a `stories-vX.Y.Z.md`, read the latest archived file, find its highest phase letter, and take its successor (e.g., archived Phase `J` → next phase `K`).
47
+ - If neither had phases, start at `A`.
48
+ - The successor follows the base-26-no-zero scheme (`Z` → `AA`, `ZZ` → `AAA`). See the Phase and Story ID Scheme below for details.
49
+ - If `stories.md` was empty, **insert the new phase as the first phase** in the file (after the header and `---`, before any `## Future` section). Otherwise append after the highest existing phase but before `## Future`.
50
+ - Break the phase into stories following the standard story format.
51
+ - Include a spike story if the phase introduces a new integration boundary.
52
+
53
+ 6. Present the updated stories to the developer for approval.
54
+
55
+ 7. **After the stories are approved, append any new must-know facts to `project-essentials.md`.** Run this step **once** at the end of phase planning — not per-story.
56
+
57
+ First, check whether `docs/specs/project-essentials.md` exists:
58
+ - **If it does NOT exist**: this is a legacy project that has never had project-essentials captured. Create it fresh from the artifact template at `templates/artifacts/project-essentials.md`, then continue below. Note: this is the same create path as `refactor_plan`, and legacy projects are the highest-value case for a first-time capture.
59
+ - **If it exists**: read the current content and keep it in mind for the next sub-step.
60
+
61
+ Then ask the developer: **"Does this phase introduce any new must-know facts that future LLMs should know? New architecture boundaries, new workflow rules, new gotchas?"** Put these concrete worked examples in front of them — phase planning is specifically about *adding* capability, so the relevant gotchas are usually about interactions between the new and old worlds:
62
+
63
+ - **New architecture boundary.** Did the phase introduce a new module, layer, or integration surface that has rules the rest of the codebase doesn't? *Example:* "Phase K adds an `archive` action type. Action handlers live in `project_guide/actions.py`; metadata registration is in `.metadata.yml`; the runtime split is that only `archive` actions fire deterministically via the CLI, while `create`/`modify` are LLM-handled. Don't add new action types without updating both files and the `VALID_ARTIFACT_ACTIONS` constant."
64
+ - **New workflow rule or CLI contract.** Did the phase add a flag, env var, or error-message format that downstream tooling may depend on? *Example:* "Phase L added `--no-input` with a pinned error-message contract in `tests/test_cli.py::test_require_setting_contract_exit_code_and_message`. Downstream tools (pyve) may cite this message verbatim — do not change it without a coordinated release."
65
+ - **New hidden coupling between files.** Did the phase introduce a pair of files (or a file and a generated output) that must stay in sync? *Example:* "Phase M wires the render pipeline to `docs/specs/project-essentials.md` via `_header-common.md`'s {% raw %}`{% if project_essentials %}`{% endraw %} guard — removing the guard silently breaks every render. Covered by the post-render placeholder validator from M.b."
66
+ - **New deferred-but-documented item.** Did the phase explicitly defer something to a future phase? That deferral itself may be a must-know fact — future work on adjacent areas may accidentally re-implement what you decided to skip.
67
+ - **Principle**: if the phase introduced a new *invariant* or *convention* that someone working in this codebase a year from now would waste an hour rediscovering, it belongs in project-essentials. If the phase was a straightforward feature addition with no new invariants, skip this step.
68
+
69
+ **Skip if there are none.** Not every phase introduces new must-know facts. A pure feature addition that follows existing conventions does not need new project-essentials content — confirm with the developer and skip.
70
+
71
+ If the developer provides new facts, **append** (do not rewrite or reorder) them to `docs/specs/project-essentials.md`. The append-only semantics are deliberate: `plan_phase` runs once per phase and is not the place to refactor existing project-essentials content — that's `refactor_plan`'s Final Step job. Add new `###` subsections under the appropriate category (or create a new category if none fits). Follow the artifact template's heading convention: **do NOT include a top-level `#` heading** (the rendered `go.md` wrapper provides `## Project Essentials`), and use `###` for subsections so they nest correctly.
72
+
73
+ Present the updated file to the developer for approval. Show only what was added (since this is an append operation, the diff is minimal).
74
+
75
+ {% include "modes/_phase-letters.md" %}