feat(tasks): add migrate:vbrief migration script for vBRIEF-centric cutover (#312)#341
Conversation
Greptile SummaryThis PR adds Confidence Score: 5/5Safe to merge; all previously raised P1 findings are addressed and only a docstring inaccuracy remains All three prior P1/P2 findings (slug collision, setdefault data loss, missing CHANGELOG date) are fixed in the round-3 batch commits. The only new finding is a misleading docstring on _resolve_repo_url (P2). 40 tests cover the critical code paths including idempotency, fold-failure abort, and slug-collision guard. No files require special attention Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([task migrate:vbrief]) --> B[Step 1: Create 5 lifecycle folders\nproposed/ pending/ active/ completed/ cancelled/]
B --> C[Step 2: Read existing sources\nspecification.vbrief.json · SPECIFICATION.md\nPROJECT.md · ROADMAP.md]
C --> D{PROJECT-DEFINITION\nalready exists?}
D -- No --> E[Step 3: Generate\nPROJECT-DEFINITION.vbrief.json\nnarratives + items registry]
D -- Yes --> F[SKIP idempotent]
E --> G
F --> G[Step 4: For each ROADMAP item]
G --> H{Exact filename\nexists in pending/?}
H -- Yes --> I[SKIP idempotent]
H -- No --> J{Any lifecycle folder\nreferences issue #N?}
J -- Yes --> K[SKIP existing vBRIEF]
J -- No --> L[CREATE pending/DATE-N-slug.vbrief.json]
I --> M
K --> M
L --> M[Step 5: Deprecation redirects]
M --> N{SPECIFICATION.md\nhas sentinel?}
N -- No --> O{User-customized?}
O -- Yes --> P[_fold_custom_content into\nPROJECT-DEFINITION narratives]
P --> Q{Fold succeeded?}
Q -- No --> R([ABORT — data loss risk])
Q -- Yes --> S[REPLACE SPECIFICATION.md\nwith redirect]
O -- No --> S
N -- Yes --> T[SKIP]
S --> U{PROJECT.md\nhas sentinel?}
T --> U
U -- No --> V[Warn if user-customized\nREPLACE PROJECT.md\nwith redirect]
U -- Yes --> W[SKIP]
V --> X([Done])
W --> X
Prompt To Fix All With AIThis is a comment left during a code review.
Path: scripts/migrate_vbrief.py
Line: 106-126
Comment:
**Docstring promises fallbacks that don't exist**
The docstring states "Resolve the GitHub repository URL from spec_vbrief **or git remote**" and "Falls back to a **generic issue: prefix** if no repository can be determined," but the implementation does neither: there is no `git remote` lookup, and the return value when nothing is found is `""` (empty string), not a `"issue:"` prefix URI. Any caller expecting a non-empty fallback will silently produce references without `url` fields.
```suggestion
def _resolve_repo_url(spec_vbrief: dict | None) -> str:
"""Resolve the GitHub repository URL from spec_vbrief metadata.
Returns an empty string if no repository URL can be determined; callers
that build provenance references should treat "" as "omit url field".
"""
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (6): Last reviewed commit: "fix: address Greptile review findings ro..." | Re-trigger Greptile |
7487bef to
c10c922
Compare
…utover (#312) - Create scripts/migrate_vbrief.py: automated migration from current document model to vBRIEF-centric lifecycle folder structure (RFC #309) - Parse specification.vbrief.json + PROJECT.md to generate PROJECT-DEFINITION.vbrief.json with narratives + items registry (D3) - Create 5 lifecycle folders: proposed/ pending/ active/ completed/ cancelled/ (D13) - Convert ROADMAP.md items to individual pending/ scope vBRIEFs with provenance (D11) - Replace SPECIFICATION.md and PROJECT.md with deprecation redirects (#334) - Detect user-customized content before replacing and preserve in narratives - Migration is idempotent (safe to run twice) - Register as task migrate:vbrief in tasks/migrate.yml + Taskfile.yml - Add 40 unit tests in tests/cli/test_migrate_vbrief.py - Add CHANGELOG entry under [Unreleased]
- Restore release date on [0.19.0] heading (was accidentally dropped) - Include issue number in scope vBRIEF filenames to prevent slug collisions (e.g. 2026-04-13-100-add-widget-support.vbrief.json) - Fix _fold_custom_content using setdefault to prevent silent content loss when plan/narratives keys are absent from PROJECT-DEFINITION - Add 2 new tests: slug collision produces separate files, filename includes issue number (42 total tests) - MCP unavailable in this session -- used gh api fallback for review comments
- Remove hard-coded deftai/directive repo URL from provenance references; resolve from spec_vbrief metadata or leave URL-less for portability - Add _resolve_repo_url() to extract repo from vBRIEFInfo.repository field or plan.references GitHub URLs - Fix _fold_custom_content to return bool; preservation warning now only printed after successful fold, with fallback warning on failure - Add 4 new tests: resolve_repo_url (3) + provenance with repo_url (1) Total: 46 tests - MCP unavailable -- used gh api fallback for review comments
- Abort migration when custom SPECIFICATION.md fold fails, preventing data loss (return False with error message instead of writing redirect) - Remove redundant _fold_custom_content call for ProjectConfig (already captured by _build_project_definition in step 3) - Add comment documenting why PROJECT.md fold is safe (step 3 safety net) - MCP unavailable -- used gh api fallback for review comments
c10c922 to
f31ec00
Compare
Summary
Add automated migration script ( ask migrate:vbrief) that converts existing Deft projects from the current document model to the new vBRIEF-centric folder structure defined by RFC #309.
Changes
New Files
Modified Files
Acceptance Criteria
References
Part of #309. Closes #312. Tracking: #338.
Checklist