diff --git a/.claude/commands/cdd-retrofit.md b/.claude/commands/cdd-retrofit.md index 3770c2c..1798600 100644 --- a/.claude/commands/cdd-retrofit.md +++ b/.claude/commands/cdd-retrofit.md @@ -166,6 +166,13 @@ For each file, with `old` = staged old render, `current` = staged current render Every application is per-file interactive: show the diff, get approval, write into `$WT`. +**Added files — reconcile fill-in skeletons, don't ship them raw.** A file absent from the old render is newer than the project's baseline, and it may be a fill-in skeleton whose placeholder defaults would make false claims about a mature project (the motivating case: `engineering-practices.md` arriving with `` / `` / `` placeholders and provisional `` markers, claiming no gate exists in a project that already runs pytest, ruff, and CI). For every file you propose adding: + +- **Scan the staged render for residual `<...>` tokens.** The render already substituted the two identifiers (``/``), so any remaining `<...>` is genuine fill-in content — a placeholder field or a provisional status marker. +- **If it carries residual placeholders, reconcile before writing.** Make a best-effort pass to fill the fields you can confidently detect from the target's actual state, and propose the filled result under the same per-file approval as any other write. Keep this lightweight: fill what you can confidently detect and leave the rest — do **not** build a general reconciliation engine (`/cdd-pre-pr` is the systematic backstop). Never fabricate a value to clear a placeholder; if you can't confidently determine it, leave the placeholder and let the summary flag it. +- **Worked example — `engineering-practices.md`.** Fill `` / `` / `` / `` / `` from the commands you can detect (a `Makefile`/`pyproject.toml`/`package.json` test or lint target, a test-runner or linter config), and flip each provisional status marker to **Enforced** or **Expected** according to whether that gate actually exists — CI judged by a `.github/workflows/*.yml`, tests/lint by the presence of the corresponding runner or linter config. Apply the same shape to any other added fill-in doc. +- Anything left unreconciled after the approved edit still counts as residual and is carried into the section 5 summary flag. + ### 4.5 Upstream candidates For each preserved local customization, judge whether it is project-specific (mentions the project's name/slug/domain, encodes its build commands) or **general** (a workflow improvement any CDD project would want). Do not silently keep general improvements local: collect them into a report — file, hunk, why it looks upstreamable — and present it at the end as candidates to port into `template/` (and the process doc) via a normal CDD task in this repo. Do not auto-apply anything to the CDD repo in this session. @@ -194,6 +201,7 @@ Report, in both modes: - Mode detected, identifiers used. - The isolation: the worktree path (`$WT`), the branch name, and the commit hash made on it — or, if section 2.5 fell back, that writes landed in place with no commit and why. - Files copied / upgraded / merged / preserved (and any the user declined). +- **Added — needs reconciliation** (upgrade mode): any added file that still contains residual `<...>` placeholders or provisional status markers after all approved edits, listed by path. Keep this as a distinct category from clean adds so it reads as an action item, not a silent success — the user must finish these, and the recommended `/cdd-pre-pr` pass below will also catch them. - The marker value written. - Upstream candidates surfaced (upgrade mode), with a pointer to file them as a roadmap item in the CDD repo. - Any gitignore warnings from step 1. diff --git a/doc/features/template.md b/doc/features/template.md index 824a3e6..d0c52e9 100644 --- a/doc/features/template.md +++ b/doc/features/template.md @@ -28,7 +28,7 @@ Audience: developers starting a new project who want a guided setup rather than A CDD-repo-only slash command (`.claude/commands/cdd-retrofit.md`, deliberately not shipped in the template) for bringing CDD to projects that already exist. Run from a CDD-repo session with the target path as argument, it auto-detects between two modes: - **Install** — the target has no CDD scaffolding: a files-only install of the template via the bootstrap script's stage mode. Missing files are copied; collisions (an existing `CLAUDE.md`, say) are merged interactively per file. The codebase survey, initial architecture doc, and roadmap generation arrive as the template roadmap's pre-filled bootstrap tasks, which the project's first `/cdd-next-step` proposes as the first task. -- **Upgrade** — the target already runs CDD: a three-way comparison anchored on the `.claude/cdd-baseline` marker applies template improvements, preserves local customizations, and surfaces general-looking local improvements as candidates to upstream into the CDD repo. Pre-marker projects fall back to two-way diffing and get the marker going forward. +- **Upgrade** — the target already runs CDD: a three-way comparison anchored on the `.claude/cdd-baseline` marker applies template improvements, preserves local customizations, and surfaces general-looking local improvements as candidates to upstream into the CDD repo. Files the template has newly accrued since the baseline are reconciled rather than shipped raw — obvious fields (test/lint/CI commands, enforced-vs-expected markers) filled from the project's detected state under per-file approval, with any file still carrying residual placeholders flagged in the summary as "needs reconciliation." Pre-marker projects fall back to two-way diffing and get the marker going forward. In both modes the writes are isolated: before rendering anything, the command creates a dedicated branch (`cdd-retrofit`) and a sibling worktree off the target's HEAD, directs every write there, and makes a single commit on the branch — so the user reviews and merges the scaffolding through a normal PR instead of finding it strewn across the current branch. A dirty target tree no longer blocks the retrofit (the worktree is taken from HEAD); the command only warns when CDD-managed files have uncommitted edits, since those won't be seen by the upgrade comparison. If the target is not a git repo (or the worktree can't be created), it warns and falls back to writing in place. diff --git a/doc/knowledge_base/claude-driven-development.md b/doc/knowledge_base/claude-driven-development.md index fb1a908..8b882d0 100644 --- a/doc/knowledge_base/claude-driven-development.md +++ b/doc/knowledge_base/claude-driven-development.md @@ -470,7 +470,7 @@ This raises a recurring question — *is the task a deliverable or a project?* **Adapting an existing project.** Addressed by `/cdd-retrofit`, a command that lives in the CDD repo only (see Section 2.7) and is run from a CDD-repo session with the target project's path as argument. It auto-detects which of two modes applies: - *Install mode* — the target has no CDD scaffolding. A files-only install of the template: slash commands, doc skeletons, the worktree helper, `.claude/settings.json`, with placeholder substitution done by `bootstrap-cdd-project.sh` in a render-only staging mode (the command never reimplements substitution). Files missing from the target are copied; collisions with existing files (a project's own `CLAUDE.md`, for instance) are merged interactively, one file at a time, with human approval — never overwritten silently. No codebase survey happens at install time: the template roadmap ships with a pre-filled bootstrap phase (survey the codebase, draft the initial architecture docs, write the feature docs, fill in the roadmap), so the project's first `/cdd-next-step` picks those up as the next unchecked tasks. This pre-filled phase is for files-only starts — install mode here and the manual bootstrap-script path — where no docs have been written yet; `/cdd-bootstrap` writes the docs through guided discovery and so ships a real roadmap without it. -- *Upgrade mode* — the target already runs CDD. Using the baseline marker (Section 2.10) as the merge base, each CDD-managed file is compared three ways: improvements the CDD template has accrued are proposed for application; local customizations are preserved; files changed on both sides get an interactive merge. Local changes that look general rather than project-specific are not silently kept local — they are surfaced as candidates to upstream into the CDD repo. Every change that touches a project file is approved per file; the checkpoints of Section 4 apply in spirit here too. +- *Upgrade mode* — the target already runs CDD. Using the baseline marker (Section 2.10) as the merge base, each CDD-managed file is compared three ways: improvements the CDD template has accrued are proposed for application; local customizations are preserved; files changed on both sides get an interactive merge. Local changes that look general rather than project-specific are not silently kept local — they are surfaced as candidates to upstream into the CDD repo. Every change that touches a project file is approved per file; the checkpoints of Section 4 apply in spirit here too. Files the template has newly accrued (absent from the project's baseline) are *added* — and because such a file can be a fill-in skeleton whose placeholder defaults would make false claims about a mature project (e.g. an `engineering-practices.md` that arrives claiming no test or CI gate exists), upgrade mode does not add it raw: it reconciles the obvious fields it can confidently detect from the project's actual state under the same per-file approval, and flags any file still carrying residual placeholders or provisional status markers in its summary as "needs reconciliation." This is best-effort — `/cdd-pre-pr` remains the systematic backstop — and it is confined to upgrade mode's added files; install mode is deliberately exempt, because there the whole template lands as skeleton by design and the first `/cdd-next-step` doc-reconciliation task is the intended mechanism. In both modes the retrofit isolates its writes from the target's current branch. Before rendering anything, it creates a dedicated branch (`cdd-retrofit`) and a sibling worktree off the target's HEAD, directs every write into that worktree, and — once all per-file approvals are done — makes a single commit on the branch so the user reviews and merges the scaffolding through a normal PR rather than finding it strewn across the current branch (usually the default branch). The recommended path before opening that PR is to start a fresh Claude session in the retrofit worktree and run `/cdd-pre-pr` there, so the retrofit's own edits — which touch CDD-managed files and doc skeletons — get the standard reconciliation and review pass; this applies in both install and upgrade mode, and is how a newly-added skeleton doc left with unfilled placeholders gets caught before it reaches review. This is the one place CDD runs history-mutating git in a target, and it is deliberately scoped: the command only ever creates the dedicated branch and commits onto *it*, never onto the target's existing branches. On the happy path — a sibling worktree off HEAD — it never touches the current checkout. If the target is not a git repo, the command warns and falls back to writing in place without committing; if it is a git repo with no commits yet (an unborn HEAD, where a worktree can't be created), it falls back to a plain branch in the existing checkout and commits there. Because the worktree branches from HEAD, uncommitted local edits to CDD-managed files are not seen by the upgrade comparison; the command warns when it detects them rather than hard-stopping on any dirty tree. diff --git a/doc/knowledge_base/roadmap.md b/doc/knowledge_base/roadmap.md index 6fbe13e..9325caf 100644 --- a/doc/knowledge_base/roadmap.md +++ b/doc/knowledge_base/roadmap.md @@ -132,6 +132,7 @@ Defects and gaps surfaced by retrofitting CDD onto real existing projects. Each - [x] **Handoff path diverges when the repo dir isn't already a valid ``.** Fixed: the `` regex in `bootstrap-cdd-project.sh` is loosened to `^[A-Za-z][A-Za-z0-9_-]*$`, so CamelCase dirs like `PyGroundControl` are accepted as-is. The rendered handoff path now matches the actual directory basename the worktree helper derives at runtime. - [x] **`cdd-next-step.md` hardcodes `~/Code/` as the repo location** (the suggested source line). Fixed: `cdd-next-step.md` §8 now instructs resolving the repo root via `git rev-parse --show-toplevel` and embedding the actual path in the printed source line. - [ ] **Gitflow case: platform default ≠ integration branch** (e.g. `main` is the release branch but daily work branches off `devel`). `cdd-merge-base` and `cdd-pre-pr` target the platform default branch — correct for the PyGroundControl case (`devel` *is* the platform default), but wrong for gitflow projects where the platform default is the release branch. Fix requires an explicit `BASE_BRANCH` config mechanism. +- [x] **Retrofit reconciles newly-added fill-in docs instead of shipping raw skeletons.** In upgrade mode, when a template file newer than the target's baseline is added, retrofit reconciles obvious fields against detected project state under per-file approval, and flags any residual placeholders/provisional markers in the summary as "needs reconciliation" (issue #41). Fixed a Scribe upgrade landing `engineering-practices.md` with unfilled ``/`` placeholders and provisional `` markers, factually wrong for a project already enforcing pytest, ruff, and CI. Install mode stays exempt (whole template lands as skeleton by design). Changes: `.claude/commands/cdd-retrofit.md` §4.4/§5 and the process doc's §6 existing-project section. - [ ] **Retrofit doc-reconciliation playbook for common pre-existing layouts.** PyGroundControl needed manual reconciliation that recurs across projects: a split architecture-doc layout (`doc/backend/`, `doc/frontend/`, a top-level `system-architecture.md`) folding into `doc/architecture/`; a `future-work.md`/TODO/backlog doc folding into `roadmap.md`; an oversized CLAUDE.md duplicating command/troubleshooting content that should be slimmed to pointers (per-session context cost). Capture these as explicit guidance/checklist in `/cdd-retrofit` (and the process doc's existing-project section) so they aren't rediscovered each time. **Milestone:** CDD retrofits cleanly onto a project regardless of default-branch name, repo directory name/location, or pre-existing doc layout, without per-project manual fixes to the scaffolding.