@ktpartners/dgs-platform 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +38 -0
- package/README.md +851 -0
- package/agents/dgs-codebase-cross-analyzer.md +183 -0
- package/agents/dgs-codebase-mapper.md +782 -0
- package/agents/dgs-codebase-synthesizer.md +156 -0
- package/agents/dgs-debugger.md +1256 -0
- package/agents/dgs-executor.md +550 -0
- package/agents/dgs-integration-checker.md +481 -0
- package/agents/dgs-nyquist-auditor.md +178 -0
- package/agents/dgs-phase-researcher.md +563 -0
- package/agents/dgs-phase-verifier.md +450 -0
- package/agents/dgs-plan-checker.md +708 -0
- package/agents/dgs-planner.md +1324 -0
- package/agents/dgs-project-researcher.md +631 -0
- package/agents/dgs-research-synthesizer.md +249 -0
- package/agents/dgs-roadmapper.md +652 -0
- package/agents/dgs-verifier.md +607 -0
- package/bin/install.js +2073 -0
- package/commands/dgs/add-doc.md +45 -0
- package/commands/dgs/add-idea.md +38 -0
- package/commands/dgs/add-phase.md +43 -0
- package/commands/dgs/add-repo.md +54 -0
- package/commands/dgs/add-tests.md +41 -0
- package/commands/dgs/add-todo.md +47 -0
- package/commands/dgs/approve-spec.md +38 -0
- package/commands/dgs/audit-milestone.md +36 -0
- package/commands/dgs/audit-phase.md +37 -0
- package/commands/dgs/cancel-job.md +23 -0
- package/commands/dgs/capture-principle.md +143 -0
- package/commands/dgs/check-todos.md +45 -0
- package/commands/dgs/cleanup.md +18 -0
- package/commands/dgs/complete-milestone.md +136 -0
- package/commands/dgs/complete-project.md +70 -0
- package/commands/dgs/consolidate-ideas.md +50 -0
- package/commands/dgs/create-milestone-job.md +37 -0
- package/commands/dgs/debug.md +164 -0
- package/commands/dgs/develop-idea.md +53 -0
- package/commands/dgs/discuss-idea.md +41 -0
- package/commands/dgs/discuss-phase.md +83 -0
- package/commands/dgs/execute-phase.md +41 -0
- package/commands/dgs/fast.md +38 -0
- package/commands/dgs/find-related-ideas.md +43 -0
- package/commands/dgs/health.md +28 -0
- package/commands/dgs/help.md +22 -0
- package/commands/dgs/import-spec.md +36 -0
- package/commands/dgs/init-product.md +28 -0
- package/commands/dgs/insert-phase.md +32 -0
- package/commands/dgs/join-discord.md +18 -0
- package/commands/dgs/list-docs.md +40 -0
- package/commands/dgs/list-ideas.md +42 -0
- package/commands/dgs/list-jobs.md +22 -0
- package/commands/dgs/list-phase-assumptions.md +46 -0
- package/commands/dgs/list-projects.md +57 -0
- package/commands/dgs/list-specs.md +40 -0
- package/commands/dgs/map-codebase.md +92 -0
- package/commands/dgs/new-milestone.md +44 -0
- package/commands/dgs/new-project.md +42 -0
- package/commands/dgs/node-repair.md +26 -0
- package/commands/dgs/overlap-check.md +20 -0
- package/commands/dgs/pause-work.md +38 -0
- package/commands/dgs/plan-milestone-gaps.md +34 -0
- package/commands/dgs/plan-phase.md +44 -0
- package/commands/dgs/progress.md +24 -0
- package/commands/dgs/quick.md +41 -0
- package/commands/dgs/reactivate-project.md +70 -0
- package/commands/dgs/reapply-patches.md +110 -0
- package/commands/dgs/refine-spec.md +38 -0
- package/commands/dgs/reject-idea.md +43 -0
- package/commands/dgs/remove-doc.md +44 -0
- package/commands/dgs/remove-phase.md +31 -0
- package/commands/dgs/remove-repo.md +69 -0
- package/commands/dgs/research-idea.md +43 -0
- package/commands/dgs/research-phase.md +189 -0
- package/commands/dgs/restore-idea.md +45 -0
- package/commands/dgs/resume-work.md +40 -0
- package/commands/dgs/rollback-job.md +24 -0
- package/commands/dgs/run-job.md +35 -0
- package/commands/dgs/search.md +40 -0
- package/commands/dgs/set-profile.md +34 -0
- package/commands/dgs/settings.md +38 -0
- package/commands/dgs/switch-project.md +58 -0
- package/commands/dgs/undo-consolidation.md +42 -0
- package/commands/dgs/update-idea.md +44 -0
- package/commands/dgs/update.md +37 -0
- package/commands/dgs/validate-phase.md +35 -0
- package/commands/dgs/verify-work.md +39 -0
- package/commands/dgs/write-spec.md +49 -0
- package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-01-SUMMARY.md +84 -0
- package/deliver-great-systems/.planning/phases/09-backend-wiring-and-error-handling/09-02-SUMMARY.md +86 -0
- package/deliver-great-systems/.planning/phases/10-v1-to-v2-migration-flow/10-01-SUMMARY.md +85 -0
- package/deliver-great-systems/bin/dgs-tools.cjs +1444 -0
- package/deliver-great-systems/bin/lib/auto-test.cjs +1365 -0
- package/deliver-great-systems/bin/lib/commands.cjs +570 -0
- package/deliver-great-systems/bin/lib/config.cjs +417 -0
- package/deliver-great-systems/bin/lib/conflict-agent.cjs +1063 -0
- package/deliver-great-systems/bin/lib/conflict-agent.test.cjs +554 -0
- package/deliver-great-systems/bin/lib/context.cjs +929 -0
- package/deliver-great-systems/bin/lib/context.test.cjs +693 -0
- package/deliver-great-systems/bin/lib/core.cjs +744 -0
- package/deliver-great-systems/bin/lib/core.test.cjs +822 -0
- package/deliver-great-systems/bin/lib/docs.cjs +919 -0
- package/deliver-great-systems/bin/lib/docs.test.cjs +211 -0
- package/deliver-great-systems/bin/lib/execution.cjs +705 -0
- package/deliver-great-systems/bin/lib/execution.test.cjs +1472 -0
- package/deliver-great-systems/bin/lib/frontmatter.cjs +324 -0
- package/deliver-great-systems/bin/lib/ideas.cjs +1406 -0
- package/deliver-great-systems/bin/lib/ideas.test.cjs +1417 -0
- package/deliver-great-systems/bin/lib/identity.cjs +125 -0
- package/deliver-great-systems/bin/lib/init.cjs +1114 -0
- package/deliver-great-systems/bin/lib/init.test.cjs +1271 -0
- package/deliver-great-systems/bin/lib/jobs.cjs +2015 -0
- package/deliver-great-systems/bin/lib/jobs.test.cjs +2619 -0
- package/deliver-great-systems/bin/lib/merge-conflicts.cjs +654 -0
- package/deliver-great-systems/bin/lib/merge-conflicts.test.cjs +370 -0
- package/deliver-great-systems/bin/lib/migration.cjs +352 -0
- package/deliver-great-systems/bin/lib/migration.test.cjs +582 -0
- package/deliver-great-systems/bin/lib/milestone.cjs +243 -0
- package/deliver-great-systems/bin/lib/overlap.cjs +437 -0
- package/deliver-great-systems/bin/lib/overlap.test.cjs +747 -0
- package/deliver-great-systems/bin/lib/path-audit.test.cjs +384 -0
- package/deliver-great-systems/bin/lib/paths.cjs +144 -0
- package/deliver-great-systems/bin/lib/paths.test.cjs +486 -0
- package/deliver-great-systems/bin/lib/phase.cjs +910 -0
- package/deliver-great-systems/bin/lib/projects.cjs +691 -0
- package/deliver-great-systems/bin/lib/projects.test.cjs +871 -0
- package/deliver-great-systems/bin/lib/repos.cjs +1432 -0
- package/deliver-great-systems/bin/lib/repos.test.cjs +1882 -0
- package/deliver-great-systems/bin/lib/roadmap.cjs +305 -0
- package/deliver-great-systems/bin/lib/search.cjs +570 -0
- package/deliver-great-systems/bin/lib/specs.cjs +1303 -0
- package/deliver-great-systems/bin/lib/state.cjs +893 -0
- package/deliver-great-systems/bin/lib/template.cjs +228 -0
- package/deliver-great-systems/bin/lib/test-helpers.cjs +291 -0
- package/deliver-great-systems/bin/lib/verify.cjs +796 -0
- package/deliver-great-systems/references/checkpoints.md +776 -0
- package/deliver-great-systems/references/conflict-resolution.md +66 -0
- package/deliver-great-systems/references/context-tiers.md +166 -0
- package/deliver-great-systems/references/continuation-format.md +249 -0
- package/deliver-great-systems/references/decimal-phase-calculation.md +67 -0
- package/deliver-great-systems/references/git-integration.md +250 -0
- package/deliver-great-systems/references/git-planning-commit.md +40 -0
- package/deliver-great-systems/references/model-profile-resolution.md +36 -0
- package/deliver-great-systems/references/model-profiles.md +95 -0
- package/deliver-great-systems/references/phase-argument-parsing.md +61 -0
- package/deliver-great-systems/references/planning-config.md +224 -0
- package/deliver-great-systems/references/questioning.md +162 -0
- package/deliver-great-systems/references/spec-review-loop.md +177 -0
- package/deliver-great-systems/references/tdd.md +265 -0
- package/deliver-great-systems/references/ui-brand.md +160 -0
- package/deliver-great-systems/references/verification-patterns.md +612 -0
- package/deliver-great-systems/templates/DEBUG.md +166 -0
- package/deliver-great-systems/templates/UAT.md +251 -0
- package/deliver-great-systems/templates/VALIDATION.md +95 -0
- package/deliver-great-systems/templates/claude-md.md +74 -0
- package/deliver-great-systems/templates/codebase/architecture.md +257 -0
- package/deliver-great-systems/templates/codebase/concerns.md +312 -0
- package/deliver-great-systems/templates/codebase/conventions.md +309 -0
- package/deliver-great-systems/templates/codebase/integrations.md +282 -0
- package/deliver-great-systems/templates/codebase/stack.md +188 -0
- package/deliver-great-systems/templates/codebase/structure.md +287 -0
- package/deliver-great-systems/templates/codebase/testing.md +482 -0
- package/deliver-great-systems/templates/config.json +38 -0
- package/deliver-great-systems/templates/context.md +354 -0
- package/deliver-great-systems/templates/continue-here.md +80 -0
- package/deliver-great-systems/templates/debug-subagent-prompt.md +93 -0
- package/deliver-great-systems/templates/discovery.md +148 -0
- package/deliver-great-systems/templates/milestone-archive.md +125 -0
- package/deliver-great-systems/templates/milestone.md +117 -0
- package/deliver-great-systems/templates/phase-prompt.md +615 -0
- package/deliver-great-systems/templates/planner-subagent-prompt.md +119 -0
- package/deliver-great-systems/templates/project.md +186 -0
- package/deliver-great-systems/templates/requirements.md +233 -0
- package/deliver-great-systems/templates/research-project/ARCHITECTURE.md +206 -0
- package/deliver-great-systems/templates/research-project/FEATURES.md +149 -0
- package/deliver-great-systems/templates/research-project/PITFALLS.md +202 -0
- package/deliver-great-systems/templates/research-project/STACK.md +122 -0
- package/deliver-great-systems/templates/research-project/SUMMARY.md +172 -0
- package/deliver-great-systems/templates/research.md +554 -0
- package/deliver-great-systems/templates/retrospective.md +54 -0
- package/deliver-great-systems/templates/roadmap.md +204 -0
- package/deliver-great-systems/templates/state.md +178 -0
- package/deliver-great-systems/templates/summary-complex.md +59 -0
- package/deliver-great-systems/templates/summary-minimal.md +41 -0
- package/deliver-great-systems/templates/summary-standard.md +48 -0
- package/deliver-great-systems/templates/summary.md +253 -0
- package/deliver-great-systems/templates/user-setup.md +313 -0
- package/deliver-great-systems/templates/verification-report.md +324 -0
- package/deliver-great-systems/workflows/add-doc.md +151 -0
- package/deliver-great-systems/workflows/add-idea.md +96 -0
- package/deliver-great-systems/workflows/add-phase.md +120 -0
- package/deliver-great-systems/workflows/add-tests.md +359 -0
- package/deliver-great-systems/workflows/add-todo.md +162 -0
- package/deliver-great-systems/workflows/approve-spec.md +194 -0
- package/deliver-great-systems/workflows/audit-milestone.md +364 -0
- package/deliver-great-systems/workflows/audit-phase.md +462 -0
- package/deliver-great-systems/workflows/cancel-job.md +108 -0
- package/deliver-great-systems/workflows/check-todos.md +181 -0
- package/deliver-great-systems/workflows/cleanup.md +247 -0
- package/deliver-great-systems/workflows/codereview.md +526 -0
- package/deliver-great-systems/workflows/complete-milestone.md +1298 -0
- package/deliver-great-systems/workflows/consolidate-ideas.md +365 -0
- package/deliver-great-systems/workflows/create-milestone-job.md +177 -0
- package/deliver-great-systems/workflows/develop-idea.md +544 -0
- package/deliver-great-systems/workflows/diagnose-issues.md +231 -0
- package/deliver-great-systems/workflows/discovery-phase.md +301 -0
- package/deliver-great-systems/workflows/discuss-idea.md +263 -0
- package/deliver-great-systems/workflows/discuss-phase.md +733 -0
- package/deliver-great-systems/workflows/execute-phase.md +571 -0
- package/deliver-great-systems/workflows/execute-plan.md +592 -0
- package/deliver-great-systems/workflows/find-related-ideas.md +271 -0
- package/deliver-great-systems/workflows/health.md +173 -0
- package/deliver-great-systems/workflows/help.md +997 -0
- package/deliver-great-systems/workflows/import-spec.md +381 -0
- package/deliver-great-systems/workflows/init-product.md +767 -0
- package/deliver-great-systems/workflows/insert-phase.md +138 -0
- package/deliver-great-systems/workflows/list-docs.md +119 -0
- package/deliver-great-systems/workflows/list-ideas.md +154 -0
- package/deliver-great-systems/workflows/list-jobs.md +89 -0
- package/deliver-great-systems/workflows/list-phase-assumptions.md +192 -0
- package/deliver-great-systems/workflows/list-specs.md +101 -0
- package/deliver-great-systems/workflows/map-codebase.md +621 -0
- package/deliver-great-systems/workflows/new-milestone.md +591 -0
- package/deliver-great-systems/workflows/new-project.md +1113 -0
- package/deliver-great-systems/workflows/node-repair.md +94 -0
- package/deliver-great-systems/workflows/overlap-check.md +86 -0
- package/deliver-great-systems/workflows/pause-work.md +134 -0
- package/deliver-great-systems/workflows/plan-milestone-gaps.md +306 -0
- package/deliver-great-systems/workflows/plan-phase.md +698 -0
- package/deliver-great-systems/workflows/progress.md +386 -0
- package/deliver-great-systems/workflows/quick.md +845 -0
- package/deliver-great-systems/workflows/refine-spec.md +275 -0
- package/deliver-great-systems/workflows/reject-idea.md +109 -0
- package/deliver-great-systems/workflows/remove-doc.md +117 -0
- package/deliver-great-systems/workflows/remove-phase.md +163 -0
- package/deliver-great-systems/workflows/research-idea.md +325 -0
- package/deliver-great-systems/workflows/research-phase.md +81 -0
- package/deliver-great-systems/workflows/restore-idea.md +101 -0
- package/deliver-great-systems/workflows/resume-project.md +311 -0
- package/deliver-great-systems/workflows/rollback-job.md +130 -0
- package/deliver-great-systems/workflows/run-job.md +498 -0
- package/deliver-great-systems/workflows/search.md +130 -0
- package/deliver-great-systems/workflows/set-profile.md +83 -0
- package/deliver-great-systems/workflows/settings.md +470 -0
- package/deliver-great-systems/workflows/transition.md +563 -0
- package/deliver-great-systems/workflows/undo-consolidation.md +155 -0
- package/deliver-great-systems/workflows/update-idea.md +157 -0
- package/deliver-great-systems/workflows/update.md +242 -0
- package/deliver-great-systems/workflows/validate-phase.md +177 -0
- package/deliver-great-systems/workflows/verify-phase.md +253 -0
- package/deliver-great-systems/workflows/verify-work.md +671 -0
- package/deliver-great-systems/workflows/write-spec.md +450 -0
- package/hooks/dist/dgs-check-update.js +62 -0
- package/hooks/dist/dgs-context-monitor.js +141 -0
- package/hooks/dist/dgs-statusline.js +115 -0
- package/package.json +60 -0
- package/scripts/build-hooks.js +43 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migration — v1-to-v2 file structure migration
|
|
3
|
+
*
|
|
4
|
+
* Detects v1 DGS installs (single project at .planning/ root) and migrates
|
|
5
|
+
* them to v2 multi-project structure (.planning/projects/<slug>/) using git mv
|
|
6
|
+
* for history preservation.
|
|
7
|
+
*
|
|
8
|
+
* Entry point: cmdReposInitProduct detects v1 and offers migration.
|
|
9
|
+
* The workflow handles the user prompt; this module handles the moves.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { safeReadFile, execGit, isV2Install, generateSlugInternal, output, error } = require('./core.cjs');
|
|
15
|
+
const { writeReposMd } = require('./repos.cjs');
|
|
16
|
+
const { regenerateProjectsMd } = require('./projects.cjs');
|
|
17
|
+
const { writeConfigField } = require('./config.cjs');
|
|
18
|
+
const { getPlanningRoot, PROJECTS_DIR } = require('./paths.cjs');
|
|
19
|
+
|
|
20
|
+
// ─── v1 Detection ────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Detect whether cwd is a v1 DGS install.
|
|
24
|
+
*
|
|
25
|
+
* v1 marker: .planning/PROJECT.md exists at root WITHOUT PROJECTS.md or REPOS.md.
|
|
26
|
+
* If v1 detected, extracts project name from heading and generates slug.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} cwd - Working directory
|
|
29
|
+
* @returns {{ isV1: boolean, projectName?: string, slug?: string }}
|
|
30
|
+
*/
|
|
31
|
+
function detectV1Install(cwd) {
|
|
32
|
+
// v1 always uses .planning/ — intentionally hardcoded for v1 source detection
|
|
33
|
+
const projectMdPath = path.join(cwd, '.planning', 'PROJECT.md');
|
|
34
|
+
const projectsMdPath = path.join(cwd, '.planning', 'PROJECTS.md');
|
|
35
|
+
const reposMdPath = path.join(cwd, '.planning', 'REPOS.md');
|
|
36
|
+
|
|
37
|
+
// Check if PROJECT.md exists
|
|
38
|
+
const projectContent = safeReadFile(projectMdPath);
|
|
39
|
+
if (!projectContent) {
|
|
40
|
+
return { isV1: false };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check v2 markers — if either exists, it's already v2 (or partially migrated)
|
|
44
|
+
const projectsMdContent = safeReadFile(projectsMdPath);
|
|
45
|
+
if (projectsMdContent && projectsMdContent.startsWith('# Projects')) {
|
|
46
|
+
return { isV1: false };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const reposMdContent = safeReadFile(reposMdPath);
|
|
50
|
+
if (reposMdContent && reposMdContent.startsWith('# Repos')) {
|
|
51
|
+
return { isV1: false };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// It's v1 — extract project name from heading
|
|
55
|
+
let projectName = null;
|
|
56
|
+
|
|
57
|
+
// Try "# Project: Name" format first
|
|
58
|
+
const colonMatch = projectContent.match(/^#\s+Project:\s+(.+)$/m);
|
|
59
|
+
if (colonMatch) {
|
|
60
|
+
projectName = colonMatch[1].trim();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Try "# Project Name" format (no colon)
|
|
64
|
+
if (!projectName) {
|
|
65
|
+
const headingMatch = projectContent.match(/^#\s+(.+)$/m);
|
|
66
|
+
if (headingMatch) {
|
|
67
|
+
projectName = headingMatch[1].trim();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Fall back to directory name
|
|
72
|
+
if (!projectName) {
|
|
73
|
+
projectName = path.basename(cwd);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const slug = generateSlugInternal(projectName) || path.basename(cwd).toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
77
|
+
|
|
78
|
+
return { isV1: true, projectName, slug };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ─── Precondition Validation ─────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Validate that migration can proceed.
|
|
85
|
+
*
|
|
86
|
+
* Checks:
|
|
87
|
+
* 1. Not already a v2 install
|
|
88
|
+
* 2. .planning/PROJECT.md exists (v1 marker)
|
|
89
|
+
* 3. Git working tree is clean (no uncommitted changes)
|
|
90
|
+
*
|
|
91
|
+
* @param {string} cwd - Working directory
|
|
92
|
+
* @returns {{ valid: boolean, reason?: string }}
|
|
93
|
+
*/
|
|
94
|
+
function validateMigrationPreconditions(cwd) {
|
|
95
|
+
// Check if already v2
|
|
96
|
+
if (isV2Install(cwd)) {
|
|
97
|
+
return { valid: false, reason: 'Already a v2 install. Migration not needed.' };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if v1 marker exists — v1 always uses .planning/
|
|
101
|
+
const projectMdPath = path.join(cwd, '.planning', 'PROJECT.md');
|
|
102
|
+
if (!safeReadFile(projectMdPath)) {
|
|
103
|
+
return { valid: false, reason: 'No .planning/PROJECT.md found. Not a v1 install.' };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check git working tree is clean
|
|
107
|
+
const gitStatus = execGit(cwd, ['status', '--porcelain']);
|
|
108
|
+
if (gitStatus.exitCode !== 0) {
|
|
109
|
+
return { valid: false, reason: 'Not a git repository or git command failed.' };
|
|
110
|
+
}
|
|
111
|
+
if (gitStatus.stdout.trim().length > 0) {
|
|
112
|
+
return { valid: false, reason: 'Working tree has uncommitted changes. Please commit or stash before migration.' };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return { valid: true };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ─── Backup Tag ──────────────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a pre-migration backup tag for safe rollback.
|
|
122
|
+
*
|
|
123
|
+
* @param {string} cwd - Working directory
|
|
124
|
+
* @returns {{ tagged: boolean, reason?: string }}
|
|
125
|
+
*/
|
|
126
|
+
function createBackupTag(cwd) {
|
|
127
|
+
const result = execGit(cwd, ['tag', 'dgs-pre-v2-migration']);
|
|
128
|
+
if (result.exitCode !== 0) {
|
|
129
|
+
// Check if tag already exists or no git
|
|
130
|
+
if (result.stderr.includes('already exists')) {
|
|
131
|
+
return { tagged: false, reason: 'Tag dgs-pre-v2-migration already exists.' };
|
|
132
|
+
}
|
|
133
|
+
return { tagged: false, reason: result.stderr || 'Failed to create tag.' };
|
|
134
|
+
}
|
|
135
|
+
return { tagged: true };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ─── Migration Planning ─────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
// Directories to move (project-level, order: directories first)
|
|
141
|
+
const DIRS_TO_MOVE = ['phases', 'research', 'todos', 'quick', 'debug'];
|
|
142
|
+
|
|
143
|
+
// Files to move (project-level)
|
|
144
|
+
const FILES_TO_MOVE = ['PROJECT.md', 'REQUIREMENTS.md', 'ROADMAP.md', 'STATE.md'];
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Collect all migration move operations as a plan (pure computation, no side effects).
|
|
148
|
+
*
|
|
149
|
+
* Returns an array of { relSource, relTarget, isDir } for all items that exist
|
|
150
|
+
* and need moving. Directories are listed before files to maximize git rename detection.
|
|
151
|
+
*
|
|
152
|
+
* @param {string} cwd - Working directory
|
|
153
|
+
* @param {string} slug - Project slug for subfolder name
|
|
154
|
+
* @returns {{ moves: Array<{relSource: string, relTarget: string, isDir: boolean}>, targetDir: string }}
|
|
155
|
+
*/
|
|
156
|
+
function collectMigrationMoves(cwd, slug) {
|
|
157
|
+
// v1 always uses .planning/ — migration source is always the .planning directory
|
|
158
|
+
const planningDir = path.join(cwd, '.planning');
|
|
159
|
+
const targetDir = path.join(planningDir, PROJECTS_DIR, slug);
|
|
160
|
+
const moves = [];
|
|
161
|
+
|
|
162
|
+
// Directories first
|
|
163
|
+
for (const dir of DIRS_TO_MOVE) {
|
|
164
|
+
const sourcePath = path.join(planningDir, dir);
|
|
165
|
+
if (fs.existsSync(sourcePath)) {
|
|
166
|
+
moves.push({
|
|
167
|
+
relSource: path.join('.planning', dir),
|
|
168
|
+
relTarget: path.join('.planning', PROJECTS_DIR, slug, dir),
|
|
169
|
+
isDir: true,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Then files
|
|
175
|
+
for (const file of FILES_TO_MOVE) {
|
|
176
|
+
const sourcePath = path.join(planningDir, file);
|
|
177
|
+
if (fs.existsSync(sourcePath)) {
|
|
178
|
+
moves.push({
|
|
179
|
+
relSource: path.join('.planning', file),
|
|
180
|
+
relTarget: path.join('.planning', PROJECTS_DIR, slug, file),
|
|
181
|
+
isDir: false,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return { moves, targetDir };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Validate that all planned moves can succeed.
|
|
191
|
+
*
|
|
192
|
+
* Checks:
|
|
193
|
+
* - Each source exists on disk
|
|
194
|
+
* - Each target does NOT already exist (would cause git mv to fail)
|
|
195
|
+
*
|
|
196
|
+
* @param {string} cwd - Working directory
|
|
197
|
+
* @param {Array<{relSource: string, relTarget: string, isDir: boolean}>} moves - Planned moves
|
|
198
|
+
* @returns {{ valid: boolean, errors: string[] }}
|
|
199
|
+
*/
|
|
200
|
+
function validateMoves(cwd, moves) {
|
|
201
|
+
const errors = [];
|
|
202
|
+
|
|
203
|
+
for (const move of moves) {
|
|
204
|
+
const absSource = path.join(cwd, move.relSource);
|
|
205
|
+
if (!fs.existsSync(absSource)) {
|
|
206
|
+
errors.push('Source does not exist: ' + move.relSource);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const absTarget = path.join(cwd, move.relTarget);
|
|
210
|
+
if (fs.existsSync(absTarget)) {
|
|
211
|
+
errors.push('Target already exists: ' + move.relTarget);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return { valid: errors.length === 0, errors };
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ─── Core Migration ──────────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Perform the v1-to-v2 migration.
|
|
222
|
+
*
|
|
223
|
+
* Uses a dry-run-then-execute pattern:
|
|
224
|
+
* 1. Collect planned moves (collectMigrationMoves)
|
|
225
|
+
* 2. Validate all moves can succeed (validateMoves)
|
|
226
|
+
* 3. Execute moves with rollback on failure
|
|
227
|
+
* 4. Commit with diff.renameLimit=1000 for large projects
|
|
228
|
+
* 5. Create v2 marker files in a separate commit
|
|
229
|
+
*
|
|
230
|
+
* @param {string} cwd - Working directory
|
|
231
|
+
* @param {string} slug - Project slug for subfolder name
|
|
232
|
+
* @returns {{ migrated: boolean, slug: string, files_moved: string[], repos_created: boolean, project_created: boolean, error?: string, rollback?: boolean }}
|
|
233
|
+
*/
|
|
234
|
+
function migrateV1ToV2(cwd, slug) {
|
|
235
|
+
// v1 always uses .planning/ — migration operates on the .planning directory
|
|
236
|
+
const planningDir = path.join(cwd, '.planning');
|
|
237
|
+
|
|
238
|
+
// Step 1: Collect planned moves
|
|
239
|
+
const { moves, targetDir } = collectMigrationMoves(cwd, slug);
|
|
240
|
+
|
|
241
|
+
// Create the target project directory (needed before validation and git mv)
|
|
242
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
243
|
+
|
|
244
|
+
// Step 2: Validate all moves
|
|
245
|
+
const validation = validateMoves(cwd, moves);
|
|
246
|
+
if (!validation.valid) {
|
|
247
|
+
// Clean up created target directory
|
|
248
|
+
try { fs.rmdirSync(targetDir); } catch (_e) { /* ignore */ }
|
|
249
|
+
return {
|
|
250
|
+
migrated: false,
|
|
251
|
+
slug,
|
|
252
|
+
files_moved: [],
|
|
253
|
+
repos_created: false,
|
|
254
|
+
project_created: false,
|
|
255
|
+
error: 'Validation failed: ' + validation.errors.join('; '),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Step 3: Execute moves with rollback on failure
|
|
260
|
+
const filesMoved = [];
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
for (const move of moves) {
|
|
264
|
+
const result = execGit(cwd, ['mv', move.relSource, move.relTarget]);
|
|
265
|
+
if (result.exitCode !== 0) {
|
|
266
|
+
throw new Error('git mv failed for ' + move.relSource + ': ' + result.stderr);
|
|
267
|
+
}
|
|
268
|
+
filesMoved.push(move.isDir ? path.basename(move.relSource) + '/' : path.basename(move.relSource));
|
|
269
|
+
}
|
|
270
|
+
} catch (err) {
|
|
271
|
+
// Rollback: restore all files to pre-move state
|
|
272
|
+
execGit(cwd, ['checkout', 'HEAD', '--', '.']);
|
|
273
|
+
execGit(cwd, ['clean', '-fd', path.join('.planning', PROJECTS_DIR, slug)]);
|
|
274
|
+
return {
|
|
275
|
+
migrated: false,
|
|
276
|
+
slug,
|
|
277
|
+
files_moved: [],
|
|
278
|
+
repos_created: false,
|
|
279
|
+
project_created: false,
|
|
280
|
+
error: 'Migration failed: ' + err.message,
|
|
281
|
+
rollback: true,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Step 4: Commit the moves (git mv already stages files, no git add -A needed)
|
|
286
|
+
// Use diff.renameLimit=1000 to handle projects with many files
|
|
287
|
+
execGit(cwd, ['-c', 'diff.renameLimit=1000', 'commit', '-m', 'chore: migrate to DGS v2 multi-project structure']);
|
|
288
|
+
|
|
289
|
+
// Step 5: Post-migration setup — Create REPOS.md
|
|
290
|
+
const dirName = path.basename(cwd);
|
|
291
|
+
writeReposMd(cwd, [{ name: dirName, path: '.', url: '', description: '' }]);
|
|
292
|
+
|
|
293
|
+
// Post-migration setup: Set current_project in config.json
|
|
294
|
+
writeConfigField(cwd, 'current_project', slug);
|
|
295
|
+
|
|
296
|
+
// Post-migration setup: Create PROJECTS.md from migrated project state
|
|
297
|
+
regenerateProjectsMd(cwd);
|
|
298
|
+
|
|
299
|
+
// Commit post-migration setup (new files need git add -A)
|
|
300
|
+
execGit(cwd, ['add', '-A']);
|
|
301
|
+
execGit(cwd, ['commit', '-m', 'chore: create v2 marker files after migration']);
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
migrated: true,
|
|
305
|
+
slug,
|
|
306
|
+
files_moved: filesMoved,
|
|
307
|
+
repos_created: true,
|
|
308
|
+
project_created: true,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ─── CLI Command ─────────────────────────────────────────────────────────────
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* CLI entry point for migration.
|
|
316
|
+
* Called from repos migrate <slug> routing.
|
|
317
|
+
*
|
|
318
|
+
* @param {string} cwd - Working directory
|
|
319
|
+
* @param {string} slug - Project slug
|
|
320
|
+
* @param {boolean} raw - Raw output mode
|
|
321
|
+
*/
|
|
322
|
+
function cmdMigrateV1ToV2(cwd, slug, raw) {
|
|
323
|
+
// Validate preconditions
|
|
324
|
+
const preconditions = validateMigrationPreconditions(cwd);
|
|
325
|
+
if (!preconditions.valid) {
|
|
326
|
+
error(preconditions.reason);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Create backup tag
|
|
330
|
+
const tag = createBackupTag(cwd);
|
|
331
|
+
|
|
332
|
+
// Perform migration
|
|
333
|
+
const result = migrateV1ToV2(cwd, slug);
|
|
334
|
+
|
|
335
|
+
output({
|
|
336
|
+
...result,
|
|
337
|
+
backup_tag: tag.tagged ? 'dgs-pre-v2-migration' : null,
|
|
338
|
+
backup_tag_note: tag.tagged ? null : tag.reason,
|
|
339
|
+
}, raw);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ─── Exports ────────────────────────────────────────────────────────────────
|
|
343
|
+
|
|
344
|
+
module.exports = {
|
|
345
|
+
detectV1Install,
|
|
346
|
+
validateMigrationPreconditions,
|
|
347
|
+
createBackupTag,
|
|
348
|
+
collectMigrationMoves,
|
|
349
|
+
validateMoves,
|
|
350
|
+
migrateV1ToV2,
|
|
351
|
+
cmdMigrateV1ToV2,
|
|
352
|
+
};
|